| 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) |