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);
|
debug_return_bool(stat(path, sb) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_FEXECVE
|
|
||||||
/*
|
/*
|
||||||
* Check whether the fd refers to a shell script with a "#!" shebang.
|
* 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)
|
if (fd == -1)
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
|
|
||||||
if (is_script(fd)) {
|
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
*fdp = fd;
|
*fdp = fd;
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
#else /* HAVE_FEXECVE */
|
|
||||||
static bool
|
static void
|
||||||
open_cmnd(const char *path, const struct sudo_digest *digest, int *fdp)
|
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
|
static bool
|
||||||
command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
|
command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
|
||||||
const struct sudo_digest *digest)
|
const struct sudo_digest *digest)
|
||||||
{
|
{
|
||||||
struct stat sb; /* XXX - unused */
|
struct stat sb; /* XXX - unused */
|
||||||
|
int fd = -1;
|
||||||
debug_decl(command_matches_fnmatch, SUDOERS_DEBUG_MATCH)
|
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)
|
if (fnmatch(sudoers_cmnd, user_cmnd, FNM_PATHNAME) != 0)
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
if (command_args_match(sudoers_cmnd, sudoers_args)) {
|
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. */
|
/* 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;
|
goto bad;
|
||||||
if (!do_stat(cmnd_fd, user_cmnd, &sb))
|
if (!do_stat(fd, user_cmnd, &sb))
|
||||||
goto bad;
|
goto bad;
|
||||||
/* Check digest of user_cmnd since sudoers_cmnd is a pattern. */
|
/* Check digest of user_cmnd since sudoers_cmnd is a pattern. */
|
||||||
if (digest != NULL) {
|
if (digest != NULL && !digest_matches(fd, user_cmnd, digest))
|
||||||
if (!digest_matches(cmnd_fd, user_cmnd, digest))
|
goto bad;
|
||||||
goto bad;
|
set_cmnd_fd(fd);
|
||||||
if (def_fdexec == never) {
|
|
||||||
close(cmnd_fd);
|
|
||||||
cmnd_fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* No need to set safe_cmnd since user_cmnd matches sudoers_cmnd */
|
/* No need to set safe_cmnd since user_cmnd matches sudoers_cmnd */
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
bad:
|
bad:
|
||||||
if (cmnd_fd != -1) {
|
if (fd != -1) {
|
||||||
close(cmnd_fd);
|
close(fd);
|
||||||
cmnd_fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
}
|
}
|
||||||
@@ -730,16 +736,7 @@ done:
|
|||||||
if (cp != NULL) {
|
if (cp != NULL) {
|
||||||
if (command_args_match(sudoers_cmnd, sudoers_args)) {
|
if (command_args_match(sudoers_cmnd, sudoers_args)) {
|
||||||
/* safe_cmnd was set above. */
|
/* safe_cmnd was set above. */
|
||||||
if (cmnd_fd != -1) {
|
set_cmnd_fd(fd);
|
||||||
close(cmnd_fd);
|
|
||||||
cmnd_fd = -1;
|
|
||||||
}
|
|
||||||
if (fd != -1) {
|
|
||||||
if (def_fdexec == never)
|
|
||||||
close(fd);
|
|
||||||
else
|
|
||||||
cmnd_fd = fd;
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
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"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (cmnd_fd != -1) {
|
set_cmnd_fd(fd);
|
||||||
close(cmnd_fd);
|
|
||||||
cmnd_fd = -1;
|
|
||||||
}
|
|
||||||
if (fd != -1) {
|
|
||||||
if (def_fdexec == never)
|
|
||||||
close(fd);
|
|
||||||
else
|
|
||||||
cmnd_fd = fd;
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
bad:
|
bad:
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
@@ -979,16 +967,7 @@ command_matches_dir(const char *sudoers_dir, size_t dlen,
|
|||||||
closedir(dirp);
|
closedir(dirp);
|
||||||
|
|
||||||
if (dent != NULL) {
|
if (dent != NULL) {
|
||||||
if (cmnd_fd != -1) {
|
set_cmnd_fd(fd);
|
||||||
close(cmnd_fd);
|
|
||||||
cmnd_fd = -1;
|
|
||||||
}
|
|
||||||
if (fd != -1) {
|
|
||||||
if (def_fdexec == never)
|
|
||||||
close(fd);
|
|
||||||
else
|
|
||||||
cmnd_fd = fd;
|
|
||||||
}
|
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
|
Reference in New Issue
Block a user