libfuse: set close-on-exec flag on pipe file descriptors
authorEric Wong <normalperson@yhbt.net>
Wed, 6 Feb 2013 09:51:40 +0000 (09:51 +0000)
committerMiklos Szeredi <mszeredi@suse.cz>
Wed, 6 Feb 2013 15:30:47 +0000 (16:30 +0100)
The FUSE library may be used from any number of programs which
may also fork() + execve(), so set the close-on-exec flag to
avoid inadvertant leakage of pipe file descriptors.

While we're at it, attempt to use pipe2() since this is within a
(currently) Linux-only code path and pipe2() offers thread-safety.

ChangeLog
configure.ac
lib/fuse_lowlevel.c

index 247cd2910cf9fd4905a0172a9847008af169d4b1..788ee045e982c6c8043646d397b3b1cb08c432fd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-02-06  Miklos Szeredi <miklos@szeredi.hu>
+
+       * libfuse: set close-on-exec flag on pipe file descriptors.  Patch
+       by Eric Wong
+
 2013-02-05  Miklos Szeredi <miklos@szeredi.hu>
 
        * libfuse: fix fuse_get_context() in non fuse threads.  Reported
index 274ac70ad3b2919cc0ec69cb631889e0a183d189..7bf6553301307ff03ee5aba80557ca375cd58f94 100644 (file)
@@ -52,7 +52,7 @@ if test "$enable_mtab" = "no"; then
        AC_DEFINE(IGNORE_MTAB, 1, [Don't update /etc/mtab])
 fi
 
-AC_CHECK_FUNCS([fork setxattr fdatasync splice vmsplice utimensat])
+AC_CHECK_FUNCS([fork setxattr fdatasync splice vmsplice utimensat pipe2])
 AC_CHECK_FUNCS([posix_fallocate])
 AC_CHECK_MEMBERS([struct stat.st_atim])
 AC_CHECK_MEMBERS([struct stat.st_atimespec])
index b4ea0e39a36fa3d9b2d0c03b67cd3a530dd2373d..e28cce3d352fbb9eeb23feca6f694bed97c8e852 100644 (file)
@@ -483,6 +483,31 @@ static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp)
 }
 
 #ifdef HAVE_SPLICE
+#if !defined(HAVE_PIPE2) || !defined(O_CLOEXEC)
+static int fuse_pipe(int fds[2])
+{
+       int rv = pipe(fds);
+
+       if (rv == -1)
+               return rv;
+
+       if (fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 ||
+           fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1 ||
+           fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
+           fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
+               close(fds[0]);
+               close(fds[1]);
+               rv = -1;
+       }
+       return rv;
+}
+#else
+static int fuse_pipe(int fds[2])
+{
+       return pipe2(fds, O_CLOEXEC | O_NONBLOCK);
+}
+#endif
+
 static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f)
 {
        struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key);
@@ -493,20 +518,12 @@ static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f)
                if (llp == NULL)
                        return NULL;
 
-               res = pipe(llp->pipe);
+               res = fuse_pipe(llp->pipe);
                if (res == -1) {
                        free(llp);
                        return NULL;
                }
 
-               if (fcntl(llp->pipe[0], F_SETFL, O_NONBLOCK) == -1 ||
-                   fcntl(llp->pipe[1], F_SETFL, O_NONBLOCK) == -1) {
-                       close(llp->pipe[0]);
-                       close(llp->pipe[1]);
-                       free(llp);
-                       return NULL;
-               }
-
                /*
                 *the default size is 16 pages on linux
                 */