From 99fff8f15cb010ca675cbb4a8c055512a2556107 Mon Sep 17 00:00:00 2001 From: Stephane Chazelas Date: Tue, 23 May 2017 16:46:25 +0100 Subject: 41142: Ensure close-on-exec is passed to moved file descriptor --- ChangeLog | 5 +++++ Src/Modules/system.c | 30 ++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index af94f3e79..f4b17ea34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-05-23 Peter Stephenson + + * Stephane: 41142: Src/Modules/system.c: ensure close-on-exec is + applied to moved file descriptor. + 2017-05-22 Peter Stephenson * Marko Myllenen: 41087: Completion/Unix/Command/_kvno: Update diff --git a/Src/Modules/system.c b/Src/Modules/system.c index afaec262a..3eecd7e95 100644 --- a/Src/Modules/system.c +++ b/Src/Modules/system.c @@ -313,7 +313,7 @@ bin_sysopen(char *nam, char **args, Options ops, UNUSED(int func)) int flags = O_NOCTTY | append | ((append || write) ? (read ? O_RDWR : O_WRONLY) : O_RDONLY); char *opt, *ptr, *nextopt, *fdvar; - int o, fd, explicit = -1; + int o, fd, moved_fd, explicit = -1; mode_t perms = 0666; #if defined(FD_CLOEXEC) && !defined(O_CLOEXEC) int fdflags; @@ -376,22 +376,32 @@ bin_sysopen(char *nam, char **args, Options ops, UNUSED(int func)) zwarnnam(nam, "can't open file %s: %e", *args, errno); return 1; } - fd = (explicit > -1) ? redup(fd, explicit) : movefd(fd); - if (fd == -1) { + moved_fd = (explicit > -1) ? redup(fd, explicit) : movefd(fd); + if (moved_fd == -1) { zwarnnam(nam, "can't open file %s", *args); return 1; } -#if defined(FD_CLOEXEC) && !defined(O_CLOEXEC) +#ifdef FD_CLOEXEC +#ifdef O_CLOEXEC + /* + * the O_CLOEXEC is a flag attached to the *file descriptor*, not the + * *open file description* so it doesn't survive a dup(). If that flag was + * requested and the fd was moved, we need to reapply it to the moved fd + * even if the original one was open with O_CLOEXEC + */ + if ((flags & O_CLOEXEC) && fd != moved_fd) +#else if (fdflags) - fcntl(fd, F_SETFD, FD_CLOEXEC); -#endif +#endif /* O_CLOEXEC */ + fcntl(moved_fd, F_SETFD, FD_CLOEXEC); +#endif /* FD_CLOEXEC */ if (explicit == -1) { - fdtable[fd] = FDT_EXTERNAL; - setiparam(fdvar, fd); - /* if setting the variable failed, close fd to avoid leak */ + fdtable[moved_fd] = FDT_EXTERNAL; + setiparam(fdvar, moved_fd); + /* if setting the variable failed, close moved_fd to avoid leak */ if (errflag) - zclose(fd); + zclose(moved_fd); } return 0; -- cgit 1.4.1