2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-31 06:15:37 +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 || if (user_stat == NULL ||
(user_stat->st_dev == sudoers_stat.st_dev && (user_stat->st_dev == sudoers_stat.st_dev &&
user_stat->st_ino == sudoers_stat.st_ino)) { 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; continue;
free(safe_cmnd); free(safe_cmnd);
if ((safe_cmnd = strdup(buf + chrootlen)) == NULL) { 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. */ /* 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; goto bad;
set_cmnd_fd(fd); 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)) if (!do_stat(fd, user_cmnd, runchroot, &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_matches(fd, user_cmnd, digests)) if (!digest_matches(fd, user_cmnd, runchroot, digests))
goto bad; goto bad;
set_cmnd_fd(fd); 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_dev == sudoers_stat.st_dev &&
user_stat->st_ino == sudoers_stat.st_ino)) { user_stat->st_ino == sudoers_stat.st_ino)) {
/* There could be multiple matches, check digest early. */ /* There could be multiple matches, check digest early. */
if (!digest_matches(fd, cp, digests)) { if (!digest_matches(fd, cp, runchroot, digests)) {
bad_digest = true; bad_digest = true;
continue; continue;
} }
@@ -490,7 +491,7 @@ command_matches_glob(const char *sudoers_cmnd, const char *sudoers_args,
if (user_stat == NULL || if (user_stat == NULL ||
(user_stat->st_dev == sudoers_stat.st_dev && (user_stat->st_dev == sudoers_stat.st_dev &&
user_stat->st_ino == sudoers_stat.st_ino)) { user_stat->st_ino == sudoers_stat.st_ino)) {
if (!digest_matches(fd, cp, digests)) if (!digest_matches(fd, cp, runchroot, digests))
continue; continue;
free(safe_cmnd); free(safe_cmnd);
if ((safe_cmnd = strdup(cp)) == NULL) { 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)) if (!command_args_match(sudoers_cmnd, sudoers_args))
goto bad; 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 */ /* XXX - log functions not available but we should log very loudly */
goto bad; goto bad;
} }

View File

@@ -28,6 +28,7 @@
#include <config.h> #include <config.h>
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -38,13 +39,15 @@
#include <gram.h> #include <gram.h>
bool 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 int digest_type = SUDO_DIGEST_INVALID;
unsigned char *file_digest = NULL; unsigned char *file_digest = NULL;
unsigned char *sudoers_digest = NULL; unsigned char *sudoers_digest = NULL;
struct command_digest *digest; struct command_digest *digest;
size_t digest_len = (size_t)-1; size_t digest_len = (size_t)-1;
char pathbuf[PATH_MAX];
bool matched = false; bool matched = false;
debug_decl(digest_matches, SUDOERS_DEBUG_MATCH); 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; 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) { TAILQ_FOREACH(digest, digests, entries) {
/* Compute file digest if needed. */ /* Compute file digest if needed. */
if (digest->digest_type != digest_type) { if (digest->digest_type != digest_type) {
free(file_digest); free(file_digest);
file_digest = sudo_filedigest(fd, file, digest->digest_type, file_digest = sudo_filedigest(fd, path, digest->digest_type,
&digest_len); &digest_len);
if (lseek(fd, (off_t)0, SEEK_SET) == -1) { if (lseek(fd, (off_t)0, SEEK_SET) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, 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, sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
"%s digest mismatch for %s, expecting %s", "%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); free(sudoers_digest);
sudoers_digest = NULL; sudoers_digest = NULL;
} }
goto done; goto done;
bad_format: 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)); digest->digest_str, digest_type_to_name(digest->digest_type));
done: done:
free(sudoers_digest); 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); 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 */ /* 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 */ /* match.c */
struct group; struct group;