Move the check for /dev/fd/N until *after* the digest has been
checked. We still need to be able to check the digest even if there is no /dev/fd/N or fexecve().
This commit is contained in:
@@ -487,7 +487,6 @@ do_stat(int fd, const char *path, struct stat *sb)
|
||||
debug_return_bool(stat(path, sb) == 0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_FEXECVE
|
||||
/*
|
||||
* Check whether the fd refers to a shell script with a "#!" shebang.
|
||||
*/
|
||||
@@ -531,42 +530,57 @@ open_cmnd(const char *path, const struct sudo_digest *digest, int *fdp)
|
||||
if (fd == -1)
|
||||
debug_return_bool(false);
|
||||
|
||||
if (is_script(fd)) {
|
||||
char fdpath[PATH_MAX];
|
||||
struct stat sb;
|
||||
|
||||
/* We can only use fexecve() on a script if /dev/fd/N exists. */
|
||||
snprintf(fdpath, sizeof(fdpath), "/dev/fd/%d", fd);
|
||||
if (stat(fdpath, &sb) != 0) {
|
||||
close(fd);
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shell scripts go through namei twice so we can't set the
|
||||
* close on exec flag on the fd for fexecve(2).
|
||||
*/
|
||||
} else {
|
||||
/* Not a script, close on exec is safe. */
|
||||
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
|
||||
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
*fdp = fd;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
#else /* HAVE_FEXECVE */
|
||||
static bool
|
||||
open_cmnd(const char *path, const struct sudo_digest *digest, int *fdp)
|
||||
|
||||
static void
|
||||
set_cmnd_fd(int fd)
|
||||
{
|
||||
return true;
|
||||
debug_decl(set_cmnd_fd, SUDOERS_DEBUG_MATCH)
|
||||
|
||||
if (cmnd_fd != -1)
|
||||
close(cmnd_fd);
|
||||
|
||||
if (fd != -1) {
|
||||
if (def_fdexec == never) {
|
||||
/* Never use fexedcve() */
|
||||
close(fd);
|
||||
fd = -1;
|
||||
} else if (is_script(fd)) {
|
||||
char fdpath[PATH_MAX];
|
||||
struct stat sb;
|
||||
int flags;
|
||||
|
||||
/* We can only use fexecve() on a script if /dev/fd/N exists. */
|
||||
snprintf(fdpath, sizeof(fdpath), "/dev/fd/%d", fd);
|
||||
if (stat(fdpath, &sb) != 0) {
|
||||
/* Missing /dev/fd file, can't use fexecve(). */
|
||||
close(fd);
|
||||
fd = -1;
|
||||
} else {
|
||||
/*
|
||||
* Shell scripts go through namei twice so we can't have the
|
||||
* close on exec flag set on the fd for fexecve(2).
|
||||
*/
|
||||
flags = fcntl(fd, F_GETFD) & ~FD_CLOEXEC;
|
||||
(void)fcntl(fd, F_SETFD, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmnd_fd = fd;
|
||||
|
||||
debug_return;
|
||||
}
|
||||
#endif /* HAVE_FEXECVE */
|
||||
|
||||
static bool
|
||||
command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
const struct sudo_digest *digest)
|
||||
{
|
||||
struct stat sb; /* XXX - unused */
|
||||
int fd = -1;
|
||||
debug_decl(command_matches_fnmatch, SUDOERS_DEBUG_MATCH)
|
||||
|
||||
/*
|
||||
@@ -579,30 +593,22 @@ command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
|
||||
if (fnmatch(sudoers_cmnd, user_cmnd, FNM_PATHNAME) != 0)
|
||||
debug_return_bool(false);
|
||||
if (command_args_match(sudoers_cmnd, sudoers_args)) {
|
||||
if (cmnd_fd != -1) {
|
||||
close(cmnd_fd);
|
||||
cmnd_fd = -1;
|
||||
}
|
||||
/* Open the file for fdexec or for digest matching. */
|
||||
if (!open_cmnd(user_cmnd, digest, &cmnd_fd))
|
||||
if (!open_cmnd(user_cmnd, digest, &fd))
|
||||
goto bad;
|
||||
if (!do_stat(cmnd_fd, user_cmnd, &sb))
|
||||
if (!do_stat(fd, user_cmnd, &sb))
|
||||
goto bad;
|
||||
/* Check digest of user_cmnd since sudoers_cmnd is a pattern. */
|
||||
if (digest != NULL) {
|
||||
if (!digest_matches(cmnd_fd, user_cmnd, digest))
|
||||
goto bad;
|
||||
if (def_fdexec == never) {
|
||||
close(cmnd_fd);
|
||||
cmnd_fd = -1;
|
||||
}
|
||||
}
|
||||
if (digest != NULL && !digest_matches(fd, user_cmnd, digest))
|
||||
goto bad;
|
||||
set_cmnd_fd(fd);
|
||||
|
||||
/* No need to set safe_cmnd since user_cmnd matches sudoers_cmnd */
|
||||
debug_return_bool(true);
|
||||
bad:
|
||||
if (cmnd_fd != -1) {
|
||||
close(cmnd_fd);
|
||||
cmnd_fd = -1;
|
||||
if (fd != -1) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
@@ -730,16 +736,7 @@ done:
|
||||
if (cp != NULL) {
|
||||
if (command_args_match(sudoers_cmnd, sudoers_args)) {
|
||||
/* safe_cmnd was set above. */
|
||||
if (cmnd_fd != -1) {
|
||||
close(cmnd_fd);
|
||||
cmnd_fd = -1;
|
||||
}
|
||||
if (fd != -1) {
|
||||
if (def_fdexec == never)
|
||||
close(fd);
|
||||
else
|
||||
cmnd_fd = fd;
|
||||
}
|
||||
set_cmnd_fd(fd);
|
||||
debug_return_bool(true);
|
||||
}
|
||||
}
|
||||
@@ -884,16 +881,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
goto bad;
|
||||
}
|
||||
if (cmnd_fd != -1) {
|
||||
close(cmnd_fd);
|
||||
cmnd_fd = -1;
|
||||
}
|
||||
if (fd != -1) {
|
||||
if (def_fdexec == never)
|
||||
close(fd);
|
||||
else
|
||||
cmnd_fd = fd;
|
||||
}
|
||||
set_cmnd_fd(fd);
|
||||
debug_return_bool(true);
|
||||
bad:
|
||||
if (fd != -1)
|
||||
@@ -979,16 +967,7 @@ command_matches_dir(const char *sudoers_dir, size_t dlen,
|
||||
closedir(dirp);
|
||||
|
||||
if (dent != NULL) {
|
||||
if (cmnd_fd != -1) {
|
||||
close(cmnd_fd);
|
||||
cmnd_fd = -1;
|
||||
}
|
||||
if (fd != -1) {
|
||||
if (def_fdexec == never)
|
||||
close(fd);
|
||||
else
|
||||
cmnd_fd = fd;
|
||||
}
|
||||
set_cmnd_fd(fd);
|
||||
debug_return_bool(true);
|
||||
}
|
||||
if (fd != -1)
|
||||
|
Reference in New Issue
Block a user