From 606732d02e678161ff433040a21d54fc2ea8bb43 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 14 Mar 2012 19:30:46 +0000 Subject: [PATCH] Use O_CLOEXEC / SOCK_CLOEXEC for almost all file descriptors. The presumption is that all file descriptors should be created with the close-on-exec flag set. The only exception are file descriptors that we want passed through to exec'd subprocesses (mainly pipes and stdin/stdout/stderr). For open calls, we pass O_CLOEXEC as an extra flag, eg: fd = open ("foo", O_RDONLY|O_CLOEXEC); This is a Linux-ism, but using a macro we can easily make it portable. For sockets, similarly: sock = socket (..., SOCK_STREAM|SOCK_CLOEXEC, ...); For accepted sockets, we use the Linux accept4 system call which allows flags to be supplied, but we use the Gnulib 'accept4' module to make this portable. For dup, dup2, we use the Linux dup3 system call, and the Gnulib modules 'dup3' and 'cloexec'. --- bootstrap | 3 +++ cat/virt-ls.c | 6 +++++- daemon/9p.c | 2 +- daemon/checksum.c | 4 ++-- daemon/copy.c | 6 +++--- daemon/daemon.h | 4 ++++ daemon/dd.c | 8 ++++---- daemon/debug.c | 6 +++--- daemon/devsparts.c | 2 +- daemon/fallocate.c | 2 +- daemon/file.c | 20 ++++++++++---------- daemon/grep.c | 2 +- daemon/guestfsd.c | 12 ++++++------ daemon/headtail.c | 2 +- daemon/hexdump.c | 2 +- daemon/initrd.c | 2 +- daemon/link.c | 2 +- daemon/realpath.c | 8 +++++--- daemon/stat.c | 2 +- daemon/strings.c | 2 +- daemon/truncate.c | 2 +- daemon/upload.c | 8 ++++---- daemon/wc.c | 2 +- daemon/zero.c | 8 ++++---- fish/alloc.c | 2 +- fish/fish.c | 4 ++-- fish/fish.h | 8 ++++++++ fish/rc.c | 6 +++--- generator/generator_tests_c_api.ml | 10 +++++++--- src/appliance.c | 4 ++-- src/guestfs-internal.h | 8 ++++++++ src/inspect.c | 2 +- src/inspect_icon.c | 2 +- src/launch.c | 8 ++++---- src/proto.c | 6 +++--- tests/c-api/test-last-errno.c | 6 +++++- tests/c-api/test-user-cancel.c | 20 +++++++++++++++++++- 37 files changed, 129 insertions(+), 74 deletions(-) diff --git a/bootstrap b/bootstrap index 7efd83840..9c68b0fc1 100755 --- a/bootstrap +++ b/bootstrap @@ -44,11 +44,14 @@ gnulib_tool=$GNULIB_SRCDIR/gnulib-tool (cd daemon && mkdir -p tests lib && ../$gnulib_tool --update) modules=' +accept4 arpa_inet byteswap c-ctype +cloexec closeout connect +dup3 error filevercmp fsusage diff --git a/cat/virt-ls.c b/cat/virt-ls.c index b79afa310..3d3699ee9 100644 --- a/cat/virt-ls.c +++ b/cat/virt-ls.c @@ -36,6 +36,10 @@ #include "guestfs.h" #include "options.h" +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + /* Currently open libguestfs handle. */ guestfs_h *g; @@ -468,7 +472,7 @@ do_ls_R (const char *dir) /* The output of find0 is a \0-separated file. Turn each \0 into * a \n character. */ - fd = open (tmpfile, O_RDONLY); + fd = open (tmpfile, O_RDONLY|O_CLOEXEC); if (fd == -1) { perror (tmpfile); exit (EXIT_FAILURE); diff --git a/daemon/9p.c b/daemon/9p.c index 6243919d7..8c0eeb681 100644 --- a/daemon/9p.c +++ b/daemon/9p.c @@ -125,7 +125,7 @@ read_whole_file (const char *filename) size_t alloc = 0, size = 0; int fd; - fd = open (filename, O_RDONLY); + fd = open (filename, O_RDONLY|O_CLOEXEC); if (fd == -1) { perror (filename); return NULL; diff --git a/daemon/checksum.c b/daemon/checksum.c index be460f8a2..2cc4a2b64 100644 --- a/daemon/checksum.c +++ b/daemon/checksum.c @@ -95,7 +95,7 @@ do_checksum (const char *csumtype, const char *path) int fd; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { @@ -111,7 +111,7 @@ do_checksum_device (const char *csumtype, const char *device) { int fd; - fd = open (device, O_RDONLY); + fd = open (device, O_RDONLY|O_CLOEXEC); if (fd == -1) { reply_with_perror ("%s", device); return NULL; diff --git a/daemon/copy.c b/daemon/copy.c index 4bfbfa96a..e895fbd85 100644 --- a/daemon/copy.c +++ b/daemon/copy.c @@ -29,8 +29,8 @@ #include "daemon.h" #include "actions.h" -#define DEST_FILE_FLAGS O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666 -#define DEST_DEVICE_FLAGS O_WRONLY, 0 +#define DEST_FILE_FLAGS O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666 +#define DEST_DEVICE_FLAGS O_WRONLY|O_CLOEXEC, 0 /* NB: We cheat slightly by assuming that optargs_bitmask is * compatible for all four of the calls. This is true provided they @@ -78,7 +78,7 @@ copy (const char *src, const char *src_display, size = -1; /* Open source and destination. */ - src_fd = open (src, O_RDONLY); + src_fd = open (src, O_RDONLY|O_CLOEXEC); if (src_fd == -1) { reply_with_perror ("%s", src_display); return -1; diff --git a/daemon/daemon.h b/daemon/daemon.h index f3e77da56..b7c1fd8e1 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -30,6 +30,10 @@ #include "guestfs_protocol.h" +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + /*-- in guestfsd.c --*/ extern int verbose; diff --git a/daemon/dd.c b/daemon/dd.c index a98f7ae06..8bc4aaba0 100644 --- a/daemon/dd.c +++ b/daemon/dd.c @@ -79,14 +79,14 @@ do_copy_size (const char *src, const char *dest, int64_t ssize) int src_fd, dest_fd; if (STRPREFIX (src, "/dev/")) - src_fd = open (src, O_RDONLY); + src_fd = open (src, O_RDONLY | O_CLOEXEC); else { buf = sysroot_path (src); if (!buf) { reply_with_perror ("malloc"); return -1; } - src_fd = open (buf, O_RDONLY); + src_fd = open (buf, O_RDONLY | O_CLOEXEC); free (buf); } if (src_fd == -1) { @@ -95,7 +95,7 @@ do_copy_size (const char *src, const char *dest, int64_t ssize) } if (STRPREFIX (dest, "/dev/")) - dest_fd = open (dest, O_WRONLY); + dest_fd = open (dest, O_WRONLY | O_CLOEXEC); else { buf = sysroot_path (dest); if (!buf) { @@ -103,7 +103,7 @@ do_copy_size (const char *src, const char *dest, int64_t ssize) close (src_fd); return -1; } - dest_fd = open (buf, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666); + dest_fd = open (buf, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666); free (buf); } if (dest_fd == -1) { diff --git a/daemon/debug.c b/daemon/debug.c index 4e8d6625b..8be48ff82 100644 --- a/daemon/debug.c +++ b/daemon/debug.c @@ -466,7 +466,7 @@ debug_core_pattern (const char *subcmd, size_t argc, char *const *const argv) const size_t pattern_len = strlen(pattern); #define CORE_PATTERN "/proc/sys/kernel/core_pattern" - int fd = open (CORE_PATTERN, O_WRONLY); + int fd = open (CORE_PATTERN, O_WRONLY|O_CLOEXEC); if (fd == -1) { reply_with_perror ("open: " CORE_PATTERN); return NULL; @@ -532,7 +532,7 @@ debug_qtrace (const char *subcmd, size_t argc, char *const *const argv) return NULL; /* Note this doesn't do device name translation or check this is a device. */ - int fd = open (argv[0], O_RDONLY | O_DIRECT); + int fd = open (argv[0], O_RDONLY|O_DIRECT|O_CLOEXEC); if (fd == -1) { reply_with_perror ("qtrace: %s: open", argv[0]); return NULL; @@ -602,7 +602,7 @@ do_debug_upload (const char *filename, int mode) /* Not chrooted - this command lets you upload a file to anywhere * in the appliance. */ - int fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, mode); + int fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, mode); if (fd == -1) { int err = errno; diff --git a/daemon/devsparts.c b/daemon/devsparts.c index 6fb009787..1848c4f9c 100644 --- a/daemon/devsparts.c +++ b/daemon/devsparts.c @@ -68,7 +68,7 @@ foreach_block_device (block_dev_func_t func) * CD-ROM device even though we didn't request it. Try to * detect this by seeing if the device contains media. */ - int fd = open (dev_path, O_RDONLY); + int fd = open (dev_path, O_RDONLY|O_CLOEXEC); if (fd == -1) { perror (dev_path); continue; diff --git a/daemon/fallocate.c b/daemon/fallocate.c index bc744f59b..f98babfb2 100644 --- a/daemon/fallocate.c +++ b/daemon/fallocate.c @@ -45,7 +45,7 @@ do_fallocate64 (const char *path, int64_t len) int fd; CHROOT_IN; - fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY, 0666); + fd = open (path, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666); CHROOT_OUT; if (fd == -1) { reply_with_perror ("open: %s", path); diff --git a/daemon/file.c b/daemon/file.c index ef7b50c01..cdf6b1bc4 100644 --- a/daemon/file.c +++ b/daemon/file.c @@ -62,7 +62,7 @@ do_touch (const char *path) } CHROOT_IN; - fd = open (path, O_WRONLY | O_CREAT | O_NOCTTY, 0666); + fd = open (path, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666); CHROOT_OUT; if (fd == -1) { @@ -94,7 +94,7 @@ do_cat (const char *path) char *buf, *buf2; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { @@ -305,7 +305,7 @@ do_write_file (const char *path, const char *content, int size) } CHROOT_IN; - fd = open (path, O_WRONLY | O_TRUNC | O_CREAT | O_NOCTTY, 0666); + fd = open (path, O_WRONLY|O_TRUNC|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666); CHROOT_OUT; if (fd == -1) { @@ -333,7 +333,7 @@ do_write (const char *path, const char *content, size_t size) int fd; CHROOT_IN; - fd = open (path, O_WRONLY | O_TRUNC | O_CREAT | O_NOCTTY, 0666); + fd = open (path, O_WRONLY|O_TRUNC|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666); CHROOT_OUT; if (fd == -1) { @@ -361,7 +361,7 @@ do_write_append (const char *path, const char *content, size_t size) int fd; CHROOT_IN; - fd = open (path, O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY, 0666); + fd = open (path, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666); CHROOT_OUT; if (fd == -1) { @@ -391,7 +391,7 @@ do_read_file (const char *path, size_t *size_r) char *r; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { @@ -506,7 +506,7 @@ do_pread (const char *path, int count, int64_t offset, size_t *size_r) int fd; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { @@ -520,7 +520,7 @@ do_pread (const char *path, int count, int64_t offset, size_t *size_r) char * do_pread_device (const char *device, int count, int64_t offset, size_t *size_r) { - int fd = open (device, O_RDONLY); + int fd = open (device, O_RDONLY|O_CLOEXEC); if (fd == -1) { reply_with_perror ("open: %s", device); return NULL; @@ -561,7 +561,7 @@ do_pwrite (const char *path, const char *content, size_t size, int64_t offset) } CHROOT_IN; - fd = open (path, O_WRONLY); + fd = open (path, O_WRONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { @@ -581,7 +581,7 @@ do_pwrite_device (const char *device, const char *content, size_t size, return -1; } - int fd = open (device, O_WRONLY); + int fd = open (device, O_WRONLY|O_CLOEXEC); if (fd == -1) { reply_with_perror ("open: %s", device); return -1; diff --git a/daemon/grep.c b/daemon/grep.c index 3562f3691..285c48ecb 100644 --- a/daemon/grep.c +++ b/daemon/grep.c @@ -36,7 +36,7 @@ grep (const char *prog, const char *flag, const char *regex, const char *path) char **lines; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index ac89a2140..a7c111b0a 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -247,7 +247,7 @@ main (int argc, char *argv[]) copy_lvm (); /* Connect to virtio-serial channel. */ - int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR | O_CLOEXEC); + int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR|O_CLOEXEC); if (sock == -1) { fprintf (stderr, "\n" @@ -292,7 +292,7 @@ main (int argc, char *argv[]) static char * read_cmdline (void) { - int fd = open ("/proc/cmdline", O_RDONLY); + int fd = open ("/proc/cmdline", O_RDONLY|O_CLOEXEC); if (fd == -1) { perror ("/proc/cmdline"); return NULL; @@ -713,7 +713,7 @@ commandrvf (char **stdoutput, char **stderror, int flags, close (stdin_fd[1]); } else { /* Set stdin to /dev/null (ignore failure) */ - ignore_value (open ("/dev/null", O_RDONLY)); + ignore_value (open ("/dev/null", O_RDONLY|O_CLOEXEC)); } close (so_fd[0]); close (se_fd[0]); @@ -1079,7 +1079,7 @@ device_name_translation (char *device) { int fd; - fd = open (device, O_RDONLY); + fd = open (device, O_RDONLY|O_CLOEXEC); if (fd >= 0) { close_ok: close (fd); @@ -1094,12 +1094,12 @@ device_name_translation (char *device) return -1; device[5] = 'h'; /* /dev/hd (old IDE driver) */ - fd = open (device, O_RDONLY); + fd = open (device, O_RDONLY|O_CLOEXEC); if (fd >= 0) goto close_ok; device[5] = 'v'; /* /dev/vd (for virtio devices) */ - fd = open (device, O_RDONLY); + fd = open (device, O_RDONLY|O_CLOEXEC); if (fd >= 0) goto close_ok; diff --git a/daemon/headtail.c b/daemon/headtail.c index 83f3f5c02..ce59d1740 100644 --- a/daemon/headtail.c +++ b/daemon/headtail.c @@ -36,7 +36,7 @@ headtail (const char *prog, const char *flag, const char *n, const char *path) char **lines; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { diff --git a/daemon/hexdump.c b/daemon/hexdump.c index 369861357..7fa5fbd83 100644 --- a/daemon/hexdump.c +++ b/daemon/hexdump.c @@ -34,7 +34,7 @@ do_hexdump (const char *path) char *out, *err; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { diff --git a/daemon/initrd.c b/daemon/initrd.c index c1ef2d1c2..2ded14a67 100644 --- a/daemon/initrd.c +++ b/daemon/initrd.c @@ -126,7 +126,7 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r) struct stat statbuf; int fd; - fd = open (fullpath, O_RDONLY); + fd = open (fullpath, O_RDONLY|O_CLOEXEC); if (fd == -1) { reply_with_perror ("open: %s:%s", path, filename); rmdir (tmpdir); diff --git a/daemon/link.c b/daemon/link.c index a8162a297..c4cdfe1d6 100644 --- a/daemon/link.c +++ b/daemon/link.c @@ -63,7 +63,7 @@ do_readlinklist (const char *path, char *const *names) DECLARE_STRINGSBUF (ret); CHROOT_IN; - fd_cwd = open (path, O_RDONLY | O_DIRECTORY); + fd_cwd = open (path, O_RDONLY|O_DIRECTORY|O_CLOEXEC); CHROOT_OUT; if (fd_cwd == -1) { diff --git a/daemon/realpath.c b/daemon/realpath.c index 126ef1939..2d657a4cb 100644 --- a/daemon/realpath.c +++ b/daemon/realpath.c @@ -27,6 +27,8 @@ #include #include +#include "cloexec.h" + #include "daemon.h" #include "optgroups.h" #include "actions.h" @@ -88,7 +90,7 @@ do_case_sensitive_path (const char *path) /* 'fd_cwd' here is a surrogate for the current working directory, so * that we don't have to actually call chdir(2). */ - fd_cwd = open (sysroot, O_RDONLY | O_DIRECTORY); + fd_cwd = open (sysroot, O_RDONLY|O_DIRECTORY|O_CLOEXEC); if (fd_cwd == -1) { reply_with_perror ("%s", sysroot); return NULL; @@ -141,7 +143,7 @@ do_case_sensitive_path (const char *path) next += i; /* Is it a directory? Try going into it. */ - int fd2 = openat (fd_cwd, name, O_RDONLY | O_DIRECTORY); + int fd2 = openat (fd_cwd, name, O_RDONLY|O_DIRECTORY|O_CLOEXEC); int err = errno; close (fd_cwd); fd_cwd = fd2; @@ -195,7 +197,7 @@ find_path_element (int fd_cwd, char *name, size_t *name_len_ret) DIR *dir; struct dirent *d; - fd2 = dup (fd_cwd); /* because closedir will close it */ + fd2 = dup_cloexec (fd_cwd); /* because closedir will close it */ if (fd2 == -1) { reply_with_perror ("dup"); return -1; diff --git a/daemon/stat.c b/daemon/stat.c index 22592bb2d..f0055518a 100644 --- a/daemon/stat.c +++ b/daemon/stat.c @@ -147,7 +147,7 @@ do_lstatlist (const char *path, char *const *names) } CHROOT_IN; - path_fd = open (path, O_RDONLY | O_DIRECTORY); + path_fd = open (path, O_RDONLY|O_DIRECTORY|O_CLOEXEC); CHROOT_OUT; if (path_fd == -1) { diff --git a/daemon/strings.c b/daemon/strings.c index d94ac44eb..847b45c8e 100644 --- a/daemon/strings.c +++ b/daemon/strings.c @@ -41,7 +41,7 @@ do_strings_e (const char *encoding, const char *path) } CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { diff --git a/daemon/truncate.c b/daemon/truncate.c index 28d9ceb28..0c3731c82 100644 --- a/daemon/truncate.c +++ b/daemon/truncate.c @@ -35,7 +35,7 @@ do_truncate_size (const char *path, int64_t size) int r; CHROOT_IN; - fd = open (path, O_WRONLY | O_NOCTTY); + fd = open (path, O_WRONLY|O_NOCTTY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { diff --git a/daemon/upload.c b/daemon/upload.c index 2f3e5b5b7..f96148b47 100644 --- a/daemon/upload.c +++ b/daemon/upload.c @@ -114,7 +114,7 @@ upload (const char *filename, int flags, int64_t offset) int do_upload (const char *filename) { - return upload (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0); + return upload (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0); } /* Has one FileIn parameter. */ @@ -126,7 +126,7 @@ do_upload_offset (const char *filename, int64_t offset) return -1; } - return upload (filename, O_WRONLY|O_CREAT|O_NOCTTY, offset); + return upload (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, offset); } /* Has one FileOut parameter. */ @@ -139,7 +139,7 @@ do_download (const char *filename) is_dev = STRPREFIX (filename, "/dev/"); if (!is_dev) CHROOT_IN; - fd = open (filename, O_RDONLY); + fd = open (filename, O_RDONLY|O_CLOEXEC); if (!is_dev) CHROOT_OUT; if (fd == -1) { reply_with_perror ("%s", filename); @@ -222,7 +222,7 @@ do_download_offset (const char *filename, int64_t offset, int64_t size) is_dev = STRPREFIX (filename, "/dev/"); if (!is_dev) CHROOT_IN; - fd = open (filename, O_RDONLY); + fd = open (filename, O_RDONLY|O_CLOEXEC); if (!is_dev) CHROOT_OUT; if (fd == -1) { reply_with_perror ("%s", filename); diff --git a/daemon/wc.c b/daemon/wc.c index 5d35559c5..f27534699 100644 --- a/daemon/wc.c +++ b/daemon/wc.c @@ -35,7 +35,7 @@ wc (const char *flag, const char *path) int fd, flags, r; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { diff --git a/daemon/zero.c b/daemon/zero.c index 14ae7ddfd..c45088cdb 100644 --- a/daemon/zero.c +++ b/daemon/zero.c @@ -38,7 +38,7 @@ do_zero (const char *device) int fd; size_t i, offset; - fd = open (device, O_RDWR); + fd = open (device, O_RDWR|O_CLOEXEC); if (fd == -1) { reply_with_perror ("%s", device); return -1; @@ -105,7 +105,7 @@ do_zero_device (const char *device) return -1; uint64_t size = (uint64_t) ssize; - int fd = open (device, O_RDWR); + int fd = open (device, O_RDWR|O_CLOEXEC); if (fd == -1) { reply_with_perror ("%s", device); return -1; @@ -164,7 +164,7 @@ do_is_zero (const char *path) ssize_t r; CHROOT_IN; - fd = open (path, O_RDONLY); + fd = open (path, O_RDONLY|O_CLOEXEC); CHROOT_OUT; if (fd == -1) { @@ -200,7 +200,7 @@ do_is_zero_device (const char *device) char buf[1024*1024]; ssize_t r; - fd = open (device, O_RDONLY); + fd = open (device, O_RDONLY|O_CLOEXEC); if (fd == -1) { reply_with_perror ("open: %s", device); return -1; diff --git a/fish/alloc.c b/fish/alloc.c index 08790a7ec..b530254ec 100644 --- a/fish/alloc.c +++ b/fish/alloc.c @@ -76,7 +76,7 @@ alloc_disk (const char *filename, const char *size_str, int add, int sparse) return -1; } - fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC, 0666); + fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666); if (fd == -1) { perror (filename); return -1; diff --git a/fish/fish.c b/fish/fish.c index 8bfea3253..a83f7021c 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -501,7 +501,7 @@ main (int argc, char *argv[]) /* -f (file) parameter? */ if (file) { close (0); - if (open (file, O_RDONLY) == -1) { + if (open (file, O_RDONLY|O_CLOEXEC) == -1) { perror (file); exit (EXIT_FAILURE); } @@ -1436,7 +1436,7 @@ cleanup_readline (void) int fd; if (histfile[0] != '\0') { - fd = open (histfile, O_WRONLY|O_CREAT, 0644); + fd = open (histfile, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0644); if (fd == -1) { perror (histfile); return; diff --git a/fish/fish.h b/fish/fish.h index b4b05fe5b..e77f349a7 100644 --- a/fish/fish.h +++ b/fish/fish.h @@ -23,6 +23,14 @@ #include "fish-cmds.h" +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif + #ifdef HAVE_GETTEXT #include "gettext.h" #define _(str) dgettext(PACKAGE, (str)) diff --git a/fish/rc.c b/fish/rc.c index 52a2623d5..8674bdf46 100644 --- a/fish/rc.c +++ b/fish/rc.c @@ -223,7 +223,7 @@ rc_listen (void) pid = getpid (); create_sockpath (pid, sockpath, sizeof sockpath, &addr); - sock = socket (AF_UNIX, SOCK_STREAM, 0); + sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (sock == -1) { perror ("socket"); exit (EXIT_FAILURE); @@ -246,7 +246,7 @@ rc_listen (void) */ close_stdout (); - s = accept (sock, NULL, NULL); + s = accept4 (sock, NULL, NULL, SOCK_CLOEXEC); if (s == -1) perror ("accept"); else { @@ -351,7 +351,7 @@ rc_remote (int pid, const char *cmd, size_t argc, char *argv[], create_sockpath (pid, sockpath, sizeof sockpath, &addr); - sock = socket (AF_UNIX, SOCK_STREAM, 0); + sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (sock == -1) { perror ("socket"); return -1; diff --git a/generator/generator_tests_c_api.ml b/generator/generator_tests_c_api.ml index ab5a0e64e..6f28e3705 100644 --- a/generator/generator_tests_c_api.ml +++ b/generator/generator_tests_c_api.ml @@ -43,6 +43,10 @@ let rec generate_tests () = #include \"guestfs.h\" #include \"guestfs-internal.h\" +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + static guestfs_h *g; static int suppress_error = 0; @@ -191,7 +195,7 @@ int main (int argc, char *argv[]) guestfs_set_error_handler (g, print_error, NULL); filename = \"test1.img\"; - fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC, 0666); + fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666); if (fd == -1) { perror (filename); exit (EXIT_FAILURE); @@ -213,7 +217,7 @@ int main (int argc, char *argv[]) } filename = \"test2.img\"; - fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC, 0666); + fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666); if (fd == -1) { perror (filename); exit (EXIT_FAILURE); @@ -235,7 +239,7 @@ int main (int argc, char *argv[]) } filename = \"test3.img\"; - fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC, 0666); + fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666); if (fd == -1) { perror (filename); exit (EXIT_FAILURE); diff --git a/src/appliance.c b/src/appliance.c index 9d51d3dc6..e42bec459 100644 --- a/src/appliance.c +++ b/src/appliance.c @@ -379,7 +379,7 @@ check_for_cached_appliance (guestfs_h *g, garbage_collect_appliances (cachedir); /* Try to open and acquire a lock on the checksum file. */ - int fd = open (filename, O_RDONLY); + int fd = open (filename, O_RDONLY|O_CLOEXEC); if (fd == -1) return 0; #ifdef HAVE_FUTIMENS @@ -497,7 +497,7 @@ build_supermin_appliance (guestfs_h *g, /* Open and acquire write lock on checksum file. The file might * not exist, in which case we want to create it. */ - int fd = open (filename, O_WRONLY|O_CREAT, 0755); + int fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0755); if (fd == -1) { perrorf (g, "open: %s", filename); guestfs___remove_tmpdir (tmpcd); diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index ff17a223d..1943f1a93 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -24,6 +24,14 @@ #include +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif + #define STREQ(a,b) (strcmp((a),(b)) == 0) #define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0) #define STRNEQ(a,b) (strcmp((a),(b)) != 0) diff --git a/src/inspect.c b/src/inspect.c index 9672aff82..60c7dd444 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -762,7 +762,7 @@ guestfs___download_to_tmp (guestfs_h *g, struct inspect_fs *fs, goto error; } - fd = open (r, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0600); + fd = open (r, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0600); if (fd == -1) { perrorf (g, "open: %s", r); goto error; diff --git a/src/inspect_icon.c b/src/inspect_icon.c index 6cb5553f8..19acfb9cc 100644 --- a/src/inspect_icon.c +++ b/src/inspect_icon.c @@ -553,7 +553,7 @@ read_whole_file (guestfs_h *g, const char *filename, ssize_t r; struct stat statbuf; - fd = open (filename, O_RDONLY); + fd = open (filename, O_RDONLY|O_CLOEXEC); if (fd == -1) { perrorf (g, "open: %s", filename); return -1; diff --git a/src/launch.c b/src/launch.c index 1a7c8236a..1b9ca9b07 100644 --- a/src/launch.c +++ b/src/launch.c @@ -532,7 +532,7 @@ launch_appliance (guestfs_h *g) snprintf (guestfsd_sock, sizeof guestfsd_sock, "%s/guestfsd.sock", g->tmpdir); unlink (guestfsd_sock); - g->sock = socket (AF_UNIX, SOCK_STREAM, 0); + g->sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (g->sock == -1) { perrorf (g, "socket"); goto cleanup0; @@ -652,7 +652,7 @@ launch_appliance (guestfs_h *g) * qemu command line, again. */ if (qemu_supports (g, "-enable-kvm") && - is_openable (g, "/dev/kvm", O_RDWR)) + is_openable (g, "/dev/kvm", O_RDWR|O_CLOEXEC)) add_cmdline (g, "-enable-kvm"); } @@ -921,7 +921,7 @@ launch_appliance (guestfs_h *g) g->fd[0] = wfd[1]; /* stdin of child */ g->fd[1] = rfd[0]; /* stdout of child */ } else { - g->fd[0] = open ("/dev/null", O_RDWR); + g->fd[0] = open ("/dev/null", O_RDWR|O_CLOEXEC); if (g->fd[0] == -1) { perrorf (g, "open /dev/null"); goto cleanup1; @@ -1039,7 +1039,7 @@ connect_unix_socket (guestfs_h *g, const char *sockpath) if (g->verbose) guestfs___print_timestamped_message (g, "connecting to %s", sockpath); - g->sock = socket (AF_UNIX, SOCK_STREAM, 0); + g->sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (g->sock == -1) { perrorf (g, "socket"); return -1; diff --git a/src/proto.c b/src/proto.c index c9ddaca3b..bf3feaedb 100644 --- a/src/proto.c +++ b/src/proto.c @@ -780,7 +780,7 @@ guestfs___accept_from_daemon (guestfs_h *g) return -1; } if (FD_ISSET (g->sock, &rset2)) { - sock = accept (g->sock, NULL, NULL); + sock = accept4 (g->sock, NULL, NULL, SOCK_CLOEXEC); if (sock == -1) { if (errno == EINTR || errno == EAGAIN) continue; @@ -891,7 +891,7 @@ guestfs___send_file (guestfs_h *g, const char *filename) g->user_cancel = 0; - fd = open (filename, O_RDONLY); + fd = open (filename, O_RDONLY|O_CLOEXEC); if (fd == -1) { perrorf (g, "open: %s", filename); send_file_cancellation (g); @@ -1125,7 +1125,7 @@ guestfs___recv_file (guestfs_h *g, const char *filename) g->user_cancel = 0; - fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666); + fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666); if (fd == -1) { perrorf (g, "open: %s", filename); goto cancel; diff --git a/tests/c-api/test-last-errno.c b/tests/c-api/test-last-errno.c index 31a5c4de0..ab4479bee 100644 --- a/tests/c-api/test-last-errno.c +++ b/tests/c-api/test-last-errno.c @@ -31,6 +31,10 @@ #include "guestfs.h" +#ifndef O_CLOEXEC +#define O_CLOEXEC +#endif + int main (int argc, char *argv[]) { @@ -45,7 +49,7 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } - fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC, 0666); + fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666); if (fd == -1) { perror (filename); exit (EXIT_FAILURE); diff --git a/tests/c-api/test-user-cancel.c b/tests/c-api/test-user-cancel.c index 4908f953e..39763bf07 100644 --- a/tests/c-api/test-user-cancel.c +++ b/tests/c-api/test-user-cancel.c @@ -46,6 +46,10 @@ #include "guestfs.h" +#ifndef O_CLOEXEC +#define O_CLOEXEC +#endif + static const char *filename = "test.img"; static const off_t filesize = 1024*1024*1024; @@ -83,7 +87,7 @@ main (int argc, char *argv[]) } /* Create a test image and test data. */ - fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666); + fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666); if (fd == -1) { perror (filename); exit (EXIT_FAILURE); @@ -135,6 +139,13 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } + /* We don't want the pipe to be passed to subprocesses. */ + if (fcntl (fds[0], F_SETFD, FD_CLOEXEC) == -1 || + fcntl (fds[1], F_SETFD, FD_CLOEXEC) == -1) { + perror ("fcntl"); + exit (EXIT_FAILURE); + } + data.fd = fds[1]; snprintf (dev_fd, sizeof dev_fd, "/dev/fd/%d", fds[0]); @@ -196,6 +207,13 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } + /* We don't want the pipe to be passed to subprocesses. */ + if (fcntl (fds[0], F_SETFD, FD_CLOEXEC) == -1 || + fcntl (fds[1], F_SETFD, FD_CLOEXEC) == -1) { + perror ("fcntl"); + exit (EXIT_FAILURE); + } + data.fd = fds[0]; snprintf (dev_fd, sizeof dev_fd, "/dev/fd/%d", fds[1]);