From bf82b3f2ba37e3c8d02abb10cdf02727c94d188a Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 25 Jul 2016 10:26:54 -0600 Subject: [PATCH] On systems that lack the O_NOFOLLOW open(2) flag, check in sudo_edit_open() whether the path to be opened is symlink before opening it. This is racey but we detect losing the last post-open and it is better to fail early if possible. When editing a link to a non-existent file, a zero-length file will be left behind but it is too dangerous to try and remove it after the fact. Bug #753 --- src/sudo_edit.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/sudo_edit.c b/src/sudo_edit.c index a7915ed1e..6e330cce6 100644 --- a/src/sudo_edit.c +++ b/src/sudo_edit.c @@ -449,9 +449,23 @@ sudo_edit_open(char *path, int oflags, mode_t mode, struct command_details *command_details) { const int sflags = command_details ? command_details->flags : 0; + struct stat sb; int fd; debug_decl(sudo_edit_open, SUDO_DEBUG_EDIT) + /* + * Check if path is a symlink. This is racey but we detect whether + * we lost the race in sudo_edit_is_symlink() after the file is opened. + */ + if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW)) { + if (lstat(path, &sb) == -1 && errno != ENOENT) + debug_return_int(-1); + if (S_ISLNK(sb.st_mode)) { + errno = ELOOP; + debug_return_int(-1); + } + } + if (ISSET(sflags, CD_SUDOEDIT_CHECKDIR) && user_details.uid != ROOT_UID) { fd = sudo_edit_open_nonwritable(path, oflags|O_NONBLOCK, mode, command_details); @@ -463,6 +477,10 @@ sudo_edit_open(char *path, int oflags, mode_t mode, if (!ISSET(oflags, O_NONBLOCK)) (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); + /* + * Post-open symlink check. This will leave a zero-length file if + * O_CREAT was specified but it is too dangerous to try and remove it. + */ if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW) && sudo_edit_is_symlink(fd, path)) { close(fd); fd = -1; -- 2.40.0