diff options
| author | Paul Eggert | 2012-11-13 20:55:41 -0800 |
|---|---|---|
| committer | Paul Eggert | 2012-11-13 20:55:41 -0800 |
| commit | 73dcdb9f30cb94a3183db54d9b463370c3978d4d (patch) | |
| tree | 216d47d5bc96bce2a4ca87a57967b0e1c3c151f2 /src/w32.c | |
| parent | 9c3912d3d9aaa1e20e3f7168f5764695ad5e43fd (diff) | |
| download | emacs-73dcdb9f30cb94a3183db54d9b463370c3978d4d.tar.gz emacs-73dcdb9f30cb94a3183db54d9b463370c3978d4d.zip | |
Use faccessat, not access, when checking file permissions.
This fixes a bug that has been present in Emacs since its creation.
It was reported by Chris Torek in 1983 even before GNU Emacs existed,
which must set some sort of record. (Torek's bug report was against
a predecessor of GNU Emacs, but GNU Emacs happened to have the
same common flaw.) See Torek's Usenet posting
"setuid/setgid programs & Emacs" Article-I.D.: sri-arpa.858
Posted: Fri Apr 8 14:18:56 1983.
* .bzrignore: Add lib/fcntl.h.
* configure.ac (euidaccess): Remove check; gnulib does this for us now.
(gl_FCNTL_O_FLAGS): Define a dummy version.
* lib/at-func.c, lib/euidaccess.c, lib/faccessat.c, lib/fcntl.in.h:
* lib/getgroups.c, lib/group-member.c, lib/root-uid.h:
* lib/xalloc-oversized.h, m4/euidaccess.m4, m4/faccessat.m4:
* m4/fcntl_h.m4, m4/getgroups.m4, m4/group-member.m4:
New files, from gnulib.
* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
* admin/merge-gnulib (GNULIB_MODULES): Add faccessat.
(GNULIB_TOOL_FLAGS): Avoid at-internal, fchdir, malloc-posix,
openat-die, openat-h, save-cwd. Do not avoid fcntl-h.
Omit gnulib's m4/fcntl-o.m4.
* nt/inc/ms-w32.h (AT_FDCWD, AT_EACCESS): New symbols.
(access): Remove.
(faccessat): New macro.
* src/Makefile.in (LIB_EACCESS): New macro.
(LIBES): Use it.
* src/callproc.c (init_callproc):
* src/charset.c (init_charset):
* src/fileio.c (check_existing, check_executable, check_writable)
(Ffile_readable_p):
* src/lread.c (openp, load_path_check):
* src/process.c (allocate_pty):
* src/xrdb.c (file_p):
Use effective UID when checking permissions, not real UID.
* src/callproc.c (init_callproc):
* src/charset.c (init_charset):
* src/lread.c (load_path_check, init_lread):
Test whether directories are accessible, not merely whether they exist.
* src/conf_post.h (GNULIB_SUPPORT_ONLY_AT_FDCWD): New macro.
* src/fileio.c (check_existing, check_executable, check_writable)
(Ffile_readable_p):
Use symbolic names instead of integers for the flags, as they're
portable now.
(check_writable): New arg AMODE. All uses changed.
Set errno on failure.
(Ffile_readable_p): Use faccessat, not stat + open + close.
(Ffile_writable_p): No need to call check_existing + check_writable.
Just call check_writable and then look at errno. This saves a syscall.
dir should never be nil; replace an unnecessary runtime check
with an eassert. When checking the parent directory of a nonexistent
file, check that the directory is searchable as well as writable, as
we can't create files in unsearchable directories.
(file_directory_p): New function, which uses 'stat' on most platforms
but faccessat with D_OK (for efficiency) if WINDOWSNT.
(Ffile_directory_p, Fset_file_times): Use it.
(file_accessible_directory_p): New function, which uses a single
syscall for efficiency.
(Ffile_accessible_directory_p): Use it.
* src/xrdb.c (file_p): Use file_directory_p.
* src/lisp.h (file_directory_p, file_accessible_directory_p): New decls.
* src/lread.c (openp): When opening a file, use fstat rather than
stat, as that avoids a permissions race. When not opening a file,
use file_directory_p rather than stat.
(dir_warning): First arg is now a usage string, not a format.
Use errno. All uses changed.
* src/nsterm.m (ns_term_init): Remove unnecessary call to file-readable
that merely introduced a race.
* src/process.c, src/sysdep.c, src/term.c: All uses of '#ifdef O_NONBLOCK'
changed to '#if O_NONBLOCK', to accommodate gnulib O_* style,
and similarly for the other O_* flags.
* src/w32.c (sys_faccessat): Rename from sys_access and switch to
faccessat's API. All uses changed.
* src/xrdb.c: Do not include <sys/stat.h>; no longer needed.
(magic_db): Rename from magic_file_p.
(magic_db, search_magic_path): Return an XrmDatabase rather than a
char *, so that we don't have to test for file existence
separately from opening the file for reading. This removes a race
fixes a permission-checking problem, and simplifies the code.
All uses changed.
(file_p): Remove; no longer needed.
Fixes: debbugs:12632
Diffstat (limited to 'src/w32.c')
| -rw-r--r-- | src/w32.c | 18 |
1 files changed, 12 insertions, 6 deletions
| @@ -1597,7 +1597,7 @@ init_environment (char ** argv) | |||
| 1597 | see if it succeeds. But I think that's too much to ask. */ | 1597 | see if it succeeds. But I think that's too much to ask. */ |
| 1598 | 1598 | ||
| 1599 | /* MSVCRT's _access crashes with D_OK. */ | 1599 | /* MSVCRT's _access crashes with D_OK. */ |
| 1600 | if (tmp && sys_access (tmp, D_OK) == 0) | 1600 | if (tmp && sys_faccessat (AT_FDCWD, tmp, D_OK, AT_EACCESS) == 0) |
| 1601 | { | 1601 | { |
| 1602 | char * var = alloca (strlen (tmp) + 8); | 1602 | char * var = alloca (strlen (tmp) + 8); |
| 1603 | sprintf (var, "TMPDIR=%s", tmp); | 1603 | sprintf (var, "TMPDIR=%s", tmp); |
| @@ -2714,10 +2714,16 @@ logon_network_drive (const char *path) | |||
| 2714 | long file names. */ | 2714 | long file names. */ |
| 2715 | 2715 | ||
| 2716 | int | 2716 | int |
| 2717 | sys_access (const char * path, int mode) | 2717 | sys_faccessat (int dirfd, const char * path, int mode, int flags) |
| 2718 | { | 2718 | { |
| 2719 | DWORD attributes; | 2719 | DWORD attributes; |
| 2720 | 2720 | ||
| 2721 | if (dirfd != AT_FDCWD) | ||
| 2722 | { | ||
| 2723 | errno = EBADF; | ||
| 2724 | return -1; | ||
| 2725 | } | ||
| 2726 | |||
| 2721 | /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its | 2727 | /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its |
| 2722 | newer versions blow up when passed D_OK. */ | 2728 | newer versions blow up when passed D_OK. */ |
| 2723 | path = map_w32_filename (path, NULL); | 2729 | path = map_w32_filename (path, NULL); |
| @@ -2960,7 +2966,7 @@ sys_mktemp (char * template) | |||
| 2960 | { | 2966 | { |
| 2961 | int save_errno = errno; | 2967 | int save_errno = errno; |
| 2962 | p[0] = first_char[i]; | 2968 | p[0] = first_char[i]; |
| 2963 | if (sys_access (template, 0) < 0) | 2969 | if (sys_faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0) |
| 2964 | { | 2970 | { |
| 2965 | errno = save_errno; | 2971 | errno = save_errno; |
| 2966 | return template; | 2972 | return template; |
| @@ -4011,7 +4017,7 @@ symlink (char const *filename, char const *linkname) | |||
| 4011 | { | 4017 | { |
| 4012 | /* Non-absolute FILENAME is understood as being relative to | 4018 | /* Non-absolute FILENAME is understood as being relative to |
| 4013 | LINKNAME's directory. We need to prepend that directory to | 4019 | LINKNAME's directory. We need to prepend that directory to |
| 4014 | FILENAME to get correct results from sys_access below, since | 4020 | FILENAME to get correct results from sys_faccessat below, since |
| 4015 | otherwise it will interpret FILENAME relative to the | 4021 | otherwise it will interpret FILENAME relative to the |
| 4016 | directory where the Emacs process runs. Note that | 4022 | directory where the Emacs process runs. Note that |
| 4017 | make-symbolic-link always makes sure LINKNAME is a fully | 4023 | make-symbolic-link always makes sure LINKNAME is a fully |
| @@ -4025,10 +4031,10 @@ symlink (char const *filename, char const *linkname) | |||
| 4025 | strncpy (tem, linkfn, p - linkfn); | 4031 | strncpy (tem, linkfn, p - linkfn); |
| 4026 | tem[p - linkfn] = '\0'; | 4032 | tem[p - linkfn] = '\0'; |
| 4027 | strcat (tem, filename); | 4033 | strcat (tem, filename); |
| 4028 | dir_access = sys_access (tem, D_OK); | 4034 | dir_access = sys_faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS); |
| 4029 | } | 4035 | } |
| 4030 | else | 4036 | else |
| 4031 | dir_access = sys_access (filename, D_OK); | 4037 | dir_access = sys_faccessat (AT_FDCWD, filename, D_OK, AT_EACCESS); |
| 4032 | 4038 | ||
| 4033 | /* Since Windows distinguishes between symlinks to directories and | 4039 | /* Since Windows distinguishes between symlinks to directories and |
| 4034 | to files, we provide a kludgy feature: if FILENAME doesn't | 4040 | to files, we provide a kludgy feature: if FILENAME doesn't |