From 175862af7b0e111d3360b1fedaa13df55d9f5d61 Mon Sep 17 00:00:00 2001 From: James Youngman Date: Wed, 23 Dec 2015 22:45:18 +0000 Subject: [PATCH] xargs: Don't leak file descriptors over an exec boundary. To: address@hidden This fixes a bug reported by Kyle Sallee (by email, so there is no Savannah bug number for it). * xargs/xargs.c (fopen_cloexec_for_read_only): New function; like fopen (..., "r") but sets the resulting file to be closed on exec. (main): Remember any non-O_CLOEXEC file desciptors that were open on startup so that we don't get false positives later. (prep_child_for_exec): Call complain_about_leaky_fds. (main): Any file opened to support the -a option is marked close-on-exec. If we open /dev/tty to support the -p option, mark that file close-on-exec, too. * NEWS: mention this bugfix. --- NEWS | 5 +++++ xargs/xargs.c | 13 +++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index e04ac9b..5c429b3 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout) * Major changes in release 4.5.17-git, 2015-12-DD +** Bug Fixes: + +When the -a option of xargs is used, xargs no longer leaks a file +descriptor (fixing a bug reported by Kyle Sallee). + ** Translations Updated the Brazilian Portuguese and Serbian translations. diff --git a/xargs/xargs.c b/xargs/xargs.c index 2b0f8f2..bf130e0 100644 --- a/xargs/xargs.c +++ b/xargs/xargs.c @@ -65,6 +65,7 @@ /* find headers. */ #include "buildcmd.h" +#include "fdleak.h" #include "findutils-version.h" #if ENABLE_NLS @@ -366,6 +367,11 @@ smaller_of (size_t a, size_t b) } +static FILE* fopen_cloexec_for_read_only (const char *file_name) { + int fd = open_cloexec (file_name, O_RDONLY); + return (fd < 0) ? NULL : fdopen (fd, "r"); +} + int main (int argc, char **argv) @@ -387,6 +393,7 @@ main (int argc, char **argv) else set_program_name ("xargs"); + remember_non_cloexec_fds (); parent = getpid (); original_exit_value = EXIT_SUCCESS; @@ -678,7 +685,7 @@ main (int argc, char **argv) else { keep_stdin = 1; /* see prep_child_for_exec () */ - input_stream = fopen (input_file, "r"); + input_stream = fopen_cloexec_for_read_only (input_file); if (NULL == input_stream) { error (EXIT_FAILURE, errno, @@ -1075,7 +1082,7 @@ print_args (bool ask) if (!tty_stream) { - tty_stream = fopen ("/dev/tty", "r"); + tty_stream = fopen_cloexec_for_read_only ("/dev/tty"); if (!tty_stream) error (EXIT_FAILURE, errno, _("failed to open /dev/tty for reading")); @@ -1154,6 +1161,8 @@ set_slot_var (unsigned int n) static void prep_child_for_exec (void) { + complain_about_leaky_fds (); + /* The parent will call add_proc to allocate a slot. We do the same in the child to make sure we get the same value. -- 2.1.4