diff options
| author | Paul Eggert | 2020-02-23 16:19:42 -0800 |
|---|---|---|
| committer | Paul Eggert | 2020-02-23 16:45:50 -0800 |
| commit | 9d626dffc6ba62c0d7a1a5c712f576ed8684fd66 (patch) | |
| tree | 6cc8fbe8e5bc02c3bb74139710814a0400e91a8a /lisp/net | |
| parent | c4ca8219dd6b8f06e67a0b767475b1259653b8e0 (diff) | |
| download | emacs-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/net')
| -rw-r--r-- | lisp/net/ange-ftp.el | 3 | ||||
| -rw-r--r-- | lisp/net/tramp-adb.el | 9 | ||||
| -rw-r--r-- | lisp/net/tramp-gvfs.el | 4 | ||||
| -rw-r--r-- | lisp/net/tramp-sh.el | 10 | ||||
| -rw-r--r-- | lisp/net/tramp-smb.el | 3 | ||||
| -rw-r--r-- | lisp/net/tramp-sudoedit.el | 6 | ||||
| -rw-r--r-- | lisp/net/tramp.el | 13 |
7 files changed, 30 insertions, 18 deletions
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))) |