summaryrefslogtreecommitdiff
path: root/m4
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2020-02-23 16:19:42 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2020-02-23 16:45:50 -0800
commit9d626dffc6ba62c0d7a1a5c712f576ed8684fd66 (patch)
tree6cc8fbe8e5bc02c3bb74139710814a0400e91a8a /m4
parentc4ca8219dd6b8f06e67a0b767475b1259653b8e0 (diff)
downloademacs-9d626dffc6ba62c0d7a1a5c712f576ed8684fd66.tar.gz
Add 'nofollow' flag to set-file-modes etc.
This avoids some race conditions (Bug#39683). E.g., if some other program changes a file to a symlink between the time Emacs creates the file and the time it changes the file’s permissions, using the new flag prevents Emacs from inadvertently changing the permissions of a victim in some completely unrelated directory. * admin/merge-gnulib (GNULIB_MODULES): Add fchmodat. * doc/lispref/files.texi (Testing Accessibility, Changing Files): * doc/lispref/os.texi (File Notifications): * etc/NEWS: Adjust documentation accordingly. * lib/chmodat.c, lib/fchmodat.c, lib/lchmod.c, m4/fchmodat.m4: * m4/lchmod.m4: New files, copied from Gnulib. * lib/gnulib.mk.in: Regenerate. * lisp/dired-aux.el (dired-do-chmod): * lisp/doc-view.el (doc-view-make-safe-dir): * lisp/emacs-lisp/autoload.el (autoload--save-buffer): * lisp/emacs-lisp/bytecomp.el (byte-compile-file): * lisp/eshell/em-pred.el (eshell-pred-file-mode): * lisp/files.el (backup-buffer-copy, copy-directory): * lisp/gnus/mail-source.el (mail-source-movemail): * lisp/gnus/mm-decode.el (mm-display-external): * lisp/gnus/nnmail.el (nnmail-write-region): * lisp/net/tramp-adb.el (tramp-adb-handle-file-local-copy) (tramp-adb-handle-write-region): * lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file-directly): * lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-write-region): * lisp/net/tramp.el (tramp-handle-write-region) (tramp-make-tramp-temp-file): * lisp/server.el (server-ensure-safe-dir): * lisp/url/url-util.el (url-make-private-file): When getting or setting file modes, avoid following symbolic links when the file is not supposed to be a symbolic link. * lisp/doc-view.el (doc-view-make-safe-dir): Omit no-longer-needed separate symlink test. * lisp/gnus/gnus-util.el (gnus-set-file-modes): * lisp/net/tramp.el (tramp-handle-file-modes): * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-set-file-modes): * src/fileio.c (symlink_nofollow_flag): New function. (Ffile_modes, Fset_file_modes): Support an optional FLAG arg. All C callers changed. * lisp/net/ange-ftp.el (ange-ftp-set-file-modes): * lisp/net/tramp-adb.el (tramp-adb-handle-set-file-modes): * lisp/net/tramp-sh.el (tramp-sh-handle-set-file-modes): * lisp/net/tramp-smb.el (tramp-smb-handle-set-file-modes): * lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-set-file-modes): Accept an optional FLAG arg that is currently ignored, and add a FIXME comment for it. * m4/gnulib-comp.m4: Regenerate.
Diffstat (limited to 'm4')
-rw-r--r--m4/fchmodat.m482
-rw-r--r--m4/gnulib-comp.m435
-rw-r--r--m4/lchmod.m431
3 files changed, 148 insertions, 0 deletions
diff --git a/m4/fchmodat.m4 b/m4/fchmodat.m4
new file mode 100644
index 00000000000..e3f2f048162
--- /dev/null
+++ b/m4/fchmodat.m4
@@ -0,0 +1,82 @@
+# fchmodat.m4 serial 4
+dnl Copyright (C) 2004-2020 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Written by Jim Meyering.
+
+AC_DEFUN([gl_FUNC_FCHMODAT],
+[
+ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_CHECK_FUNCS_ONCE([fchmodat lchmod])
+ if test $ac_cv_func_fchmodat != yes; then
+ HAVE_FCHMODAT=0
+ else
+ AC_CACHE_CHECK(
+ [whether fchmodat+AT_SYMLINK_NOFOLLOW works on non-symlinks],
+ [gl_cv_func_fchmodat_works],
+ [dnl This test fails on GNU/Linux with glibc 2.31 (but not on
+ dnl GNU/kFreeBSD nor GNU/Hurd) and Cygwin 2.9.
+ AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [
+ AC_INCLUDES_DEFAULT[
+ #include <fcntl.h>
+ #ifndef S_IRUSR
+ #define S_IRUSR 0400
+ #endif
+ #ifndef S_IWUSR
+ #define S_IWUSR 0200
+ #endif
+ #ifndef S_IRWXU
+ #define S_IRWXU 0700
+ #endif
+ #ifndef S_IRWXG
+ #define S_IRWXG 0070
+ #endif
+ #ifndef S_IRWXO
+ #define S_IRWXO 0007
+ #endif
+ ]],
+ [[
+ int permissive = S_IRWXU | S_IRWXG | S_IRWXO;
+ int desired = S_IRUSR | S_IWUSR;
+ static char const f[] = "conftest.fchmodat";
+ struct stat st;
+ if (creat (f, permissive) < 0)
+ return 1;
+ if (fchmodat (AT_FDCWD, f, desired, AT_SYMLINK_NOFOLLOW) != 0)
+ return 1;
+ if (stat (f, &st) != 0)
+ return 1;
+ return ! ((st.st_mode & permissive) == desired);
+ ]])],
+ [gl_cv_func_fchmodat_works=yes],
+ [gl_cv_func_fchmodat_works=no],
+ [case "$host_os" in
+ dnl Guess no on Linux with glibc and Cygwin, yes otherwise.
+ linux-gnu* | cygwin*) gl_cv_func_fchmodat_works="guessing no" ;;
+ *) gl_cv_func_fchmodat_works="$gl_cross_guess_normal" ;;
+ esac
+ ])
+ rm -f conftest.fchmodat])
+ case $gl_cv_func_fchmodat_works in
+ *yes) ;;
+ *)
+ AC_DEFINE([NEED_FCHMODAT_NONSYMLINK_FIX], [1],
+ [Define to 1 if fchmodat+AT_SYMLINK_NOFOLLOW does not work right on non-symlinks.])
+ REPLACE_FCHMODAT=1
+ ;;
+ esac
+ fi
+])
+
+# Prerequisites of lib/fchmodat.c.
+AC_DEFUN([gl_PREREQ_FCHMODAT],
+[
+ AC_CHECK_FUNCS_ONCE([lchmod])
+ :
+])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index fea32b544f9..1465ce811b8 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -82,6 +82,7 @@ AC_DEFUN([gl_EARLY],
# Code from module extensions:
# Code from module extern-inline:
# Code from module faccessat:
+ # Code from module fchmodat:
# Code from module fcntl:
# Code from module fcntl-h:
# Code from module fdopendir:
@@ -111,6 +112,7 @@ AC_DEFUN([gl_EARLY],
# Code from module inttypes-incomplete:
# Code from module largefile:
AC_REQUIRE([AC_SYS_LARGEFILE])
+ # Code from module lchmod:
# Code from module libc-config:
# Code from module limits-h:
# Code from module localtime-buffer:
@@ -255,6 +257,12 @@ AC_DEFUN([gl_INIT],
fi
gl_MODULE_INDICATOR([faccessat])
gl_UNISTD_MODULE_INDICATOR([faccessat])
+ gl_FUNC_FCHMODAT
+ if test $HAVE_FCHMODAT = 0 || test $REPLACE_FCHMODAT = 1; then
+ AC_LIBOBJ([fchmodat])
+ gl_PREREQ_FCHMODAT
+ fi
+ gl_SYS_STAT_MODULE_INDICATOR([fchmodat])
gl_FUNC_FCNTL
if test $HAVE_FCNTL = 0 || test $REPLACE_FCNTL = 1; then
AC_LIBOBJ([fcntl])
@@ -468,6 +476,7 @@ AC_DEFUN([gl_INIT],
gl_gnulib_enabled_getgroups=false
gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false
gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1=false
+ gl_gnulib_enabled_lchmod=false
gl_gnulib_enabled_21ee726a3540c09237a8e70c0baf7467=false
gl_gnulib_enabled_2049e887c7e5308faad27b3f894bb8c9=false
gl_gnulib_enabled_malloca=false
@@ -569,6 +578,18 @@ AC_DEFUN([gl_INIT],
fi
fi
}
+ func_gl_gnulib_m4code_lchmod ()
+ {
+ if ! $gl_gnulib_enabled_lchmod; then
+ gl_FUNC_LCHMOD
+ if test $HAVE_LCHMOD = 0; then
+ AC_LIBOBJ([lchmod])
+ gl_PREREQ_LCHMOD
+ fi
+ gl_SYS_STAT_MODULE_INDICATOR([lchmod])
+ gl_gnulib_enabled_lchmod=true
+ fi
+ }
func_gl_gnulib_m4code_21ee726a3540c09237a8e70c0baf7467 ()
{
if ! $gl_gnulib_enabled_21ee726a3540c09237a8e70c0baf7467; then
@@ -660,6 +681,15 @@ AC_DEFUN([gl_INIT],
if test $HAVE_FACCESSAT = 0 || test $REPLACE_FACCESSAT = 1; then
func_gl_gnulib_m4code_03e0aaad4cb89ca757653bd367a6ccb7
fi
+ if test $HAVE_FCHMODAT = 0; then
+ func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
+ fi
+ if test $HAVE_FCHMODAT = 0; then
+ func_gl_gnulib_m4code_lchmod
+ fi
+ if test $HAVE_FCHMODAT = 0; then
+ func_gl_gnulib_m4code_03e0aaad4cb89ca757653bd367a6ccb7
+ fi
if test $HAVE_FCNTL = 0 || test $REPLACE_FCNTL = 1; then
func_gl_gnulib_m4code_getdtablesize
fi
@@ -708,6 +738,7 @@ AC_DEFUN([gl_INIT],
AM_CONDITIONAL([gl_GNULIB_ENABLED_getgroups], [$gl_gnulib_enabled_getgroups])
AM_CONDITIONAL([gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36], [$gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36])
AM_CONDITIONAL([gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1], [$gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1])
+ AM_CONDITIONAL([gl_GNULIB_ENABLED_lchmod], [$gl_gnulib_enabled_lchmod])
AM_CONDITIONAL([gl_GNULIB_ENABLED_21ee726a3540c09237a8e70c0baf7467], [$gl_gnulib_enabled_21ee726a3540c09237a8e70c0baf7467])
AM_CONDITIONAL([gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9], [$gl_gnulib_enabled_2049e887c7e5308faad27b3f894bb8c9])
AM_CONDITIONAL([gl_GNULIB_ENABLED_malloca], [$gl_gnulib_enabled_malloca])
@@ -908,6 +939,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/execinfo.in.h
lib/explicit_bzero.c
lib/faccessat.c
+ lib/fchmodat.c
lib/fcntl.c
lib/fcntl.in.h
lib/fdopendir.c
@@ -946,6 +978,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/ignore-value.h
lib/intprops.h
lib/inttypes.in.h
+ lib/lchmod.c
lib/libc-config.h
lib/limits.in.h
lib/localtime-buffer.c
@@ -1058,6 +1091,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/extensions.m4
m4/extern-inline.m4
m4/faccessat.m4
+ m4/fchmodat.m4
m4/fcntl-o.m4
m4/fcntl.m4
m4/fcntl_h.m4
@@ -1083,6 +1117,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/include_next.m4
m4/inttypes.m4
m4/largefile.m4
+ m4/lchmod.m4
m4/limits-h.m4
m4/localtime-buffer.m4
m4/lstat.m4
diff --git a/m4/lchmod.m4 b/m4/lchmod.m4
new file mode 100644
index 00000000000..b9e8a97cb31
--- /dev/null
+++ b/m4/lchmod.m4
@@ -0,0 +1,31 @@
+#serial 7
+
+dnl Copyright (C) 2005-2006, 2008-2020 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+dnl Provide a replacement for lchmod on hosts that lack a working version.
+
+AC_DEFUN([gl_FUNC_LCHMOD],
+[
+ AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
+
+ dnl Persuade glibc <sys/stat.h> to declare lchmod().
+ AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+ AC_CHECK_FUNCS_ONCE([lchmod lstat])
+ if test "$ac_cv_func_lchmod" = no; then
+ HAVE_LCHMOD=0
+ fi
+])
+
+# Prerequisites of lib/lchmod.c.
+AC_DEFUN([gl_PREREQ_LCHMOD],
+[
+ AC_REQUIRE([AC_C_INLINE])
+ :
+])