2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-09-05 00:35:14 +00:00

Revert pivot_root and go back to prepending the new root directory.

We cannot perform passwd/group lookups _after_ changing the root
directory.  This does mean that symbolic links in a path are not
currently handled properly when matching chroot()ed commands.

Fixes a local privilege escalation vulnerability where a user could
craft their own nsswitch.conf file to load a shared library of their
choosing and run arbitrary code.  CVE-2025-32463

Reported by Rich Mirch @ Stratascale Cyber Research Unit (CRU).
This commit is contained in:
Todd C. Miller
2025-04-06 08:28:46 -06:00
parent d530367828
commit fdafc2ceb3
18 changed files with 641 additions and 822 deletions

View File

@@ -43,14 +43,14 @@
* On failure, returns false.
*/
static bool
cmnd_allowed(char *cmnd, size_t cmnd_size, struct stat *cmnd_sbp,
char * const *allowlist)
cmnd_allowed(char *cmnd, size_t cmnd_size, const char *runchroot,
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, cmnd_sbp))
if (!sudo_goodpath(cmnd, runchroot, cmnd_sbp))
debug_return_bool(false);
if (allowlist == NULL)
@@ -67,7 +67,7 @@ cmnd_allowed(char *cmnd, size_t cmnd_size, struct stat *cmnd_sbp,
if (strcmp(cmnd_base, base) != 0)
continue;
if (sudo_goodpath(path, &sb) &&
if (sudo_goodpath(path, runchroot, &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,7 +87,8 @@ cmnd_allowed(char *cmnd, size_t cmnd_size, struct stat *cmnd_sbp,
*/
int
find_path(const char *infile, char **outfile, struct stat *sbp,
const char *path, bool ignore_dot, char * const *allowlist)
const char *path, const char *runchroot, bool ignore_dot,
char * const *allowlist)
{
char command[PATH_MAX];
const char *cp, *ep, *pathend;
@@ -108,7 +109,8 @@ find_path(const char *infile, char **outfile, struct stat *sbp,
errno = ENAMETOOLONG;
debug_return_int(NOT_FOUND_ERROR);
}
found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
found = cmnd_allowed(command, sizeof(command), runchroot, sbp,
allowlist);
goto done;
}
@@ -137,7 +139,8 @@ find_path(const char *infile, char **outfile, struct stat *sbp,
errno = ENAMETOOLONG;
debug_return_int(NOT_FOUND_ERROR);
}
found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
found = cmnd_allowed(command, sizeof(command), runchroot,
sbp, allowlist);
if (found)
break;
}
@@ -151,7 +154,8 @@ find_path(const char *infile, char **outfile, struct stat *sbp,
errno = ENAMETOOLONG;
debug_return_int(NOT_FOUND_ERROR);
}
found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
found = cmnd_allowed(command, sizeof(command), runchroot,
sbp, allowlist);
if (found && ignore_dot)
debug_return_int(NOT_FOUND_DOT);
}