summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-12-07 11:04:32 +0200
committerAvi Kivity <avi@redhat.com>2009-12-07 11:04:32 +0200
commit149d76049af52aa76f4665b6bc9bdbd5904a8588 (patch)
treee07c6dfe28f03438dff9bb07240a7534c010f990
parentMerge commit 'e9b2e81889d9877415710484b876ee57a42b0bcb' into upstream-merge (diff)
parentDon't leak file descriptors (diff)
downloadqemu-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.c22
-rw-r--r--block/qcow2-snapshot.c7
-rw-r--r--block/qcow2.c16
-rw-r--r--block/raw-posix.c6
-rw-r--r--block_int.h3
-rw-r--r--compatfd.c16
-rwxr-xr-xconfigure20
-rw-r--r--gdbstub.c6
-rw-r--r--hw/ide/core.c54
-rw-r--r--hw/ide/internal.h1
-rw-r--r--hw/virtio-blk.c13
-rw-r--r--kvm-all.c2
-rw-r--r--migration-tcp.c6
-rw-r--r--migration-unix.c6
-rw-r--r--net/socket.c8
-rw-r--r--osdep.c104
-rw-r--r--qemu-char.c8
-rw-r--r--qemu-common.h7
-rw-r--r--qemu-img.c4
-rw-r--r--qemu-sockets.c10
-rw-r--r--qemu_socket.h2
-rw-r--r--slirp/misc.c4
-rw-r--r--slirp/slirp.h4
-rw-r--r--slirp/socket.c2
-rw-r--r--slirp/tcp_subr.c2
-rw-r--r--slirp/udp.c4
-rw-r--r--vl.c13
-rw-r--r--vnc.c2
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;
}
diff --git a/configure b/configure
index d5f53f8b7..cc01192ac 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/gdbstub.c b/gdbstub.c
index ad7cdca85..b1c55d8a4 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -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)
diff --git a/kvm-all.c b/kvm-all.c
index 8de370a58..91db3bc16 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -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;
diff --git a/osdep.c b/osdep.c
index 5747ce547..0706fcd4e 100644
--- a/osdep.c
+++ b/osdep.c
@@ -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);
diff --git a/vl.c b/vl.c
index 71ad502ea..a292498c8 100644
--- a/vl.c
+++ b/vl.c
@@ -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, &current_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);
}
diff --git a/vnc.c b/vnc.c
index 2bb802469..32c467880 100644
--- a/vnc.c
+++ b/vnc.c
@@ -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);
}