| From dce4683cbbe107a95f1f0d45fabc304acfb5d71a Mon Sep 17 00:00:00 2001 |
| From: Andreas Gruenbacher <agruen@gnu.org> |
| Date: Mon, 15 Jul 2019 16:21:48 +0200 |
| Subject: Don't follow symlinks unless --follow-symlinks is given |
| |
| * src/inp.c (plan_a, plan_b), src/util.c (copy_to_fd, copy_file, |
| append_to_file): Unless the --follow-symlinks option is given, open files with |
| the O_NOFOLLOW flag to avoid following symlinks. So far, we were only doing |
| that consistently for input files. |
| * src/util.c (create_backup): When creating empty backup files, (re)create them |
| with O_CREAT | O_EXCL to avoid following symlinks in that case as well. |
| |
| CVE: CVE-2019-13636 |
| Upstream-Status: Backport[https://git.savannah.gnu.org/cgit/patch.git/patch/?id=dce4683cbbe107a95f1f0d45fabc304acfb5d71a] |
| Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> |
| |
| --- |
| src/inp.c | 12 ++++++++++-- |
| src/util.c | 14 +++++++++++--- |
| 2 files changed, 21 insertions(+), 5 deletions(-) |
| |
| diff --git a/src/inp.c b/src/inp.c |
| index 32d0919..22d7473 100644 |
| --- a/src/inp.c |
| +++ b/src/inp.c |
| @@ -238,8 +238,13 @@ plan_a (char const *filename) |
| { |
| if (S_ISREG (instat.st_mode)) |
| { |
| - int ifd = safe_open (filename, O_RDONLY|binary_transput, 0); |
| + int flags = O_RDONLY | binary_transput; |
| size_t buffered = 0, n; |
| + int ifd; |
| + |
| + if (! follow_symlinks) |
| + flags |= O_NOFOLLOW; |
| + ifd = safe_open (filename, flags, 0); |
| if (ifd < 0) |
| pfatal ("can't open file %s", quotearg (filename)); |
| |
| @@ -340,6 +345,7 @@ plan_a (char const *filename) |
| static void |
| plan_b (char const *filename) |
| { |
| + int flags = O_RDONLY | binary_transput; |
| int ifd; |
| FILE *ifp; |
| int c; |
| @@ -353,7 +359,9 @@ plan_b (char const *filename) |
| |
| if (instat.st_size == 0) |
| filename = NULL_DEVICE; |
| - if ((ifd = safe_open (filename, O_RDONLY | binary_transput, 0)) < 0 |
| + if (! follow_symlinks) |
| + flags |= O_NOFOLLOW; |
| + if ((ifd = safe_open (filename, flags, 0)) < 0 |
| || ! (ifp = fdopen (ifd, binary_transput ? "rb" : "r"))) |
| pfatal ("Can't open file %s", quotearg (filename)); |
| if (TMPINNAME_needs_removal) |
| diff --git a/src/util.c b/src/util.c |
| index 1cc08ba..fb38307 100644 |
| --- a/src/util.c |
| +++ b/src/util.c |
| @@ -388,7 +388,7 @@ create_backup (char const *to, const struct stat *to_st, bool leave_original) |
| |
| try_makedirs_errno = ENOENT; |
| safe_unlink (bakname); |
| - while ((fd = safe_open (bakname, O_CREAT | O_WRONLY | O_TRUNC, 0666)) < 0) |
| + while ((fd = safe_open (bakname, O_CREAT | O_EXCL | O_WRONLY | O_TRUNC, 0666)) < 0) |
| { |
| if (errno != try_makedirs_errno) |
| pfatal ("Can't create file %s", quotearg (bakname)); |
| @@ -579,10 +579,13 @@ create_file (char const *file, int open_flags, mode_t mode, |
| static void |
| copy_to_fd (const char *from, int tofd) |
| { |
| + int from_flags = O_RDONLY | O_BINARY; |
| int fromfd; |
| ssize_t i; |
| |
| - if ((fromfd = safe_open (from, O_RDONLY | O_BINARY, 0)) < 0) |
| + if (! follow_symlinks) |
| + from_flags |= O_NOFOLLOW; |
| + if ((fromfd = safe_open (from, from_flags, 0)) < 0) |
| pfatal ("Can't reopen file %s", quotearg (from)); |
| while ((i = read (fromfd, buf, bufsize)) != 0) |
| { |
| @@ -625,6 +628,8 @@ copy_file (char const *from, char const *to, struct stat *tost, |
| else |
| { |
| assert (S_ISREG (mode)); |
| + if (! follow_symlinks) |
| + to_flags |= O_NOFOLLOW; |
| tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode, |
| to_dir_known_to_exist); |
| copy_to_fd (from, tofd); |
| @@ -640,9 +645,12 @@ copy_file (char const *from, char const *to, struct stat *tost, |
| void |
| append_to_file (char const *from, char const *to) |
| { |
| + int to_flags = O_WRONLY | O_APPEND | O_BINARY; |
| int tofd; |
| |
| - if ((tofd = safe_open (to, O_WRONLY | O_BINARY | O_APPEND, 0)) < 0) |
| + if (! follow_symlinks) |
| + to_flags |= O_NOFOLLOW; |
| + if ((tofd = safe_open (to, to_flags, 0)) < 0) |
| pfatal ("Can't reopen file %s", quotearg (to)); |
| copy_to_fd (from, tofd); |
| if (close (tofd) != 0) |
| -- |
| cgit v1.0-41-gc330 |
| |