Mercurial > hg > octave-lojdl > gnulib-hg
changeset 12027:b10ac4488b07
openat: allow return of fd 0
Partially reverts patch fc33350 from 2009-09-02.
* modules/chdir-long (Depends-on): Relax openat-safer to openat.
* modules/save-cwd (Depends-on): Replace fcntl-safer with
unistd-safer.
* lib/chdir-long.c (includes): Replace "fcntl--.h" with
<fcntl.h>; this module does not leak fds.
* lib/openat.c (includes): Do not use "fcntl_safer"; plain openat
must be allowed to return 0, leaving openat_safer to add the
safety.
(openat_permissive): Avoid writing to just-opened fd 2 if
restoring the current directory fails.
* lib/openat-die.c (openat_restore_fail): Add comment.
* lib/save-cwd.c (includes): Make "fcntl--.h" conditional.
(save_cwd): Guarantee safe fd, but without use of open_safer.
* tests/test-openat.c: New test.
* modules/openat-tests (Files, Makefile.am): Distribute and build
new file.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Sat, 19 Sep 2009 07:12:15 -0600 |
parents | 6e27d5a192d0 |
children | a65ac3b41872 |
files | ChangeLog lib/chdir-long.c lib/openat-die.c lib/openat.c lib/save-cwd.c modules/chdir-long modules/openat-tests modules/save-cwd tests/test-openat.c |
diffstat | 9 files changed, 116 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ 2009-09-19 Eric Blake <ebb9@byu.net> + openat: allow return of fd 0 + * modules/chdir-long (Depends-on): Relax openat-safer to openat. + * modules/save-cwd (Depends-on): Replace fcntl-safer with + unistd-safer. + * lib/chdir-long.c (includes): Replace "fcntl--.h" with + <fcntl.h>; this module does not leak fds. + * lib/openat.c (includes): Do not use "fcntl_safer"; plain openat + must be allowed to return 0, leaving openat_safer to add the + safety. + (openat_permissive): Avoid writing to just-opened fd 2 if + restoring the current directory fails. + * lib/openat-die.c (openat_restore_fail): Add comment. + * lib/save-cwd.c (includes): Make "fcntl--.h" conditional. + (save_cwd): Guarantee safe fd, but without use of open_safer. + * tests/test-openat.c: New test. + * modules/openat-tests (Files, Makefile.am): Distribute and build + new file. + relocatable-prog-wrapper: fix build * modules/relocatable-prog-wrapper (Files): Update name of canonicalize m4 file, broken on 2009-09-17.
--- a/lib/chdir-long.c +++ b/lib/chdir-long.c @@ -20,19 +20,23 @@ #include "chdir-long.h" +#include <assert.h> +#include <errno.h> +#include <fcntl.h> #include <stdlib.h> #include <stdbool.h> #include <string.h> -#include <errno.h> #include <stdio.h> -#include <assert.h> - -#include "fcntl--.h" #ifndef PATH_MAX # error "compile this file only if your system defines PATH_MAX" #endif +/* The results of openat() in this file are not leaked to any + single-threaded code that could use stdio. + FIXME - if the kernel ever adds support for multi-thread safety for + avoiding standard fds, then we should use openat_safer. */ + struct cd_buf { int fd;
--- a/lib/openat-die.c +++ b/lib/openat-die.c @@ -40,6 +40,11 @@ abort (); } + +/* Exit with an error about failure to restore the working directory + during an openat emulation. The caller must ensure that fd 2 is + not a just-opened fd, even when openat_safer is not in use. */ + void openat_restore_fail (int errnum) {
--- a/lib/openat.c +++ b/lib/openat.c @@ -28,13 +28,6 @@ #include "openat-priv.h" #include "save-cwd.h" -/* We can't use "fcntl--.h", so that openat_safer does not interfere. */ -#if GNULIB_FCNTL_SAFER -# include "fcntl-safer.h" -# undef open -# define open open_safer -#endif - /* Replacement for Solaris' openat function. <http://www.google.com/search?q=openat+site:docs.sun.com> First, try to simulate it via open ("/proc/self/fd/FD/FILE"). @@ -124,7 +117,13 @@ if (save_ok && restore_cwd (&saved_cwd) != 0) { if (! cwd_errno) - openat_restore_fail (errno); + { + /* Don't write a message to just-created fd 2. */ + saved_errno = errno; + if (err == STDERR_FILENO) + close (err); + openat_restore_fail (saved_errno); + } *cwd_errno = errno; } }
--- a/lib/save-cwd.c +++ b/lib/save-cwd.c @@ -1,6 +1,6 @@ /* save-cwd.c -- Save and restore current working directory. - Copyright (C) 1995, 1997, 1998, 2003, 2004, 2005, 2006 Free + Copyright (C) 1995, 1997, 1998, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -23,15 +23,21 @@ #include "save-cwd.h" #include <errno.h> +#include <fcntl.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <unistd.h> #include "chdir-long.h" -#include "fcntl--.h" +#include "unistd--.h" #include "xgetcwd.h" +#if GNULIB_FCNTL_SAFER +# include "fcntl--.h" +#else +# define GNULIB_FCNTL_SAFER 0 +#endif + /* On systems without the fchdir function (WOE), pretend that open always returns -1 so that save_cwd resorts to using xgetcwd. Since chdir_long requires fchdir, use chdir instead. */ @@ -70,6 +76,8 @@ cwd->name = NULL; cwd->desc = open (".", O_RDONLY); + if (!GNULIB_FCNTL_SAFER) + cwd->desc = fd_safer (cwd->desc); if (cwd->desc < 0) { cwd->name = xgetcwd ();
--- a/modules/chdir-long +++ b/modules/chdir-long @@ -10,7 +10,7 @@ atexit fchdir fcntl-h -openat-safer +openat memchr mempcpy memrchr
--- a/modules/openat-tests +++ b/modules/openat-tests @@ -1,5 +1,6 @@ Files: tests/test-rmdir.h +tests/test-openat.c tests/test-unlinkat.c Depends-on: @@ -8,6 +9,7 @@ AC_CHECK_FUNCS_ONCE([symlink]) Makefile.am: -TESTS += test-unlinkat -check_PROGRAMS += test-unlinkat +TESTS += test-openat test-unlinkat +check_PROGRAMS += test-openat test-unlinkat +test_openat_LDADD = $(LDADD) @LIBINTL@ test_unlinkat_LDADD = $(LDADD) @LIBINTL@
--- a/modules/save-cwd +++ b/modules/save-cwd @@ -8,9 +8,9 @@ Depends-on: chdir-long -fcntl-safer +stdbool +unistd-safer xgetcwd -stdbool configure.ac: gl_SAVE_CWD
new file mode 100644 --- /dev/null +++ b/tests/test-openat.c @@ -0,0 +1,60 @@ +/* Test that openat works. + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Eric Blake <ebb9@byu.net>, 2009. */ + +#include <config.h> + +#include <fcntl.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +int +main () +{ + /* FIXME - add more tests. For example, share /dev/null and + trailing slash tests with test-open, and do more checks for + proper fd handling. */ + + /* Check that even when *-safer modules are in use, plain openat can + land in fd 0. Do this test last, since it is destructive to + stdin. */ + ASSERT (close (STDIN_FILENO) == 0); + ASSERT (openat (AT_FDCWD, ".", O_RDONLY) == STDIN_FILENO); + { + int dfd = open (".", O_RDONLY); + ASSERT (STDIN_FILENO < dfd); + ASSERT (chdir ("..") == 0); + ASSERT (close (STDIN_FILENO) == 0); + ASSERT (openat (dfd, ".", O_RDONLY) == STDIN_FILENO); + ASSERT (close (dfd) == 0); + } + return 0; +}