b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From dce4683cbbe107a95f1f0d45fabc304acfb5d71a Mon Sep 17 00:00:00 2001 |
| 2 | From: Andreas Gruenbacher <agruen@gnu.org> |
| 3 | Date: Mon, 15 Jul 2019 16:21:48 +0200 |
| 4 | Subject: Don't follow symlinks unless --follow-symlinks is given |
| 5 | |
| 6 | * src/inp.c (plan_a, plan_b), src/util.c (copy_to_fd, copy_file, |
| 7 | append_to_file): Unless the --follow-symlinks option is given, open files with |
| 8 | the O_NOFOLLOW flag to avoid following symlinks. So far, we were only doing |
| 9 | that consistently for input files. |
| 10 | * src/util.c (create_backup): When creating empty backup files, (re)create them |
| 11 | with O_CREAT | O_EXCL to avoid following symlinks in that case as well. |
| 12 | --- |
| 13 | src/inp.c | 12 ++++++++++-- |
| 14 | src/util.c | 14 +++++++++++--- |
| 15 | 2 files changed, 21 insertions(+), 5 deletions(-) |
| 16 | |
| 17 | --- a/src/inp.c |
| 18 | +++ b/src/inp.c |
| 19 | @@ -238,8 +238,13 @@ plan_a (char const *filename) |
| 20 | { |
| 21 | if (S_ISREG (instat.st_mode)) |
| 22 | { |
| 23 | - int ifd = safe_open (filename, O_RDONLY|binary_transput, 0); |
| 24 | + int flags = O_RDONLY | binary_transput; |
| 25 | size_t buffered = 0, n; |
| 26 | + int ifd; |
| 27 | + |
| 28 | + if (! follow_symlinks) |
| 29 | + flags |= O_NOFOLLOW; |
| 30 | + ifd = safe_open (filename, flags, 0); |
| 31 | if (ifd < 0) |
| 32 | pfatal ("can't open file %s", quotearg (filename)); |
| 33 | |
| 34 | @@ -340,6 +345,7 @@ plan_a (char const *filename) |
| 35 | static void |
| 36 | plan_b (char const *filename) |
| 37 | { |
| 38 | + int flags = O_RDONLY | binary_transput; |
| 39 | int ifd; |
| 40 | FILE *ifp; |
| 41 | int c; |
| 42 | @@ -353,7 +359,9 @@ plan_b (char const *filename) |
| 43 | |
| 44 | if (instat.st_size == 0) |
| 45 | filename = NULL_DEVICE; |
| 46 | - if ((ifd = safe_open (filename, O_RDONLY | binary_transput, 0)) < 0 |
| 47 | + if (! follow_symlinks) |
| 48 | + flags |= O_NOFOLLOW; |
| 49 | + if ((ifd = safe_open (filename, flags, 0)) < 0 |
| 50 | || ! (ifp = fdopen (ifd, binary_transput ? "rb" : "r"))) |
| 51 | pfatal ("Can't open file %s", quotearg (filename)); |
| 52 | if (TMPINNAME_needs_removal) |
| 53 | --- a/src/util.c |
| 54 | +++ b/src/util.c |
| 55 | @@ -388,7 +388,7 @@ create_backup (char const *to, const str |
| 56 | |
| 57 | try_makedirs_errno = ENOENT; |
| 58 | safe_unlink (bakname); |
| 59 | - while ((fd = safe_open (bakname, O_CREAT | O_WRONLY | O_TRUNC, 0666)) < 0) |
| 60 | + while ((fd = safe_open (bakname, O_CREAT | O_EXCL | O_WRONLY | O_TRUNC, 0666)) < 0) |
| 61 | { |
| 62 | if (errno != try_makedirs_errno) |
| 63 | pfatal ("Can't create file %s", quotearg (bakname)); |
| 64 | @@ -579,10 +579,13 @@ create_file (char const *file, int open_ |
| 65 | static void |
| 66 | copy_to_fd (const char *from, int tofd) |
| 67 | { |
| 68 | + int from_flags = O_RDONLY | O_BINARY; |
| 69 | int fromfd; |
| 70 | ssize_t i; |
| 71 | |
| 72 | - if ((fromfd = safe_open (from, O_RDONLY | O_BINARY, 0)) < 0) |
| 73 | + if (! follow_symlinks) |
| 74 | + from_flags |= O_NOFOLLOW; |
| 75 | + if ((fromfd = safe_open (from, from_flags, 0)) < 0) |
| 76 | pfatal ("Can't reopen file %s", quotearg (from)); |
| 77 | while ((i = read (fromfd, buf, bufsize)) != 0) |
| 78 | { |
| 79 | @@ -625,6 +628,8 @@ copy_file (char const *from, char const |
| 80 | else |
| 81 | { |
| 82 | assert (S_ISREG (mode)); |
| 83 | + if (! follow_symlinks) |
| 84 | + to_flags |= O_NOFOLLOW; |
| 85 | tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode, |
| 86 | to_dir_known_to_exist); |
| 87 | copy_to_fd (from, tofd); |
| 88 | @@ -640,9 +645,12 @@ copy_file (char const *from, char const |
| 89 | void |
| 90 | append_to_file (char const *from, char const *to) |
| 91 | { |
| 92 | + int to_flags = O_WRONLY | O_APPEND | O_BINARY; |
| 93 | int tofd; |
| 94 | |
| 95 | - if ((tofd = safe_open (to, O_WRONLY | O_BINARY | O_APPEND, 0)) < 0) |
| 96 | + if (! follow_symlinks) |
| 97 | + to_flags |= O_NOFOLLOW; |
| 98 | + if ((tofd = safe_open (to, to_flags, 0)) < 0) |
| 99 | pfatal ("Can't reopen file %s", quotearg (to)); |
| 100 | copy_to_fd (from, tofd); |
| 101 | if (close (tofd) != 0) |