aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorPaul Eggert2020-02-23 16:19:42 -0800
committerPaul Eggert2020-02-23 16:45:50 -0800
commit9d626dffc6ba62c0d7a1a5c712f576ed8684fd66 (patch)
tree6cc8fbe8e5bc02c3bb74139710814a0400e91a8a /lisp
parentc4ca8219dd6b8f06e67a0b767475b1259653b8e0 (diff)
downloademacs-9d626dffc6ba62c0d7a1a5c712f576ed8684fd66.tar.gz
emacs-9d626dffc6ba62c0d7a1a5c712f576ed8684fd66.zip
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 'lisp')
-rw-r--r--lisp/dired-aux.el3
-rw-r--r--lisp/doc-view.el4
-rw-r--r--lisp/emacs-lisp/autoload.el2
-rw-r--r--lisp/emacs-lisp/bytecomp.el2
-rw-r--r--lisp/eshell/em-pred.el2
-rw-r--r--lisp/files.el12
-rw-r--r--lisp/gnus/gnus-util.el4
-rw-r--r--lisp/gnus/mail-source.el2
-rw-r--r--lisp/gnus/mm-decode.el2
-rw-r--r--lisp/gnus/nnmail.el2
-rw-r--r--lisp/net/ange-ftp.el3
-rw-r--r--lisp/net/tramp-adb.el9
-rw-r--r--lisp/net/tramp-gvfs.el4
-rw-r--r--lisp/net/tramp-sh.el10
-rw-r--r--lisp/net/tramp-smb.el3
-rw-r--r--lisp/net/tramp-sudoedit.el6
-rw-r--r--lisp/net/tramp.el13
-rw-r--r--lisp/server.el2
-rw-r--r--lisp/url/url-util.el4
19 files changed, 51 insertions, 38 deletions
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 0069c1744dc..8f00317c2b0 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -409,7 +409,8 @@ has no effect on MS-Windows."
409 (set-file-modes 409 (set-file-modes
410 file 410 file
411 (if num-modes num-modes 411 (if num-modes num-modes
412 (file-modes-symbolic-to-number modes (file-modes file))))) 412 (file-modes-symbolic-to-number modes (file-modes file 'nofollow)))
413 'nofollow))
413 (dired-do-redisplay arg))) 414 (dired-do-redisplay arg)))
414 415
415;;;###autoload 416;;;###autoload
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 3788d797258..8b3d5527f08 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -683,8 +683,6 @@ at the top edge of the page moves to the previous page."
683 ;; time-window of loose permissions otherwise. 683 ;; time-window of loose permissions otherwise.
684 (with-file-modes #o0700 (make-directory dir)) 684 (with-file-modes #o0700 (make-directory dir))
685 (file-already-exists 685 (file-already-exists
686 (when (file-symlink-p dir)
687 (error "Danger: %s points to a symbolic link" dir))
688 ;; In case it was created earlier with looser rights. 686 ;; In case it was created earlier with looser rights.
689 ;; We could check the mode info returned by file-attributes, but it's 687 ;; We could check the mode info returned by file-attributes, but it's
690 ;; a pain to parse and it may not tell you what we want under 688 ;; a pain to parse and it may not tell you what we want under
@@ -694,7 +692,7 @@ at the top edge of the page moves to the previous page."
694 ;; sure we have write-access to the directory and that we own it, thus 692 ;; sure we have write-access to the directory and that we own it, thus
695 ;; closing a bunch of security holes. 693 ;; closing a bunch of security holes.
696 (condition-case error 694 (condition-case error
697 (set-file-modes dir #o0700) 695 (set-file-modes dir #o0700 'nofollow)
698 (file-error 696 (file-error
699 (error 697 (error
700 (format "Unable to use temporary directory %s: %s" 698 (format "Unable to use temporary directory %s: %s"
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index 785e350e0e5..e9f76583272 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -895,7 +895,7 @@ FILE's modification time."
895 (cons (lambda () (ignore-errors (delete-file tempfile))) 895 (cons (lambda () (ignore-errors (delete-file tempfile)))
896 kill-emacs-hook))) 896 kill-emacs-hook)))
897 (unless (= temp-modes desired-modes) 897 (unless (= temp-modes desired-modes)
898 (set-file-modes tempfile desired-modes)) 898 (set-file-modes tempfile desired-modes 'nofollow))
899 (write-region (point-min) (point-max) tempfile nil 1) 899 (write-region (point-min) (point-max) tempfile nil 1)
900 (backup-buffer) 900 (backup-buffer)
901 (rename-file tempfile buffer-file-name t)) 901 (rename-file tempfile buffer-file-name t))
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index fce5e4aed6d..24a36393b2e 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2008,7 +2008,7 @@ The value is non-nil if there were no errors, nil if errors."
2008 (delete-file tempfile))) 2008 (delete-file tempfile)))
2009 kill-emacs-hook))) 2009 kill-emacs-hook)))
2010 (unless (= temp-modes desired-modes) 2010 (unless (= temp-modes desired-modes)
2011 (set-file-modes tempfile desired-modes)) 2011 (set-file-modes tempfile desired-modes 'nofollow))
2012 (write-region (point-min) (point-max) tempfile nil 1) 2012 (write-region (point-min) (point-max) tempfile nil 1)
2013 ;; This has the intentional side effect that any 2013 ;; This has the intentional side effect that any
2014 ;; hard-links to target-file continue to 2014 ;; hard-links to target-file continue to
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index 04bf3ff8998..7219af45f54 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -478,7 +478,7 @@ that `ls -l' will show in the first column of its display."
478(defsubst eshell-pred-file-mode (mode) 478(defsubst eshell-pred-file-mode (mode)
479 "Return a test which tests that MODE pertains to the file." 479 "Return a test which tests that MODE pertains to the file."
480 `(lambda (file) 480 `(lambda (file)
481 (let ((modes (file-modes file))) 481 (let ((modes (file-modes file 'nofollow)))
482 (if modes 482 (if modes
483 (logand ,mode modes))))) 483 (logand ,mode modes)))))
484 484
diff --git a/lisp/files.el b/lisp/files.el
index 683f4a8ce7c..2e7694d7677 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -4672,6 +4672,7 @@ BACKUPNAME is the backup file name, which is the old file renamed."
4672 ;; Create temp files with strict access rights. It's easy to 4672 ;; Create temp files with strict access rights. It's easy to
4673 ;; loosen them later, whereas it's impossible to close the 4673 ;; loosen them later, whereas it's impossible to close the
4674 ;; time-window of loose permissions otherwise. 4674 ;; time-window of loose permissions otherwise.
4675 (let (nofollow-flag)
4675 (with-file-modes ?\700 4676 (with-file-modes ?\700
4676 (when (condition-case nil 4677 (when (condition-case nil
4677 ;; Try to overwrite old backup first. 4678 ;; Try to overwrite old backup first.
@@ -4682,6 +4683,7 @@ BACKUPNAME is the backup file name, which is the old file renamed."
4682 (when (file-exists-p to-name) 4683 (when (file-exists-p to-name)
4683 (delete-file to-name)) 4684 (delete-file to-name))
4684 (copy-file from-name to-name nil t t) 4685 (copy-file from-name to-name nil t t)
4686 (setq nofollow-flag 'nofollow)
4685 nil) 4687 nil)
4686 (file-already-exists t)) 4688 (file-already-exists t))
4687 ;; The file was somehow created by someone else between 4689 ;; The file was somehow created by someone else between
@@ -4694,7 +4696,7 @@ BACKUPNAME is the backup file name, which is the old file renamed."
4694 (with-demoted-errors 4696 (with-demoted-errors
4695 (set-file-extended-attributes to-name extended-attributes))) 4697 (set-file-extended-attributes to-name extended-attributes)))
4696 (and modes 4698 (and modes
4697 (set-file-modes to-name (logand modes #o1777))))) 4699 (set-file-modes to-name (logand modes #o1777) nofollow-flag)))))
4698 4700
4699(defvar file-name-version-regexp 4701(defvar file-name-version-regexp
4700 "\\(?:~\\|\\.~[-[:alnum:]:#@^._]+\\(?:~[[:digit:]]+\\)?~\\)" 4702 "\\(?:~\\|\\.~[-[:alnum:]:#@^._]+\\(?:~[[:digit:]]+\\)?~\\)"
@@ -5900,7 +5902,8 @@ into NEWNAME instead."
5900 ;; If default-directory is a remote directory, make sure we find its 5902 ;; If default-directory is a remote directory, make sure we find its
5901 ;; copy-directory handler. 5903 ;; copy-directory handler.
5902 (let ((handler (or (find-file-name-handler directory 'copy-directory) 5904 (let ((handler (or (find-file-name-handler directory 'copy-directory)
5903 (find-file-name-handler newname 'copy-directory)))) 5905 (find-file-name-handler newname 'copy-directory)))
5906 (follow parents))
5904 (if handler 5907 (if handler
5905 (funcall handler 'copy-directory directory 5908 (funcall handler 'copy-directory directory
5906 newname keep-time parents copy-contents) 5909 newname keep-time parents copy-contents)
@@ -5920,7 +5923,8 @@ into NEWNAME instead."
5920 (or parents (not (file-directory-p newname))) 5923 (or parents (not (file-directory-p newname)))
5921 (setq newname (concat newname 5924 (setq newname (concat newname
5922 (file-name-nondirectory directory)))) 5925 (file-name-nondirectory directory))))
5923 (make-directory (directory-file-name newname) parents))) 5926 (make-directory (directory-file-name newname) parents))
5927 (t (setq follow t)))
5924 5928
5925 ;; Copy recursively. 5929 ;; Copy recursively.
5926 (dolist (file 5930 (dolist (file
@@ -5941,7 +5945,7 @@ into NEWNAME instead."
5941 (let ((modes (file-modes directory)) 5945 (let ((modes (file-modes directory))
5942 (times (and keep-time (file-attribute-modification-time 5946 (times (and keep-time (file-attribute-modification-time
5943 (file-attributes directory))))) 5947 (file-attributes directory)))))
5944 (if modes (set-file-modes newname modes)) 5948 (if modes (set-file-modes newname modes (unless follow 'nofollow)))
5945 (if times (set-file-times newname times)))))) 5949 (if times (set-file-times newname times))))))
5946 5950
5947 5951
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index eb0fd2522d3..83a85161aa0 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -1601,10 +1601,10 @@ empty directories from OLD-PATH."
1601 (file-truename 1601 (file-truename
1602 (concat old-dir ".."))))))))) 1602 (concat old-dir "..")))))))))
1603 1603
1604(defun gnus-set-file-modes (filename mode) 1604(defun gnus-set-file-modes (filename mode &optional flag)
1605 "Wrapper for set-file-modes." 1605 "Wrapper for set-file-modes."
1606 (ignore-errors 1606 (ignore-errors
1607 (set-file-modes filename mode))) 1607 (set-file-modes filename mode flag)))
1608 1608
1609(defun gnus-rescale-image (image size) 1609(defun gnus-rescale-image (image size)
1610 "Rescale IMAGE to SIZE if possible. 1610 "Rescale IMAGE to SIZE if possible.
diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el
index f5b68789b85..acf35a376a9 100644
--- a/lisp/gnus/mail-source.el
+++ b/lisp/gnus/mail-source.el
@@ -695,7 +695,7 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff bfile)
695 mail-source-movemail-program 695 mail-source-movemail-program
696 nil errors nil from to))))) 696 nil errors nil from to)))))
697 (when (file-exists-p to) 697 (when (file-exists-p to)
698 (set-file-modes to mail-source-default-file-modes)) 698 (set-file-modes to mail-source-default-file-modes 'nofollow))
699 (if (and (or (not (buffer-modified-p errors)) 699 (if (and (or (not (buffer-modified-p errors))
700 (zerop (buffer-size errors))) 700 (zerop (buffer-size errors)))
701 (and (numberp result) 701 (and (numberp result)
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index 2dab278b373..96695aabfde 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -948,7 +948,7 @@ external if displayed external."
948 ;; The file is deleted after the viewer exists. If the users edits 948 ;; The file is deleted after the viewer exists. If the users edits
949 ;; the file, changes will be lost. Set file to read-only to make it 949 ;; the file, changes will be lost. Set file to read-only to make it
950 ;; clear. 950 ;; clear.
951 (set-file-modes file #o400) 951 (set-file-modes file #o400 'nofollow)
952 (message "Viewing with %s" method) 952 (message "Viewing with %s" method)
953 (cond 953 (cond
954 (needsterm 954 (needsterm
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index 6e01b5c4d0b..93e4b0e7a8f 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -1958,7 +1958,7 @@ If TIME is nil, then return the cutoff time for oldness instead."
1958 (let ((coding-system-for-write nnmail-file-coding-system) 1958 (let ((coding-system-for-write nnmail-file-coding-system)
1959 (file-name-coding-system nnmail-pathname-coding-system)) 1959 (file-name-coding-system nnmail-pathname-coding-system))
1960 (write-region start end filename append visit lockname) 1960 (write-region start end filename append visit lockname)
1961 (set-file-modes filename nnmail-default-file-modes))) 1961 (set-file-modes filename nnmail-default-file-modes 'nofollow)))
1962 1962
1963;;; 1963;;;
1964;;; Status functions 1964;;; Status functions
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index f28394260dd..e2d4d7dd057 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -4740,7 +4740,8 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4740 (setq ange-ftp-ls-cache-file nil) ;Stop confusing Dired. 4740 (setq ange-ftp-ls-cache-file nil) ;Stop confusing Dired.
4741 0) 4741 0)
4742 4742
4743(defun ange-ftp-set-file-modes (filename mode) 4743(defun ange-ftp-set-file-modes (filename mode &optional flag)
4744 flag ;; FIXME: Support 'nofollow'.
4744 (ange-ftp-call-chmod (list (format "%o" mode) filename))) 4745 (ange-ftp-call-chmod (list (format "%o" mode) filename)))
4745 4746
4746(defun ange-ftp-make-symbolic-link (&rest _arguments) 4747(defun ange-ftp-make-symbolic-link (&rest _arguments)
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index aa7fe147c20..96ef95dbe30 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -591,7 +591,8 @@ Emacs dired can't find files."
591 (ignore-errors (delete-file tmpfile)) 591 (ignore-errors (delete-file tmpfile))
592 (tramp-error 592 (tramp-error
593 v 'file-error "Cannot make local copy of file `%s'" filename)) 593 v 'file-error "Cannot make local copy of file `%s'" filename))
594 (set-file-modes tmpfile (logior (or (file-modes filename) 0) #o0400))) 594 (set-file-modes tmpfile (logior (or (file-modes filename) 0) #o0400)
595 'nofollow))
595 tmpfile))) 596 tmpfile)))
596 597
597(defun tramp-adb-handle-file-writable-p (filename) 598(defun tramp-adb-handle-file-writable-p (filename)
@@ -636,7 +637,8 @@ But handle the case, if the \"test\" command is not available."
636 (tmpfile (tramp-compat-make-temp-file filename))) 637 (tmpfile (tramp-compat-make-temp-file filename)))
637 (when (and append (file-exists-p filename)) 638 (when (and append (file-exists-p filename))
638 (copy-file filename tmpfile 'ok) 639 (copy-file filename tmpfile 'ok)
639 (set-file-modes tmpfile (logior (or (file-modes tmpfile) 0) #o0600))) 640 (set-file-modes tmpfile (logior (or (file-modes tmpfile) 0) #o0600)
641 'nofollow))
640 (tramp-run-real-handler 642 (tramp-run-real-handler
641 #'write-region (list start end tmpfile append 'no-message lockname)) 643 #'write-region (list start end tmpfile append 'no-message lockname))
642 (with-tramp-progress-reporter 644 (with-tramp-progress-reporter
@@ -665,8 +667,9 @@ But handle the case, if the \"test\" command is not available."
665 (tramp-message v 0 "Wrote %s" filename)) 667 (tramp-message v 0 "Wrote %s" filename))
666 (run-hooks 'tramp-handle-write-region-hook)))) 668 (run-hooks 'tramp-handle-write-region-hook))))
667 669
668(defun tramp-adb-handle-set-file-modes (filename mode) 670(defun tramp-adb-handle-set-file-modes (filename mode &optional flag)
669 "Like `set-file-modes' for Tramp files." 671 "Like `set-file-modes' for Tramp files."
672 flag ;; FIXME: Support 'nofollow'.
670 (with-parsed-tramp-file-name filename nil 673 (with-parsed-tramp-file-name filename nil
671 (tramp-flush-file-properties v localname) 674 (tramp-flush-file-properties v localname)
672 (tramp-adb-send-command-and-check v (format "chmod %o %s" mode localname)))) 675 (tramp-adb-send-command-and-check v (format "chmod %o %s" mode localname))))
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 762c4fe4b3b..79835804bc0 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1562,12 +1562,12 @@ If FILE-SYSTEM is non-nil, return file system attributes."
1562 (tramp-run-real-handler 1562 (tramp-run-real-handler
1563 #'rename-file (list filename newname ok-if-already-exists)))) 1563 #'rename-file (list filename newname ok-if-already-exists))))
1564 1564
1565(defun tramp-gvfs-handle-set-file-modes (filename mode) 1565(defun tramp-gvfs-handle-set-file-modes (filename mode &optional flag)
1566 "Like `set-file-modes' for Tramp files." 1566 "Like `set-file-modes' for Tramp files."
1567 (with-parsed-tramp-file-name filename nil 1567 (with-parsed-tramp-file-name filename nil
1568 (tramp-flush-file-properties v localname) 1568 (tramp-flush-file-properties v localname)
1569 (tramp-gvfs-send-command 1569 (tramp-gvfs-send-command
1570 v "gvfs-set-attribute" "-t" "uint32" 1570 v "gvfs-set-attribute" (if flag "-nt" "-t") "uint32"
1571 (tramp-gvfs-url-file-name (tramp-make-tramp-file-name v)) 1571 (tramp-gvfs-url-file-name (tramp-make-tramp-file-name v))
1572 "unix::mode" (number-to-string mode)))) 1572 "unix::mode" (number-to-string mode))))
1573 1573
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 5a3abc31ea6..f31d3615884 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1478,10 +1478,11 @@ of."
1478 ;; only if that agrees with the buffer's record. 1478 ;; only if that agrees with the buffer's record.
1479 (t (tramp-compat-time-equal-p mt tramp-time-doesnt-exist))))))))) 1479 (t (tramp-compat-time-equal-p mt tramp-time-doesnt-exist)))))))))
1480 1480
1481(defun tramp-sh-handle-set-file-modes (filename mode) 1481(defun tramp-sh-handle-set-file-modes (filename mode &optional flag)
1482 "Like `set-file-modes' for Tramp files." 1482 "Like `set-file-modes' for Tramp files."
1483 (with-parsed-tramp-file-name filename nil 1483 (with-parsed-tramp-file-name filename nil
1484 (tramp-flush-file-properties v localname) 1484 (tramp-flush-file-properties v localname)
1485 flag ;; FIXME: Support 'nofollow'.
1485 ;; FIXME: extract the proper text from chmod's stderr. 1486 ;; FIXME: extract the proper text from chmod's stderr.
1486 (tramp-barf-unless-okay 1487 (tramp-barf-unless-okay
1487 v 1488 v
@@ -2279,7 +2280,7 @@ the uid and gid from FILENAME."
2279 ;; We must change the ownership as local user. 2280 ;; We must change the ownership as local user.
2280 ;; Since this does not work reliable, we also 2281 ;; Since this does not work reliable, we also
2281 ;; give read permissions. 2282 ;; give read permissions.
2282 (set-file-modes tmpfile #o0777) 2283 (set-file-modes tmpfile #o0777 'nofollow)
2283 (tramp-set-file-uid-gid 2284 (tramp-set-file-uid-gid
2284 tmpfile 2285 tmpfile
2285 (tramp-get-remote-uid v 'integer) 2286 (tramp-get-remote-uid v 'integer)
@@ -3221,7 +3222,8 @@ STDERR can also be a file name."
3221 (delete-file tmpfile2))))) 3222 (delete-file tmpfile2)))))
3222 3223
3223 ;; Set proper permissions. 3224 ;; Set proper permissions.
3224 (set-file-modes tmpfile (tramp-default-file-modes filename)) 3225 (set-file-modes tmpfile (tramp-default-file-modes filename)
3226 'nofollow)
3225 ;; Set local user ownership. 3227 ;; Set local user ownership.
3226 (tramp-set-file-uid-gid tmpfile)) 3228 (tramp-set-file-uid-gid tmpfile))
3227 3229
@@ -3320,7 +3322,7 @@ STDERR can also be a file name."
3320 ;; handles permissions. 3322 ;; handles permissions.
3321 ;; Ensure that it is still readable. 3323 ;; Ensure that it is still readable.
3322 (when modes 3324 (when modes
3323 (set-file-modes tmpfile (logior (or modes 0) #o0400))) 3325 (set-file-modes tmpfile (logior (or modes 0) #o0400) 'nofollow))
3324 3326
3325 ;; This is a bit lengthy due to the different methods 3327 ;; This is a bit lengthy due to the different methods
3326 ;; possible for file transfer. First, we check whether the 3328 ;; possible for file transfer. First, we check whether the
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index f02be394a7b..95505ea101f 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1464,8 +1464,9 @@ component is used as the target of the symlink."
1464 (tramp-flush-connection-property v "process-name") 1464 (tramp-flush-connection-property v "process-name")
1465 (tramp-flush-connection-property v "process-buffer"))))))) 1465 (tramp-flush-connection-property v "process-buffer")))))))
1466 1466
1467(defun tramp-smb-handle-set-file-modes (filename mode) 1467(defun tramp-smb-handle-set-file-modes (filename mode &optional flag)
1468 "Like `set-file-modes' for Tramp files." 1468 "Like `set-file-modes' for Tramp files."
1469 flag ;; FIXME: Support 'nofollow'.
1469 (with-parsed-tramp-file-name filename nil 1470 (with-parsed-tramp-file-name filename nil
1470 (when (tramp-smb-get-cifs-capabilities v) 1471 (when (tramp-smb-get-cifs-capabilities v)
1471 (tramp-flush-file-properties v localname) 1472 (tramp-flush-file-properties v localname)
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index f258ad6b931..4654d633fab 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -463,8 +463,9 @@ the result will be a local, non-Tramp, file name."
463 (tramp-sudoedit-send-command 463 (tramp-sudoedit-send-command
464 v "test" "-r" (tramp-compat-file-name-unquote localname))))) 464 v "test" "-r" (tramp-compat-file-name-unquote localname)))))
465 465
466(defun tramp-sudoedit-handle-set-file-modes (filename mode) 466(defun tramp-sudoedit-handle-set-file-modes (filename mode &optional flag)
467 "Like `set-file-modes' for Tramp files." 467 "Like `set-file-modes' for Tramp files."
468 flag ;; FIXME: Support 'nofollow'.
468 (with-parsed-tramp-file-name filename nil 469 (with-parsed-tramp-file-name filename nil
469 (tramp-flush-file-properties v localname) 470 (tramp-flush-file-properties v localname)
470 (unless (tramp-sudoedit-send-command 471 (unless (tramp-sudoedit-send-command
@@ -735,7 +736,8 @@ ID-FORMAT valid values are `string' and `integer'."
735 (file-attributes filename 'integer)) 736 (file-attributes filename 'integer))
736 gid)) 737 gid))
737 (tramp-set-file-uid-gid filename uid gid)) 738 (tramp-set-file-uid-gid filename uid gid))
738 (set-file-modes filename modes))))) 739 (set-file-modes filename modes
740 (when (eq mustbenew 'excl) 'nofollow))))))
739 741
740 742
741;; Internal functions. 743;; Internal functions.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 409e1f7499a..64acaa95d47 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3179,10 +3179,13 @@ User is always nil."
3179 (copy-file filename tmpfile 'ok-if-already-exists 'keep-time) 3179 (copy-file filename tmpfile 'ok-if-already-exists 'keep-time)
3180 tmpfile))) 3180 tmpfile)))
3181 3181
3182(defun tramp-handle-file-modes (filename) 3182(defun tramp-handle-file-modes (filename &optional flag)
3183 "Like `file-modes' for Tramp files." 3183 "Like `file-modes' for Tramp files."
3184 (when-let ((attrs (file-attributes (or (file-truename filename) filename)))) 3184 (when-let ((attrs (file-attributes filename)))
3185 (tramp-mode-string-to-int (tramp-compat-file-attribute-modes attrs)))) 3185 (let ((mode-string (tramp-compat-file-attribute-modes attrs)))
3186 (if (and (not flag) (eq ?l (aref mode-string 0)))
3187 (tramp-handle-file-modes (file-chase-links filename) 'nofollow)
3188 (tramp-mode-string-to-int mode-string)))))
3186 3189
3187;; Localname manipulation functions that grok Tramp localnames... 3190;; Localname manipulation functions that grok Tramp localnames...
3188(defun tramp-handle-file-name-as-directory (file) 3191(defun tramp-handle-file-name-as-directory (file)
@@ -3884,7 +3887,7 @@ of."
3884 ;; renamed to the backup file. This case `save-buffer' 3887 ;; renamed to the backup file. This case `save-buffer'
3885 ;; handles permissions. 3888 ;; handles permissions.
3886 ;; Ensure that it is still readable. 3889 ;; Ensure that it is still readable.
3887 (set-file-modes tmpfile (logior (or modes 0) #o0400)) 3890 (set-file-modes tmpfile (logior (or modes 0) #o0400) 'nofollow)
3888 ;; We say `no-message' here because we don't want the visited file 3891 ;; We say `no-message' here because we don't want the visited file
3889 ;; modtime data to be clobbered from the temp file. We call 3892 ;; modtime data to be clobbered from the temp file. We call
3890 ;; `set-visited-file-modtime' ourselves later on. 3893 ;; `set-visited-file-modtime' ourselves later on.
@@ -4664,7 +4667,7 @@ Return the local name of the temporary file."
4664 (setq result nil) 4667 (setq result nil)
4665 ;; This creates the file by side effect. 4668 ;; This creates the file by side effect.
4666 (set-file-times result) 4669 (set-file-times result)
4667 (set-file-modes result #o0700))) 4670 (set-file-modes result #o0700 'nofollow)))
4668 4671
4669 ;; Return the local part. 4672 ;; Return the local part.
4670 (tramp-file-local-name result))) 4673 (tramp-file-local-name result)))
diff --git a/lisp/server.el b/lisp/server.el
index e6d8b1783c9..18612181477 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -563,7 +563,7 @@ See variable `server-auth-dir' for details."
563 (format "it is not owned by you (owner = %s (%d))" 563 (format "it is not owned by you (owner = %s (%d))"
564 (user-full-name uid) uid)) 564 (user-full-name uid) uid))
565 (w32 nil) ; on NTFS? 565 (w32 nil) ; on NTFS?
566 ((let ((modes (file-modes dir))) 566 ((let ((modes (file-modes dir 'nofollow)))
567 (unless (zerop (logand (or modes 0) #o077)) 567 (unless (zerop (logand (or modes 0) #o077))
568 (format "it is accessible by others (%03o)" modes)))) 568 (format "it is accessible by others (%03o)" modes))))
569 (t nil)))) 569 (t nil))))
diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el
index 645011a5783..6dd7a9c2aac 100644
--- a/lisp/url/url-util.el
+++ b/lisp/url/url-util.el
@@ -615,9 +615,7 @@ Creates FILE and its parent directories if they do not exist."
615 (with-temp-buffer 615 (with-temp-buffer
616 (write-region (point-min) (point-max) file nil 'silent nil 'excl))) 616 (write-region (point-min) (point-max) file nil 'silent nil 'excl)))
617 (file-already-exists 617 (file-already-exists
618 (if (file-symlink-p file) 618 (set-file-modes file #o0600 'nofollow))))
619 (error "Danger: `%s' is a symbolic link" file))
620 (set-file-modes file #o0600))))
621 619
622(autoload 'puny-encode-domain "puny") 620(autoload 'puny-encode-domain "puny")
623(autoload 'url-domsuf-cookie-allowed-p "url-domsuf") 621(autoload 'url-domsuf-cookie-allowed-p "url-domsuf")