2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 01:49:11 +00:00

Pass runchroot to match_digest() too.

We use the open fd for the actual I/O but having runchroot makes
it possible to report the correct file name in error messages.
This commit is contained in:
Todd C. Miller 2020-10-06 10:54:39 -06:00
parent 645eda55ab
commit 607076d8a0
3 changed files with 25 additions and 11 deletions

View File

@ -272,7 +272,8 @@ command_matches_dir(const char *sudoers_dir, size_t dlen, const char *runchroot,
if (user_stat == NULL ||
(user_stat->st_dev == sudoers_stat.st_dev &&
user_stat->st_ino == sudoers_stat.st_ino)) {
if (!digest_matches(fd, buf, digests))
/* buf is already relative to runchroot */
if (!digest_matches(fd, buf, NULL, digests))
continue;
free(safe_cmnd);
if ((safe_cmnd = strdup(buf + chrootlen)) == NULL) {
@ -311,7 +312,7 @@ command_matches_all(const char *runchroot,
}
/* Check digest of user_cmnd since we have no sudoers_cmnd for ALL. */
if (!digest_matches(fd, user_cmnd, digests))
if (!digest_matches(fd, user_cmnd, runchroot, digests))
goto bad;
set_cmnd_fd(fd);
@ -351,7 +352,7 @@ command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args,
if (!do_stat(fd, user_cmnd, runchroot, &sb))
goto bad;
/* Check digest of user_cmnd since sudoers_cmnd is a pattern. */
if (!digest_matches(fd, user_cmnd, digests))
if (!digest_matches(fd, user_cmnd, runchroot, digests))
goto bad;
set_cmnd_fd(fd);
@ -438,7 +439,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
(user_stat->st_dev == sudoers_stat.st_dev &&
user_stat->st_ino == sudoers_stat.st_ino)) {
/* There could be multiple matches, check digest early. */
if (!digest_matches(fd, cp, digests)) {
if (!digest_matches(fd, cp, runchroot, digests)) {
bad_digest = true;
continue;
}
@ -490,7 +491,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
if (user_stat == NULL ||
(user_stat->st_dev == sudoers_stat.st_dev &&
user_stat->st_ino == sudoers_stat.st_ino)) {
if (!digest_matches(fd, cp, digests))
if (!digest_matches(fd, cp, runchroot, digests))
continue;
free(safe_cmnd);
if ((safe_cmnd = strdup(cp)) == NULL) {
@ -563,7 +564,7 @@ command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args,
}
if (!command_args_match(sudoers_cmnd, sudoers_args))
goto bad;
if (!digest_matches(fd, sudoers_cmnd, digests)) {
if (!digest_matches(fd, sudoers_cmnd, runchroot, digests)) {
/* XXX - log functions not available but we should log very loudly */
goto bad;
}

View File

@ -28,6 +28,7 @@
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -38,13 +39,15 @@
#include <gram.h>
bool
digest_matches(int fd, const char *file, const struct command_digest_list *digests)
digest_matches(int fd, const char *path, const char *runchroot,
const struct command_digest_list *digests)
{
unsigned int digest_type = SUDO_DIGEST_INVALID;
unsigned char *file_digest = NULL;
unsigned char *sudoers_digest = NULL;
struct command_digest *digest;
size_t digest_len = (size_t)-1;
char pathbuf[PATH_MAX];
bool matched = false;
debug_decl(digest_matches, SUDOERS_DEBUG_MATCH);
@ -58,11 +61,21 @@ digest_matches(int fd, const char *file, const struct command_digest_list *diges
goto done;
}
if (runchroot != NULL) {
const int len =
snprintf(pathbuf, sizeof(pathbuf), "%s%s", runchroot, path);
if (len >= ssizeof(pathbuf)) {
errno = ENAMETOOLONG;
debug_return_bool(false);
}
path = pathbuf;
}
TAILQ_FOREACH(digest, digests, entries) {
/* Compute file digest if needed. */
if (digest->digest_type != digest_type) {
free(file_digest);
file_digest = sudo_filedigest(fd, file, digest->digest_type,
file_digest = sudo_filedigest(fd, path, digest->digest_type,
&digest_len);
if (lseek(fd, (off_t)0, SEEK_SET) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
@ -106,14 +119,14 @@ digest_matches(int fd, const char *file, const struct command_digest_list *diges
sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
"%s digest mismatch for %s, expecting %s",
digest_type_to_name(digest->digest_type), file, digest->digest_str);
digest_type_to_name(digest->digest_type), path, digest->digest_str);
free(sudoers_digest);
sudoers_digest = NULL;
}
goto done;
bad_format:
sudo_warnx(U_("digest for %s (%s) is not in %s form"), file,
sudo_warnx(U_("digest for %s (%s) is not in %s form"), path,
digest->digest_str, digest_type_to_name(digest->digest_type));
done:
free(sudoers_digest);

View File

@ -325,7 +325,7 @@ bool addr_matches(char *n);
bool command_matches(const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, struct cmnd_info *info, const struct command_digest_list *digests);
/* match_digest.c */
bool digest_matches(int fd, const char *file, const struct command_digest_list *digests);
bool digest_matches(int fd, const char *path, const char *runchroot, const struct command_digest_list *digests);
/* match.c */
struct group;