diff --git a/plugins/sudoers/match_command.c b/plugins/sudoers/match_command.c index c9fd3efc8..8a31cf422 100644 --- a/plugins/sudoers/match_command.c +++ b/plugins/sudoers/match_command.c @@ -806,7 +806,7 @@ command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd, const struct command_digest_list *digests) { const bool intercepted = info ? info->intercepted : false; - int pivot_fds[2] = { -1, -1 }; + sudoers_pivot_t pivot_state = SUDOERS_PIVOT_INITIALIZER; char *saved_user_cmnd = NULL; struct stat saved_user_stat; bool reset_cmnd = false; @@ -832,7 +832,7 @@ command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd, /* Pivot root. */ if (runchroot != NULL) { - if (!pivot_root(runchroot, pivot_fds)) + if (!pivot_root(runchroot, pivot_state)) goto done; } @@ -856,14 +856,15 @@ command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd, if (sudoers_cmnd == NULL) { sudoers_cmnd = "ALL"; - ret = command_matches_all(ctx, pivot_fds[0], intercepted, digests); + ret = command_matches_all(ctx, pivot_get_root(pivot_state), + intercepted, digests); goto done; } /* Check for regular expressions first. */ if (sudoers_cmnd[0] == '^') { ret = command_matches_regex(ctx, sudoers_cmnd, sudoers_args, - pivot_fds[0], intercepted, digests); + pivot_get_root(pivot_state), intercepted, digests); goto done; } @@ -893,19 +894,19 @@ command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd, */ if (def_fast_glob) { ret = command_matches_fnmatch(ctx, sudoers_cmnd, sudoers_args, - pivot_fds[0], intercepted, digests); + pivot_get_root(pivot_state), intercepted, digests); } else { ret = command_matches_glob(ctx, sudoers_cmnd, sudoers_args, - pivot_fds[0], intercepted, digests); + pivot_get_root(pivot_state), intercepted, digests); } } else { ret = command_matches_normal(ctx, sudoers_cmnd, sudoers_args, - pivot_fds[0], intercepted, digests); + pivot_get_root(pivot_state), intercepted, digests); } done: /* Restore root. */ if (runchroot != NULL) - (void)unpivot_root(pivot_fds); + (void)unpivot_root(pivot_state); /* Restore ctx->user.cmnd and ctx->user.cmnd_stat. */ if (saved_user_cmnd != NULL) { diff --git a/plugins/sudoers/pivot.c b/plugins/sudoers/pivot.c index b314779a9..28bb2d6e2 100644 --- a/plugins/sudoers/pivot.c +++ b/plugins/sudoers/pivot.c @@ -29,29 +29,26 @@ #include "sudoers.h" -#define OLD_ROOT 0 -#define OLD_CWD 1 - /* * Pivot to a new root directory, storing the old root and old cwd - * in fds[2]. Changes current working directory to the new root. + * in state. Changes current working directory to the new root. * Returns true on success, else false. */ bool -pivot_root(const char *new_root, int fds[2]) +pivot_root(const char *new_root, sudoers_pivot_t state) { debug_decl(pivot_root, SUDOERS_DEBUG_UTIL); - fds[OLD_ROOT] = open("/", O_RDONLY); - fds[OLD_CWD] = open(".", O_RDONLY); - if (fds[OLD_ROOT] == -1 || fds[OLD_CWD] == -1 || chroot(new_root) == -1) { - if (fds[OLD_ROOT] != -1) { - close(fds[OLD_ROOT]); - fds[OLD_ROOT] = -1; + state.saved_root = open("/", O_RDONLY); + state.saved_cwd = open(".", O_RDONLY); + if (state.saved_root == -1 || state.saved_cwd == -1 || chroot(new_root) == -1) { + if (state.saved_root != -1) { + close(state.saved_root); + state.saved_root = -1; } - if (fds[OLD_CWD] != -1) { - close(fds[OLD_CWD]); - fds[OLD_CWD] = -1; + if (state.saved_cwd != -1) { + close(state.saved_cwd); + state.saved_cwd = -1; } debug_return_bool(false); } @@ -63,28 +60,40 @@ pivot_root(const char *new_root, int fds[2]) * Returns true on success, else false. */ bool -unpivot_root(int fds[2]) +unpivot_root(sudoers_pivot_t state) { bool ret = true; debug_decl(unpivot_root, SUDOERS_DEBUG_UTIL); /* Order is important: restore old root, *then* change cwd. */ - if (fds[OLD_ROOT] != -1) { - if (fchdir(fds[OLD_ROOT]) == -1 || chroot(".") == -1) { + if (state.saved_root != -1) { + if (fchdir(state.saved_root) == -1 || chroot(".") == -1) { sudo_warn("%s", U_("unable to restore root directory")); ret = false; } - close(fds[OLD_ROOT]); - fds[OLD_ROOT] = -1; + close(state.saved_root); + state.saved_root = -1; } - if (fds[OLD_CWD] != -1) { - if (fchdir(fds[OLD_CWD]) == -1) { + if (state.saved_cwd != -1) { + if (fchdir(state.saved_cwd) == -1) { sudo_warn("%s", U_("unable to restore current working directory")); ret = false; } - close(fds[OLD_CWD]); - fds[OLD_CWD] = -1; + close(state.saved_cwd); + state.saved_cwd = -1; } debug_return_bool(ret); } + +int +pivot_get_root(sudoers_pivot_t state) +{ + return state.saved_root; +} + +int +pivot_get_cwd(sudoers_pivot_t state) +{ + return state.saved_cwd; +} diff --git a/plugins/sudoers/regress/fuzz/fuzz_stubs.c b/plugins/sudoers/regress/fuzz/fuzz_stubs.c index e1e060aef..14805476c 100644 --- a/plugins/sudoers/regress/fuzz/fuzz_stubs.c +++ b/plugins/sudoers/regress/fuzz/fuzz_stubs.c @@ -58,17 +58,29 @@ init_eventlog_config(void) } bool -pivot_root(const char *new_root, int fds[2]) +pivot_root(const char *new_root, sudoers_pivot_t state) { return true; } bool -unpivot_root(int fds[2]) +unpivot_root(sudoers_pivot_t state) { return true; } +int +pivot_get_root(sudoers_pivot_t state) +{ + return -1; +} + +int +pivot_get_cwd(sudoers_pivot_t state) +{ + return -1; +} + int group_plugin_query(const char *user, const char *group, const struct passwd *pw) { diff --git a/plugins/sudoers/stubs.c b/plugins/sudoers/stubs.c index 850ccf43d..8dff27dd4 100644 --- a/plugins/sudoers/stubs.c +++ b/plugins/sudoers/stubs.c @@ -98,14 +98,28 @@ init_eventlog_config(void) /* STUB */ bool -pivot_root(const char *new_root, int fds[2]) +pivot_root(const char *new_root, sudoers_pivot_t state) { return true; } /* STUB */ bool -unpivot_root(int fds[2]) +unpivot_root(sudoers_pivot_t state) { return true; } + +/* STUB */ +int +pivot_get_root(sudoers_pivot_t state) +{ + return -1; +} + +/* STUB */ +int +pivot_get_cwd(sudoers_pivot_t state) +{ + return -1; +} diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index d4515f903..ac3e96f79 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -1062,10 +1062,11 @@ init_vars(struct sudoers_context *ctx, char * const envp[]) int set_cmnd_path(struct sudoers_context *ctx, const char *runchroot) { + sudoers_pivot_t pivot_state = SUDOERS_PIVOT_INITIALIZER; const char *cmnd_in; char *cmnd_out = NULL; char *path = ctx->user.path; - int ret, pivot_fds[2]; + int ret; debug_decl(set_cmnd_path, SUDOERS_DEBUG_PLUGIN); cmnd_in = ISSET(ctx->mode, MODE_CHECK) ? @@ -1082,7 +1083,7 @@ set_cmnd_path(struct sudoers_context *ctx, const char *runchroot) /* Pivot root. */ if (runchroot != NULL) { - if (!pivot_root(runchroot, pivot_fds)) + if (!pivot_root(runchroot, pivot_state)) goto error; } @@ -1120,12 +1121,12 @@ set_cmnd_path(struct sudoers_context *ctx, const char *runchroot) /* Restore root. */ if (runchroot != NULL) - (void)unpivot_root(pivot_fds); + (void)unpivot_root(pivot_state); debug_return_int(ret); error: if (runchroot != NULL) - (void)unpivot_root(pivot_fds); + (void)unpivot_root(pivot_state); free(cmnd_out); debug_return_int(NOT_FOUND_ERROR); } diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index a1244072c..032e62fcb 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -49,6 +49,7 @@ #include "defaults.h" #include "logging.h" #include "parse.h" +#include "pivot.h" /* * Info passed in from the sudo front-end. @@ -494,10 +495,6 @@ void unescape_string(char *str); /* serialize_list.c */ char *serialize_list(const char *varname, struct list_members *members); -/* pivot_root.c */ -bool pivot_root(const char *new_root, int fds[2]); -bool unpivot_root(int fds[2]); - /* sethost.c */ bool sudoers_sethost(struct sudoers_context *ctx, const char *host, const char *remhost); diff --git a/plugins/sudoers/testsudoers.c b/plugins/sudoers/testsudoers.c index 622bc2c78..d7bf218c2 100644 --- a/plugins/sudoers/testsudoers.c +++ b/plugins/sudoers/testsudoers.c @@ -605,17 +605,29 @@ init_eventlog_config(void) } bool -pivot_root(const char *new_root, int fds[2]) +pivot_root(const char *new_root, sudoers_pivot_t state) { return true; } bool -unpivot_root(int fds[2]) +unpivot_root(sudoers_pivot_t state) { return true; } +int +pivot_get_root(sudoers_pivot_t state) +{ + return -1; +} + +int +pivot_get_cwd(sudoers_pivot_t state) +{ + return -1; +} + int set_cmnd_path(struct sudoers_context *ctx, const char *runchroot) {