From fd7f25b62734ecdb63ed59001ef69a1a34edc4b4 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 6 Feb 2013 09:51:40 +0000 Subject: [PATCH] libfuse: set close-on-exec flag on pipe file descriptors 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 | 5 +++++ configure.ac | 2 +- lib/fuse_lowlevel.c | 35 ++++++++++++++++++++++++++--------- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 247cd29..788ee04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-02-06 Miklos Szeredi + + * libfuse: set close-on-exec flag on pipe file descriptors. Patch + by Eric Wong + 2013-02-05 Miklos Szeredi * libfuse: fix fuse_get_context() in non fuse threads. Reported diff --git a/configure.ac b/configure.ac index 274ac70..7bf6553 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index b4ea0e3..e28cce3 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -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 */ -- 2.30.2