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
This commit is contained in:
Todd C. Miller
2016-07-25 10:26:54 -06:00
parent 2663575118
commit bf82b3f2ba

View File

@@ -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;