set_cmnd_path: apply runchroot if set when finding the command path
Previously we would prepend runchroot to the path we were checking but that does not properly handle symbolic links.
This commit is contained in:
@@ -147,7 +147,7 @@ resolve_editor(const char *ed, size_t edlen, int nfiles, char * const *files,
|
||||
goto oom;
|
||||
|
||||
/* If we can't find the editor in the user's PATH, give up. */
|
||||
if (find_path(editor, &editor_path, &user_editor_sb, getenv("PATH"), NULL,
|
||||
if (find_path(editor, &editor_path, &user_editor_sb, getenv("PATH"),
|
||||
0, allowlist) != FOUND) {
|
||||
errno = ENOENT;
|
||||
goto bad;
|
||||
|
@@ -43,14 +43,14 @@
|
||||
* On failure, returns false.
|
||||
*/
|
||||
static bool
|
||||
cmnd_allowed(char *cmnd, size_t cmnd_size, const char *runchroot,
|
||||
struct stat *cmnd_sbp, char * const *allowlist)
|
||||
cmnd_allowed(char *cmnd, size_t cmnd_size, struct stat *cmnd_sbp,
|
||||
char * const *allowlist)
|
||||
{
|
||||
const char *cmnd_base;
|
||||
char * const *al;
|
||||
debug_decl(cmnd_allowed, SUDOERS_DEBUG_UTIL);
|
||||
|
||||
if (!sudo_goodpath(cmnd, runchroot, cmnd_sbp))
|
||||
if (!sudo_goodpath(cmnd, cmnd_sbp))
|
||||
debug_return_bool(false);
|
||||
|
||||
if (allowlist == NULL)
|
||||
@@ -67,7 +67,7 @@ cmnd_allowed(char *cmnd, size_t cmnd_size, const char *runchroot,
|
||||
if (strcmp(cmnd_base, base) != 0)
|
||||
continue;
|
||||
|
||||
if (sudo_goodpath(path, runchroot, &sb) &&
|
||||
if (sudo_goodpath(path, &sb) &&
|
||||
sb.st_dev == cmnd_sbp->st_dev && sb.st_ino == cmnd_sbp->st_ino) {
|
||||
/* Overwrite cmnd with safe version from allowlist. */
|
||||
if (strlcpy(cmnd, path, cmnd_size) < cmnd_size)
|
||||
@@ -87,8 +87,7 @@ cmnd_allowed(char *cmnd, size_t cmnd_size, const char *runchroot,
|
||||
*/
|
||||
int
|
||||
find_path(const char *infile, char **outfile, struct stat *sbp,
|
||||
const char *path, const char *runchroot, int ignore_dot,
|
||||
char * const *allowlist)
|
||||
const char *path, int ignore_dot, char * const *allowlist)
|
||||
{
|
||||
char command[PATH_MAX];
|
||||
const char *cp, *ep, *pathend;
|
||||
@@ -109,8 +108,7 @@ find_path(const char *infile, char **outfile, struct stat *sbp,
|
||||
errno = ENAMETOOLONG;
|
||||
debug_return_int(NOT_FOUND_ERROR);
|
||||
}
|
||||
found = cmnd_allowed(command, sizeof(command), runchroot, sbp,
|
||||
allowlist);
|
||||
found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -139,8 +137,7 @@ find_path(const char *infile, char **outfile, struct stat *sbp,
|
||||
errno = ENAMETOOLONG;
|
||||
debug_return_int(NOT_FOUND_ERROR);
|
||||
}
|
||||
found = cmnd_allowed(command, sizeof(command), runchroot,
|
||||
sbp, allowlist);
|
||||
found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
|
||||
if (found)
|
||||
break;
|
||||
}
|
||||
@@ -154,8 +151,7 @@ find_path(const char *infile, char **outfile, struct stat *sbp,
|
||||
errno = ENAMETOOLONG;
|
||||
debug_return_int(NOT_FOUND_ERROR);
|
||||
}
|
||||
found = cmnd_allowed(command, sizeof(command), runchroot,
|
||||
sbp, allowlist);
|
||||
found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
|
||||
if (found && ignore_dot)
|
||||
debug_return_int(NOT_FOUND_DOT);
|
||||
}
|
||||
|
@@ -39,24 +39,13 @@
|
||||
* Verify that path is a normal file and executable by root.
|
||||
*/
|
||||
bool
|
||||
sudo_goodpath(const char *path, const char *runchroot, struct stat *sbp)
|
||||
sudo_goodpath(const char *path, struct stat *sbp)
|
||||
{
|
||||
bool ret = false;
|
||||
struct stat sb;
|
||||
debug_decl(sudo_goodpath, SUDOERS_DEBUG_UTIL);
|
||||
|
||||
if (path != NULL) {
|
||||
char pathbuf[PATH_MAX];
|
||||
struct stat sb;
|
||||
|
||||
if (runchroot != NULL) {
|
||||
const int len =
|
||||
snprintf(pathbuf, sizeof(pathbuf), "%s%s", runchroot, path);
|
||||
if (len >= ssizeof(pathbuf)) {
|
||||
errno = ENAMETOOLONG;
|
||||
goto done;
|
||||
}
|
||||
path = pathbuf; // -V507
|
||||
}
|
||||
if (sbp == NULL)
|
||||
sbp = &sb;
|
||||
|
||||
@@ -68,6 +57,5 @@ sudo_goodpath(const char *path, const char *runchroot, struct stat *sbp)
|
||||
errno = EACCES;
|
||||
}
|
||||
}
|
||||
done:
|
||||
debug_return_bool(ret);
|
||||
}
|
||||
|
@@ -80,8 +80,7 @@ sudo_dso_public int main(int argc, char *argv[]);
|
||||
/* STUB */
|
||||
int
|
||||
find_path(const char *infile, char **outfile, struct stat *sbp,
|
||||
const char *path, const char *runchroot, int ignore_dot,
|
||||
char * const *allowlist)
|
||||
const char *path, int ignore_dot, char * const *allowlist)
|
||||
{
|
||||
if (infile[0] == '/') {
|
||||
*outfile = strdup(infile);
|
||||
|
@@ -799,8 +799,7 @@ display_privs(struct sudo_nss_list *snl, struct passwd *pw, bool verbose)
|
||||
/* STUB */
|
||||
int
|
||||
find_path(const char *infile, char **outfile, struct stat *sbp,
|
||||
const char *path, const char *runchroot, int ignore_dot,
|
||||
char * const *allowlist)
|
||||
const char *path, int ignore_dot, char * const *allowlist)
|
||||
{
|
||||
switch (pass) {
|
||||
case PASS_CHECK_NOT_FOUND:
|
||||
|
@@ -998,7 +998,7 @@ set_cmnd_path(const char *runchroot)
|
||||
const char *cmnd_in;
|
||||
char *cmnd_out = NULL;
|
||||
char *path = user_path;
|
||||
int ret;
|
||||
int ret, pivot_fds[2];
|
||||
debug_decl(set_cmnd_path, SUDOERS_DEBUG_PLUGIN);
|
||||
|
||||
cmnd_in = ISSET(sudo_mode, MODE_CHECK) ? NewArgv[1] : NewArgv[0];
|
||||
@@ -1009,10 +1009,16 @@ set_cmnd_path(const char *runchroot)
|
||||
user_cmnd = NULL;
|
||||
if (def_secure_path && !user_is_exempt())
|
||||
path = def_secure_path;
|
||||
|
||||
/* Pivot root. */
|
||||
if (runchroot != NULL) {
|
||||
if (!pivot_root(runchroot, pivot_fds))
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!set_perms(PERM_RUNAS))
|
||||
goto error;
|
||||
ret = find_path(cmnd_in, &cmnd_out, user_stat, path,
|
||||
runchroot, def_ignore_dot, NULL);
|
||||
ret = find_path(cmnd_in, &cmnd_out, user_stat, path, def_ignore_dot, NULL);
|
||||
if (!restore_perms())
|
||||
goto error;
|
||||
if (ret == NOT_FOUND) {
|
||||
@@ -1020,7 +1026,7 @@ set_cmnd_path(const char *runchroot)
|
||||
if (!set_perms(PERM_USER))
|
||||
goto error;
|
||||
ret = find_path(cmnd_in, &cmnd_out, user_stat, path,
|
||||
runchroot, def_ignore_dot, NULL);
|
||||
def_ignore_dot, NULL);
|
||||
if (!restore_perms())
|
||||
goto error;
|
||||
}
|
||||
@@ -1030,8 +1036,14 @@ set_cmnd_path(const char *runchroot)
|
||||
else
|
||||
user_cmnd = cmnd_out;
|
||||
|
||||
/* Restore root. */
|
||||
if (runchroot != NULL)
|
||||
(void)unpivot_root(pivot_fds);
|
||||
|
||||
debug_return_int(ret);
|
||||
error:
|
||||
if (runchroot != NULL)
|
||||
(void)unpivot_root(pivot_fds);
|
||||
free(cmnd_out);
|
||||
debug_return_int(NOT_FOUND_ERROR);
|
||||
}
|
||||
|
@@ -288,12 +288,11 @@ struct timespec;
|
||||
#define YY_DECL int sudoerslex(void)
|
||||
|
||||
/* goodpath.c */
|
||||
bool sudo_goodpath(const char *path, const char *runchroot, struct stat *sbp);
|
||||
bool sudo_goodpath(const char *path, struct stat *sbp);
|
||||
|
||||
/* findpath.c */
|
||||
int find_path(const char *infile, char **outfile, struct stat *sbp,
|
||||
const char *path, const char *runchroot, int ignore_dot,
|
||||
char * const *allowlist);
|
||||
const char *path, int ignore_dot, char * const *allowlist);
|
||||
|
||||
/* check.c */
|
||||
int check_user(int validate, int mode);
|
||||
|
Reference in New Issue
Block a user