sort: file descriptor discipline

Use O_CLOEXEC when creating file descriptors, so that subsidiary
processes do not inherit file descriptors that they do not need.
This is helpful for ‘sort’, as it is a multithreaded program that
forks and execs.
* bootstrap.conf (gnulib_modules): Add mkostemp, open, pipe2.
* src/sort.c (create_temp_file): Open temporary file with O_CLOEXEC.
(stream_open): Open the stream with O_CLOEXEC.
(pipe_fork): Create the pipe with O_CLOEXEC.
(check_output): Open the output file with O_CLOEXEC.
(main): Use xfopen/xfclose to handle --files0-from, so that
O_CLOEXEC is used properly.  This is simpler anyway.
* tests/misc/sort-files0-from.pl: Adjust to change in diagnostic
wording.
This commit is contained in:
Paul Eggert 2017-08-17 08:03:57 -07:00
parent 72f1751f60
commit 717f1d02e1
3 changed files with 15 additions and 17 deletions

View File

@ -171,6 +171,7 @@ gnulib_modules="
mkdir-p
mkfifo
mknod
mkostemp
mkstemp
mktime
modechange
@ -180,11 +181,13 @@ gnulib_modules="
non-recursive-gnulib-prefix-hack
nproc
obstack
open
parse-datetime
pathmax
perl
physmem
pipe-posix
pipe2
posix-shell
posixtm
posixver

View File

@ -868,7 +868,7 @@ create_temp_file (int *pfd, bool survive_fd_exhaustion)
/* Create the temporary file in a critical section, to avoid races. */
cs = cs_enter ();
fd = mkstemp (file);
fd = mkostemp (file, O_CLOEXEC);
if (0 <= fd)
{
*temptail = node;
@ -951,7 +951,10 @@ stream_open (char const *file, char const *how)
fp = stdin;
}
else
fp = fopen (file, how);
{
int fd = open (file, O_RDONLY | O_CLOEXEC);
fp = fd < 0 ? NULL : fdopen (fd, how);
}
fadvise (fp, FADVISE_SEQUENTIAL);
}
else if (*how == 'w')
@ -1031,7 +1034,7 @@ pipe_fork (int pipefds[2], size_t tries)
pid_t pid IF_LINT ( = -1);
struct cs_status cs;
if (pipe (pipefds) < 0)
if (pipe2 (pipefds, O_CLOEXEC) < 0)
return -1;
/* At least NMERGE + 1 subprocesses are needed. More could be created, but
@ -3764,7 +3767,8 @@ check_output (char const *outfile)
{
if (outfile)
{
int outfd = open (outfile, O_WRONLY | O_CREAT | O_BINARY, MODE_RW_UGO);
int oflags = O_WRONLY | O_BINARY | O_CLOEXEC | O_CREAT;
int outfd = open (outfile, oflags, MODE_RW_UGO);
if (outfd < 0)
sort_die (_("open failed"), outfile);
move_fd_or_die (outfd, STDOUT_FILENO);
@ -4578,8 +4582,6 @@ main (int argc, char **argv)
if (files_from)
{
FILE *stream;
/* When using --files0-from=F, you may not specify any files
on the command-line. */
if (nfiles)
@ -4590,21 +4592,14 @@ main (int argc, char **argv)
usage (SORT_FAILURE);
}
if (STREQ (files_from, "-"))
stream = stdin;
else
{
stream = fopen (files_from, "r");
if (stream == NULL)
die (SORT_FAILURE, errno, _("cannot open %s for reading"),
quoteaf (files_from));
}
FILE *stream = xfopen (files_from, "r");
readtokens0_init (&tok);
if (! readtokens0 (stream, &tok) || fclose (stream) != 0)
if (! readtokens0 (stream, &tok))
die (SORT_FAILURE, 0, _("cannot read file names from %s"),
quoteaf (files_from));
xfclose (stream, files_from);
if (tok.n_tok)
{

View File

@ -37,7 +37,7 @@ my @Tests =
# missing input file
['missing', '--files0-from=missing', {EXIT=>2},
{ERR => "$prog: cannot open 'missing' for reading: "
{ERR => "$prog: open failed: missing: "
. "No such file or directory\n"}],
# input file name of '-'