diff options
author | Avi Kivity <avi@redhat.com> | 2009-12-07 11:04:32 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-07 11:04:32 +0200 |
commit | 149d76049af52aa76f4665b6bc9bdbd5904a8588 (patch) | |
tree | e07c6dfe28f03438dff9bb07240a7534c010f990 | |
parent | Merge commit 'e9b2e81889d9877415710484b876ee57a42b0bcb' into upstream-merge (diff) | |
parent | Don't leak file descriptors (diff) | |
download | qemu-kvm-149d76049af52aa76f4665b6bc9bdbd5904a8588.tar.gz qemu-kvm-149d76049af52aa76f4665b6bc9bdbd5904a8588.tar.bz2 qemu-kvm-149d76049af52aa76f4665b6bc9bdbd5904a8588.zip |
Merge commit '40ff6d7e8dceca227e7f8a3e8e0d58b2c66d19b4' into upstream-merge
* commit '40ff6d7e8dceca227e7f8a3e8e0d58b2c66d19b4':
Don't leak file descriptors
qemu-img: There is more than one host device driver
qcow2: Fix some more qemu_malloc fallout
qcow2: Store exact backing format length
virtio-blk: Implement rerror option
ide: Implement rerror option
Conflicts:
posix-aio-compat.c
Extended qemu_set_cloexec() to compatfd.c.
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | block/qcow2-refcount.c | 22 | ||||
-rw-r--r-- | block/qcow2-snapshot.c | 7 | ||||
-rw-r--r-- | block/qcow2.c | 16 | ||||
-rw-r--r-- | block/raw-posix.c | 6 | ||||
-rw-r--r-- | block_int.h | 3 | ||||
-rw-r--r-- | compatfd.c | 16 | ||||
-rwxr-xr-x | configure | 20 | ||||
-rw-r--r-- | gdbstub.c | 6 | ||||
-rw-r--r-- | hw/ide/core.c | 54 | ||||
-rw-r--r-- | hw/ide/internal.h | 1 | ||||
-rw-r--r-- | hw/virtio-blk.c | 13 | ||||
-rw-r--r-- | kvm-all.c | 2 | ||||
-rw-r--r-- | migration-tcp.c | 6 | ||||
-rw-r--r-- | migration-unix.c | 6 | ||||
-rw-r--r-- | net/socket.c | 8 | ||||
-rw-r--r-- | osdep.c | 104 | ||||
-rw-r--r-- | qemu-char.c | 8 | ||||
-rw-r--r-- | qemu-common.h | 7 | ||||
-rw-r--r-- | qemu-img.c | 4 | ||||
-rw-r--r-- | qemu-sockets.c | 10 | ||||
-rw-r--r-- | qemu_socket.h | 2 | ||||
-rw-r--r-- | slirp/misc.c | 4 | ||||
-rw-r--r-- | slirp/slirp.h | 4 | ||||
-rw-r--r-- | slirp/socket.c | 2 | ||||
-rw-r--r-- | slirp/tcp_subr.c | 2 | ||||
-rw-r--r-- | slirp/udp.c | 4 | ||||
-rw-r--r-- | vl.c | 13 | ||||
-rw-r--r-- | vnc.c | 2 |
28 files changed, 277 insertions, 75 deletions
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 30266786d..54b19f86d 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -513,7 +513,11 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, l1_size2 = l1_size * sizeof(uint64_t); l1_allocated = 0; if (l1_table_offset != s->l1_table_offset) { - l1_table = qemu_mallocz(align_offset(l1_size2, 512)); + if (l1_size2 != 0) { + l1_table = qemu_mallocz(align_offset(l1_size2, 512)); + } else { + l1_table = NULL; + } l1_allocated = 1; if (bdrv_pread(s->hd, l1_table_offset, l1_table, l1_size2) != l1_size2) @@ -769,12 +773,16 @@ static int check_refcounts_l1(BlockDriverState *bs, l1_table_offset, l1_size2); /* Read L1 table entries from disk */ - l1_table = qemu_malloc(l1_size2); - if (bdrv_pread(s->hd, l1_table_offset, - l1_table, l1_size2) != l1_size2) - goto fail; - for(i = 0;i < l1_size; i++) - be64_to_cpus(&l1_table[i]); + if (l1_size2 == 0) { + l1_table = NULL; + } else { + l1_table = qemu_malloc(l1_size2); + if (bdrv_pread(s->hd, l1_table_offset, + l1_table, l1_size2) != l1_size2) + goto fail; + for(i = 0;i < l1_size; i++) + be64_to_cpus(&l1_table[i]); + } /* Do the actual checks */ for(i = 0; i < l1_size; i++) { diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c index 94cb83806..d63c7e17d 100644 --- a/block/qcow2-snapshot.c +++ b/block/qcow2-snapshot.c @@ -266,7 +266,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) sn->l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t)); sn->l1_size = s->l1_size; - l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t)); + if (s->l1_size != 0) { + l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t)); + } else { + l1_table = NULL; + } + for(i = 0; i < s->l1_size; i++) { l1_table[i] = cpu_to_be64(s->l1_table[i]); } diff --git a/block/qcow2.c b/block/qcow2.c index 3954cf139..984264b3e 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -124,12 +124,12 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset, #ifdef DEBUG_EXT printf("Qcow2: Got format extension %s\n", bs->backing_format); #endif - offset += ((ext.len + 7) & ~7); + offset = ((offset + ext.len + 7) & ~7); break; default: /* unknown magic -- just skip it */ - offset += ((ext.len + 7) & ~7); + offset = ((offset + ext.len + 7) & ~7); break; } } @@ -738,6 +738,7 @@ static int qcow_create2(const char *filename, int64_t total_size, int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; int ref_clusters, backing_format_len = 0; + int rounded_ext_bf_len = 0; QCowHeader header; uint64_t tmp, offset; QCowCreateState s1, *s = &s1; @@ -759,8 +760,9 @@ static int qcow_create2(const char *filename, int64_t total_size, if (backing_format) { ext_bf.magic = QCOW_EXT_MAGIC_BACKING_FORMAT; backing_format_len = strlen(backing_format); - ext_bf.len = (backing_format_len + 7) & ~7; - header_size += ((sizeof(ext_bf) + ext_bf.len + 7) & ~7); + ext_bf.len = backing_format_len; + rounded_ext_bf_len = (sizeof(ext_bf) + ext_bf.len + 7) & ~7; + header_size += rounded_ext_bf_len; } header.backing_file_offset = cpu_to_be64(header_size); backing_filename_len = strlen(backing_file); @@ -828,15 +830,15 @@ static int qcow_create2(const char *filename, int64_t total_size, if (backing_file) { if (backing_format_len) { char zero[16]; - int d = ext_bf.len - backing_format_len; + int padding = rounded_ext_bf_len - (ext_bf.len + sizeof(ext_bf)); memset(zero, 0, sizeof(zero)); cpu_to_be32s(&ext_bf.magic); cpu_to_be32s(&ext_bf.len); write(fd, &ext_bf, sizeof(ext_bf)); write(fd, backing_format, backing_format_len); - if (d>0) { - write(fd, zero, d); + if (padding > 0) { + write(fd, zero, padding); } } write(fd, backing_file, backing_filename_len); diff --git a/block/raw-posix.c b/block/raw-posix.c index 7446ca931..6dcc65189 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -155,7 +155,7 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, s->open_flags |= O_DSYNC; s->fd = -1; - fd = open(filename, s->open_flags, 0644); + fd = qemu_open(filename, s->open_flags, 0644); if (fd < 0) { ret = -errno; if (ret == -EROFS) @@ -1016,6 +1016,7 @@ static BlockDriver bdrv_host_device = { .bdrv_close = raw_close, .bdrv_create = hdev_create, .create_options = raw_create_options, + .no_zero_init = 1, .bdrv_flush = raw_flush, .bdrv_aio_readv = raw_aio_readv, @@ -1112,6 +1113,7 @@ static BlockDriver bdrv_host_floppy = { .bdrv_close = raw_close, .bdrv_create = hdev_create, .create_options = raw_create_options, + .no_zero_init = 1, .bdrv_flush = raw_flush, .bdrv_aio_readv = raw_aio_readv, @@ -1194,6 +1196,7 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_close = raw_close, .bdrv_create = hdev_create, .create_options = raw_create_options, + .no_zero_init = 1, .bdrv_flush = raw_flush, .bdrv_aio_readv = raw_aio_readv, @@ -1315,6 +1318,7 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_close = raw_close, .bdrv_create = hdev_create, .create_options = raw_create_options, + .no_zero_init = 1, .bdrv_flush = raw_flush, .bdrv_aio_readv = raw_aio_readv, diff --git a/block_int.h b/block_int.h index 907e86410..9a3b2e09d 100644 --- a/block_int.h +++ b/block_int.h @@ -117,6 +117,9 @@ struct BlockDriver { /* Returns number of errors in image, -errno for internal errors */ int (*bdrv_check)(BlockDriverState* bs); + /* Set if newly created images are not guaranteed to contain only zeros */ + int no_zero_init; + struct BlockDriver *next; }; diff --git a/compatfd.c b/compatfd.c index 594e4af8a..e87bb9e71 100644 --- a/compatfd.c +++ b/compatfd.c @@ -85,6 +85,9 @@ static int qemu_signalfd_compat(const sigset_t *mask) return -1; } + qemu_set_cloexec(fds[0]); + qemu_set_cloexec(fds[1]); + memcpy(&info->mask, mask, sizeof(*mask)); info->fd = fds[1]; @@ -104,8 +107,10 @@ int qemu_signalfd(const sigset_t *mask) int ret; ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8); - if (ret != -1) + if (ret != -1) { + qemu_set_cloexec(ret); return ret; + } #endif return qemu_signalfd_compat(mask); @@ -119,13 +124,20 @@ int qemu_eventfd(int *fds) ret = syscall(SYS_eventfd, 0); if (ret >= 0) { fds[0] = ret; + qemu_set_cloexec(ret); if ((fds[1] = dup(ret)) == -1) { close(ret); return -1; } + qemu_set_cloexec(fds[1]); return 0; } #endif - return pipe(fds); + ret = pipe(fds); + if (ret != -1) { + qemu_set_cloexec(fds[0]); + qemu_set_cloexec(fds[1]); + } + return ret; } @@ -1693,6 +1693,23 @@ if compile_prog "" "" ; then pipe2=yes fi +# check if accept4 is there +accept4=no +cat > $TMPC << EOF +#define _GNU_SOURCE +#include <sys/socket.h> +#include <stddef.h> + +int main(void) +{ + accept4(0, NULL, NULL, SOCK_CLOEXEC); + return 0; +} +EOF +if compile_prog "" "" ; then + accept4=yes +fi + # check if tee/splice is there. vmsplice was added same time. splice=no cat > $TMPC << EOF @@ -2170,6 +2187,9 @@ fi if test "$pipe2" = "yes" ; then echo "CONFIG_PIPE2=y" >> $config_host_mak fi +if test "$accept4" = "yes" ; then + echo "CONFIG_ACCEPT4=y" >> $config_host_mak +fi if test "$splice" = "yes" ; then echo "CONFIG_SPLICE=y" >> $config_host_mak fi @@ -2357,6 +2357,9 @@ static void gdb_accept(void) perror("accept"); return; } else if (fd >= 0) { +#ifndef _WIN32 + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif break; } } @@ -2386,6 +2389,9 @@ static int gdbserver_open(int port) perror("socket"); return -1; } +#ifndef _WIN32 + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif /* allow fast reuse */ val = 1; diff --git a/hw/ide/core.c b/hw/ide/core.c index 49bbdcde1..a5b00ae0d 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -61,8 +61,9 @@ static inline int media_is_cd(IDEState *s) } static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb); -static void ide_dma_restart(IDEState *s); +static void ide_dma_restart(IDEState *s, int is_read); static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret); +static int ide_handle_rw_error(IDEState *s, int error, int op); static void padstr(char *str, const char *src, int len) { @@ -407,8 +408,11 @@ static void ide_sector_read(IDEState *s) n = s->req_nb_sectors; ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); if (ret != 0) { - ide_rw_error(s); - return; + if (ide_handle_rw_error(s, -ret, + BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ)) + { + return; + } } ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read); ide_set_irq(s->bus); @@ -471,9 +475,10 @@ void ide_dma_error(IDEState *s) ide_set_irq(s->bus); } -static int ide_handle_write_error(IDEState *s, int error, int op) +static int ide_handle_rw_error(IDEState *s, int error, int op) { - BlockInterfaceErrorAction action = drive_get_on_error(s->bs, 0); + int is_read = (op & BM_STATUS_RETRY_READ); + BlockInterfaceErrorAction action = drive_get_on_error(s->bs, is_read); if (action == BLOCK_ERR_IGNORE) return 0; @@ -484,7 +489,7 @@ static int ide_handle_write_error(IDEState *s, int error, int op) s->bus->bmdma->status |= op; vm_stop(0); } else { - if (op == BM_STATUS_DMA_RETRY) { + if (op & BM_STATUS_DMA_RETRY) { dma_buf_commit(s, 0); ide_dma_error(s); } else { @@ -551,9 +556,11 @@ static void ide_read_dma_cb(void *opaque, int ret) int64_t sector_num; if (ret < 0) { - dma_buf_commit(s, 1); - ide_dma_error(s); - return; + if (ide_handle_rw_error(s, -ret, + BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ)) + { + return; + } } n = s->io_buffer_size >> 9; @@ -622,7 +629,7 @@ static void ide_sector_write(IDEState *s) ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); if (ret != 0) { - if (ide_handle_write_error(s, -ret, BM_STATUS_PIO_RETRY)) + if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY)) return; } @@ -658,16 +665,23 @@ static void ide_sector_write(IDEState *s) static void ide_dma_restart_bh(void *opaque) { BMDMAState *bm = opaque; + int is_read; qemu_bh_delete(bm->bh); bm->bh = NULL; + is_read = !!(bm->status & BM_STATUS_RETRY_READ); + if (bm->status & BM_STATUS_DMA_RETRY) { - bm->status &= ~BM_STATUS_DMA_RETRY; - ide_dma_restart(bmdma_active_if(bm)); + bm->status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ); + ide_dma_restart(bmdma_active_if(bm), is_read); } else if (bm->status & BM_STATUS_PIO_RETRY) { - bm->status &= ~BM_STATUS_PIO_RETRY; - ide_sector_write(bmdma_active_if(bm)); + bm->status &= ~(BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ); + if (is_read) { + ide_sector_read(bmdma_active_if(bm)); + } else { + ide_sector_write(bmdma_active_if(bm)); + } } } @@ -692,7 +706,7 @@ static void ide_write_dma_cb(void *opaque, int ret) int64_t sector_num; if (ret < 0) { - if (ide_handle_write_error(s, -ret, BM_STATUS_DMA_RETRY)) + if (ide_handle_rw_error(s, -ret, BM_STATUS_DMA_RETRY)) return; } @@ -2715,7 +2729,7 @@ static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb) } } -static void ide_dma_restart(IDEState *s) +static void ide_dma_restart(IDEState *s, int is_read) { BMDMAState *bm = s->bus->bmdma; ide_set_sector(s, bm->sector_num); @@ -2723,7 +2737,13 @@ static void ide_dma_restart(IDEState *s) s->io_buffer_size = 0; s->nsector = bm->nsector; bm->cur_addr = bm->addr; - bm->dma_cb = ide_write_dma_cb; + + if (is_read) { + bm->dma_cb = ide_read_dma_cb; + } else { + bm->dma_cb = ide_write_dma_cb; + } + ide_dma_start(s, bm->dma_cb); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 567616e13..f937daacf 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -464,6 +464,7 @@ struct IDEDeviceInfo { #define BM_STATUS_INT 0x04 #define BM_STATUS_DMA_RETRY 0x08 #define BM_STATUS_PIO_RETRY 0x10 +#define BM_STATUS_RETRY_READ 0x20 #define BM_CMD_START 0x01 #define BM_CMD_READ 0x08 diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index a93d20dfa..a2f063974 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -98,9 +98,11 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status) qemu_free(req); } -static int virtio_blk_handle_write_error(VirtIOBlockReq *req, int error) +static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, + int is_read) { - BlockInterfaceErrorAction action = drive_get_on_error(req->dev->bs, 0); + BlockInterfaceErrorAction action = + drive_get_on_error(req->dev->bs, is_read); VirtIOBlock *s = req->dev; if (action == BLOCK_ERR_IGNORE) @@ -122,12 +124,13 @@ static void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *req = opaque; - if (ret && (req->out->type & VIRTIO_BLK_T_OUT)) { - if (virtio_blk_handle_write_error(req, -ret)) + if (ret) { + int is_read = !(req->out->type & VIRTIO_BLK_T_OUT); + if (virtio_blk_handle_rw_error(req, -ret, is_read)) return; } - virtio_blk_req_complete(req, ret ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK); + virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); } static void virtio_blk_flush_complete(void *opaque, int ret) @@ -420,7 +420,7 @@ int kvm_init(int smp_cpus) s->slots[i].slot = i; s->vmfd = -1; - s->fd = open("/dev/kvm", O_RDWR); + s->fd = qemu_open("/dev/kvm", O_RDWR); if (s->fd == -1) { fprintf(stderr, "Could not access KVM kernel module: %m\n"); ret = -errno; diff --git a/migration-tcp.c b/migration-tcp.c index b77ed8762..2cfa8cba5 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -105,7 +105,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon, s->state = MIG_STATE_ACTIVE; s->mon = NULL; s->bandwidth_limit = bandwidth_limit; - s->fd = socket(PF_INET, SOCK_STREAM, 0); + s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (s->fd == -1) { qemu_free(s); return NULL; @@ -146,7 +146,7 @@ static void tcp_accept_incoming_migration(void *opaque) int c, ret; do { - c = accept(s, (struct sockaddr *)&addr, &addrlen); + c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); } while (c == -1 && socket_error() == EINTR); dprintf("accepted migration\n"); @@ -193,7 +193,7 @@ int tcp_start_incoming_migration(const char *host_port) return -EINVAL; } - s = socket(PF_INET, SOCK_STREAM, 0); + s = qemu_socket(PF_INET, SOCK_STREAM, 0); if (s == -1) return -socket_error(); diff --git a/migration-unix.c b/migration-unix.c index 7dd787cd9..783228b3b 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -104,7 +104,7 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon, s->state = MIG_STATE_ACTIVE; s->mon = NULL; s->bandwidth_limit = bandwidth_limit; - s->fd = socket(PF_UNIX, SOCK_STREAM, 0); + s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (s->fd < 0) { dprintf("Unable to open socket"); goto err_after_alloc; @@ -150,7 +150,7 @@ static void unix_accept_incoming_migration(void *opaque) int c, ret; do { - c = accept(s, (struct sockaddr *)&addr, &addrlen); + c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); } while (c == -1 && socket_error() == EINTR); dprintf("accepted migration\n"); @@ -191,7 +191,7 @@ int unix_start_incoming_migration(const char *path) dprintf("Attempting to start an incoming migration\n"); - sock = socket(PF_UNIX, SOCK_STREAM, 0); + sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { fprintf(stderr, "Could not open unix socket: %s\n", strerror(errno)); return -EINVAL; diff --git a/net/socket.c b/net/socket.c index 7331d87c6..5533737e4 100644 --- a/net/socket.c +++ b/net/socket.c @@ -161,7 +161,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) return -1; } - fd = socket(PF_INET, SOCK_DGRAM, 0); + fd = qemu_socket(PF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket(PF_INET, SOCK_DGRAM)"); return -1; @@ -355,7 +355,7 @@ static void net_socket_accept(void *opaque) for(;;) { len = sizeof(saddr); - fd = accept(s->fd, (struct sockaddr *)&saddr, &len); + fd = qemu_accept(s->fd, (struct sockaddr *)&saddr, &len); if (fd < 0 && errno != EINTR) { return; } else if (fd >= 0) { @@ -386,7 +386,7 @@ static int net_socket_listen_init(VLANState *vlan, s = qemu_mallocz(sizeof(NetSocketListenState)); - fd = socket(PF_INET, SOCK_STREAM, 0); + fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); return -1; @@ -427,7 +427,7 @@ static int net_socket_connect_init(VLANState *vlan, if (parse_host_port(&saddr, host_str) < 0) return -1; - fd = socket(PF_INET, SOCK_STREAM, 0); + fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); return -1; @@ -125,7 +125,7 @@ int qemu_create_pidfile(const char *filename) #ifndef _WIN32 int fd; - fd = open(filename, O_RDWR | O_CREAT, 0600); + fd = qemu_open(filename, O_RDWR | O_CREAT, 0600); if (fd == -1) return -1; @@ -205,11 +205,113 @@ int inet_aton(const char *cp, struct in_addr *ia) ia->s_addr = addr; return 1; } + +void qemu_set_cloexec(int fd) +{ +} + #else + void socket_set_nonblock(int fd) { int f; f = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, f | O_NONBLOCK); } + +void qemu_set_cloexec(int fd) +{ + int f; + f = fcntl(fd, F_GETFD); + fcntl(fd, F_SETFD, f | FD_CLOEXEC); +} + +#endif + +/* + * Opens a file with FD_CLOEXEC set + */ +int qemu_open(const char *name, int flags, ...) +{ + int ret; + int mode = 0; + + if (flags & O_CREAT) { + va_list ap; + + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + } + +#ifdef O_CLOEXEC + ret = open(name, flags | O_CLOEXEC, mode); +#else + ret = open(name, flags, mode); + if (ret >= 0) { + qemu_set_cloexec(ret); + } #endif + + return ret; +} + +#ifndef _WIN32 +/* + * Creates a pipe with FD_CLOEXEC set on both file descriptors + */ +int qemu_pipe(int pipefd[2]) +{ + int ret; + +#ifdef CONFIG_PIPE2 + ret = pipe2(pipefd, O_CLOEXEC); +#else + ret = pipe(pipefd); + if (ret == 0) { + qemu_set_cloexec(pipefd[0]); + qemu_set_cloexec(pipefd[1]); + } +#endif + + return ret; +} +#endif + +/* + * Opens a socket with FD_CLOEXEC set + */ +int qemu_socket(int domain, int type, int protocol) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socket(domain, type | SOCK_CLOEXEC, protocol); +#else + ret = socket(domain, type, protocol); + if (ret >= 0) { + qemu_set_cloexec(ret); + } +#endif + + return ret; +} + +/* + * Accept a connection and set FD_CLOEXEC + */ +int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + int ret; + +#ifdef CONFIG_ACCEPT4 + ret = accept4(s, addr, addrlen, SOCK_CLOEXEC); +#else + ret = accept(s, addr, addrlen); + if (ret >= 0) { + qemu_set_cloexec(ret); + } +#endif + + return ret; +} diff --git a/qemu-char.c b/qemu-char.c index e202585fd..da5c15c4f 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -620,7 +620,7 @@ static CharDriverState *qemu_chr_open_file_out(QemuOpts *opts) { int fd_out; - TFR(fd_out = open(qemu_opt_get(opts, "path"), + TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"), O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666)); if (fd_out < 0) return NULL; @@ -640,8 +640,8 @@ static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts) snprintf(filename_in, 256, "%s.in", filename); snprintf(filename_out, 256, "%s.out", filename); - TFR(fd_in = open(filename_in, O_RDWR | O_BINARY)); - TFR(fd_out = open(filename_out, O_RDWR | O_BINARY)); + TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY)); + TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY)); if (fd_in < 0 || fd_out < 0) { if (fd_in >= 0) close(fd_in); @@ -2101,7 +2101,7 @@ static void tcp_chr_accept(void *opaque) len = sizeof(saddr); addr = (struct sockaddr *)&saddr; } - fd = accept(s->listen_fd, addr, &len); + fd = qemu_accept(s->listen_fd, addr, &len); if (fd < 0 && errno != EINTR) { return; } else if (fd >= 0) { diff --git a/qemu-common.h b/qemu-common.h index 1cebbe304..5fbe0f9db 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -159,6 +159,13 @@ void *get_mmap_addr(unsigned long size); void qemu_mutex_lock_iothread(void); void qemu_mutex_unlock_iothread(void); +int qemu_open(const char *name, int flags, ...); +void qemu_set_cloexec(int fd); + +#ifndef _WIN32 +int qemu_pipe(int pipefd[2]); +#endif + /* Error handling. */ void QEMU_NORETURN hw_error(const char *fmt, ...) diff --git a/qemu-img.c b/qemu-img.c index 972843ab8..f19c6440e 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -743,7 +743,7 @@ static int img_convert(int argc, char **argv) if (n > bs_offset + bs_sectors - sector_num) n = bs_offset + bs_sectors - sector_num; - if (strcmp(drv->format_name, "host_device")) { + if (!drv->no_zero_init) { /* If the output image is being created as a copy on write image, assume that sectors which are unallocated in the input image are present in both the output's and input's base images (no @@ -776,7 +776,7 @@ static int img_convert(int argc, char **argv) If the output is to a host device, we also write out sectors that are entirely 0, since whatever data was already there is garbage, not 0s. */ - if (strcmp(drv->format_name, "host_device") == 0 || out_baseimg || + if (drv->no_zero_init || out_baseimg || is_allocated_sectors(buf1, n, &n1)) { if (bdrv_write(out_bs, sector_num, buf1, n1) < 0) error("error while writing"); diff --git a/qemu-sockets.c b/qemu-sockets.c index 8801453cb..8850516f2 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -160,7 +160,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset) getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, uaddr,INET6_ADDRSTRLEN,uport,32, NI_NUMERICHOST | NI_NUMERICSERV); - slisten = socket(e->ai_family, e->ai_socktype, e->ai_protocol); + slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); if (slisten < 0) { fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, inet_strfamily(e->ai_family), strerror(errno)); @@ -258,7 +258,7 @@ int inet_connect_opts(QemuOpts *opts) fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__); continue; } - sock = socket(e->ai_family, e->ai_socktype, e->ai_protocol); + sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); if (sock < 0) { fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, inet_strfamily(e->ai_family), strerror(errno)); @@ -351,7 +351,7 @@ int inet_dgram_opts(QemuOpts *opts) } /* create socket */ - sock = socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); + sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); if (sock < 0) { fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, inet_strfamily(peer->ai_family), strerror(errno)); @@ -505,7 +505,7 @@ int unix_listen_opts(QemuOpts *opts) const char *path = qemu_opt_get(opts, "path"); int sock, fd; - sock = socket(PF_UNIX, SOCK_STREAM, 0); + sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { perror("socket(unix)"); return -1; @@ -560,7 +560,7 @@ int unix_connect_opts(QemuOpts *opts) return -1; } - sock = socket(PF_UNIX, SOCK_STREAM, 0); + sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (sock < 0) { perror("socket(unix)"); return -1; diff --git a/qemu_socket.h b/qemu_socket.h index c253b3241..86bdbf53d 100644 --- a/qemu_socket.h +++ b/qemu_socket.h @@ -32,6 +32,8 @@ int inet_aton(const char *cp, struct in_addr *ia); #include "qemu-option.h" /* misc helpers */ +int qemu_socket(int domain, int type, int protocol); +int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); void socket_set_nonblock(int fd); int send_all(int fd, const void *buf, int len1); diff --git a/slirp/misc.c b/slirp/misc.c index e9f08fdac..c76ad8fef 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -132,7 +132,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty) addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || + if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || listen(s, 1) < 0) { lprint("Error: inet socket: %s\n", strerror(errno)); @@ -165,7 +165,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty) * Connect to the socket * XXX If any of these fail, we're in trouble! */ - s = socket(AF_INET, SOCK_STREAM, 0); + s = qemu_socket(AF_INET, SOCK_STREAM, 0); addr.sin_addr = loopback_addr; do { ret = connect(s, (struct sockaddr *)&addr, addrlen); diff --git a/slirp/slirp.h b/slirp/slirp.h index 9ef57ea39..98a26442a 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -197,6 +197,10 @@ int inet_aton(const char *cp, struct in_addr *ia); #include "bootp.h" #include "tftp.h" +/* osdep.c */ +int qemu_socket(int domain, int type, int protocol); + + struct Slirp { QTAILQ_ENTRY(Slirp) entry; diff --git a/slirp/socket.c b/slirp/socket.c index 207109c7e..cf6e6a957 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -626,7 +626,7 @@ tcp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr, addr.sin_addr.s_addr = haddr; addr.sin_port = hport; - if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || + if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) || (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || (listen(s,1) < 0)) { diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 04173450d..7851307fa 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -325,7 +325,7 @@ int tcp_fconnect(struct socket *so) DEBUG_CALL("tcp_fconnect"); DEBUG_ARG("so = %lx", (long )so); - if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) { + if( (ret = so->s = qemu_socket(AF_INET,SOCK_STREAM,0)) >= 0) { int opt, s=so->s; struct sockaddr_in addr; diff --git a/slirp/udp.c b/slirp/udp.c index a88b645cc..d6c39b97b 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -302,7 +302,7 @@ int udp_output(struct socket *so, struct mbuf *m, int udp_attach(struct socket *so) { - if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) { + if((so->s = qemu_socket(AF_INET,SOCK_DGRAM,0)) != -1) { so->so_expire = curtime + SO_EXPIRE; insque(so, &so->slirp->udb); } @@ -350,7 +350,7 @@ udp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr, if (!so) { return NULL; } - so->s = socket(AF_INET,SOCK_DGRAM,0); + so->s = qemu_socket(AF_INET,SOCK_DGRAM,0); so->so_expire = curtime + SO_EXPIRE; insque(so, &slirp->udb); @@ -1257,7 +1257,7 @@ static int hpet_start_timer(struct qemu_alarm_timer *t) struct hpet_info info; int r, fd; - fd = open("/dev/hpet", O_RDONLY); + fd = qemu_open("/dev/hpet", O_RDONLY); if (fd < 0) return -1; @@ -1306,7 +1306,7 @@ static int rtc_start_timer(struct qemu_alarm_timer *t) int rtc_fd; unsigned long current_rtc_freq = 0; - TFR(rtc_fd = open("/dev/rtc", O_RDONLY)); + TFR(rtc_fd = qemu_open("/dev/rtc", O_RDONLY)); if (rtc_fd < 0) return -1; ioctl(rtc_fd, RTC_IRQP_READ, ¤t_rtc_freq); @@ -2219,7 +2219,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, on_read_error = BLOCK_ERR_REPORT; if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { - if (1) { + if (type != IF_IDE && type != IF_VIRTIO) { fprintf(stderr, "rerror is no supported by this format\n"); return NULL; } @@ -3381,7 +3381,7 @@ static int qemu_event_init(void) int err; int fds[2]; - err = pipe(fds); + err = qemu_pipe(fds); if (err == -1) return -errno; @@ -5616,6 +5616,9 @@ int main(int argc, char **argv, char **envp) } else if (pid < 0) exit(1); + close(fds[0]); + qemu_set_cloexec(fds[1]); + setsid(); pid = fork(); @@ -6020,7 +6023,7 @@ int main(int argc, char **argv, char **envp) exit(1); chdir("/"); - TFR(fd = open("/dev/null", O_RDWR)); + TFR(fd = qemu_open("/dev/null", O_RDWR)); if (fd == -1) exit(1); } @@ -2247,7 +2247,7 @@ static void vnc_listen_read(void *opaque) /* Catch-up */ vga_hw_update(); - int csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); + int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); if (csock != -1) { vnc_connect(vs, csock); } |