Always dynamically allocate user_cmnd, it is freed in sudo_user_free().
Instead of setting user_cmnd in the policy functions, always set argv. Calling sudoers_policy_main() with argc of 0 is no longer allowed.
This commit is contained in:
@@ -348,6 +348,7 @@ sudoers_policy_deserialize_info(void *v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Sudo front-end should restrict mode flags for sudoedit. */
|
/* Sudo front-end should restrict mode flags for sudoedit. */
|
||||||
|
/* XXX - also restrict pseudo-commands */
|
||||||
if (ISSET(flags, MODE_EDIT) && (flags & edit_mask) != flags) {
|
if (ISSET(flags, MODE_EDIT) && (flags & edit_mask) != flags) {
|
||||||
sudo_warnx(U_("invalid mode flags from sudo front end: 0x%x"), flags);
|
sudo_warnx(U_("invalid mode flags from sudo front end: 0x%x"), flags);
|
||||||
goto bad;
|
goto bad;
|
||||||
@@ -976,6 +977,8 @@ sudoers_policy_close(int exit_status, int error_code)
|
|||||||
free(audit_msg);
|
free(audit_msg);
|
||||||
audit_msg = NULL;
|
audit_msg = NULL;
|
||||||
|
|
||||||
|
/* XXX - leaks NewArgv */
|
||||||
|
|
||||||
/* sudoers_debug_deregister() calls sudo_debug_exit() for us. */
|
/* sudoers_debug_deregister() calls sudo_debug_exit() for us. */
|
||||||
sudoers_debug_deregister();
|
sudoers_debug_deregister();
|
||||||
}
|
}
|
||||||
@@ -1045,13 +1048,13 @@ sudoers_policy_check(int argc, char * const argv[], char *env_add[],
|
|||||||
static int
|
static int
|
||||||
sudoers_policy_validate(const char **errstr)
|
sudoers_policy_validate(const char **errstr)
|
||||||
{
|
{
|
||||||
|
char *argv[] = { "validate", NULL };
|
||||||
|
const int argc = 1;
|
||||||
int ret;
|
int ret;
|
||||||
debug_decl(sudoers_policy_validate, SUDOERS_DEBUG_PLUGIN);
|
debug_decl(sudoers_policy_validate, SUDOERS_DEBUG_PLUGIN);
|
||||||
|
|
||||||
user_cmnd = "validate";
|
|
||||||
SET(sudo_mode, MODE_VALIDATE);
|
SET(sudo_mode, MODE_VALIDATE);
|
||||||
|
ret = sudoers_policy_main(argc, argv, I_VERIFYPW, NULL, false, NULL);
|
||||||
ret = sudoers_policy_main(0, NULL, I_VERIFYPW, NULL, false, NULL);
|
|
||||||
|
|
||||||
/* The audit functions set audit_msg on failure. */
|
/* The audit functions set audit_msg on failure. */
|
||||||
if (ret != 1 && audit_msg != NULL) {
|
if (ret != 1 && audit_msg != NULL) {
|
||||||
@@ -1075,14 +1078,17 @@ static int
|
|||||||
sudoers_policy_list(int argc, char * const argv[], int verbose,
|
sudoers_policy_list(int argc, char * const argv[], int verbose,
|
||||||
const char *list_user, const char **errstr)
|
const char *list_user, const char **errstr)
|
||||||
{
|
{
|
||||||
|
char *list_argv[] = { "list", NULL };
|
||||||
int ret;
|
int ret;
|
||||||
debug_decl(sudoers_policy_list, SUDOERS_DEBUG_PLUGIN);
|
debug_decl(sudoers_policy_list, SUDOERS_DEBUG_PLUGIN);
|
||||||
|
|
||||||
user_cmnd = "list";
|
if (argc == 0) {
|
||||||
if (argc)
|
|
||||||
SET(sudo_mode, MODE_CHECK);
|
|
||||||
else
|
|
||||||
SET(sudo_mode, MODE_LIST);
|
SET(sudo_mode, MODE_LIST);
|
||||||
|
argc = 1;
|
||||||
|
argv = list_argv;
|
||||||
|
} else {
|
||||||
|
SET(sudo_mode, MODE_CHECK);
|
||||||
|
}
|
||||||
if (list_user) {
|
if (list_user) {
|
||||||
list_pw = sudo_getpwnam(list_user);
|
list_pw = sudo_getpwnam(list_user);
|
||||||
if (list_pw == NULL) {
|
if (list_pw == NULL) {
|
||||||
|
@@ -302,7 +302,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First argv entry is the command, the rest are args. */
|
/* Additional environment variables to add. */
|
||||||
if (strncmp(line, "env=", sizeof("env=") - 1) == 0) {
|
if (strncmp(line, "env=", sizeof("env=") - 1) == 0) {
|
||||||
push(&env_add, line);
|
push(&env_add, line);
|
||||||
continue;
|
continue;
|
||||||
@@ -340,10 +340,6 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Avoid double free of user_cmnd, it will be freed as part of argv. */
|
|
||||||
if (argv.len != 0 && user_cmnd == argv.entries[0])
|
|
||||||
user_cmnd = NULL;
|
|
||||||
|
|
||||||
/* Free resources. */
|
/* Free resources. */
|
||||||
sudoers_policy.close(0, 0);
|
sudoers_policy.close(0, 0);
|
||||||
|
|
||||||
@@ -639,7 +635,7 @@ find_path(const char *infile, char **outfile, struct stat *sbp,
|
|||||||
if (asprintf(outfile, "/usr/bin/%s", infile) == -1)
|
if (asprintf(outfile, "/usr/bin/%s", infile) == -1)
|
||||||
*outfile = NULL;
|
*outfile = NULL;
|
||||||
}
|
}
|
||||||
return *outfile ? FOUND : NOT_FOUND;
|
return *outfile ? FOUND : NOT_FOUND_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STUB */
|
/* STUB */
|
||||||
|
@@ -341,6 +341,11 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
|
|
||||||
sudo_warn_set_locale_func(sudoers_warn_setlocale);
|
sudo_warn_set_locale_func(sudoers_warn_setlocale);
|
||||||
|
|
||||||
|
if (argc == 0) {
|
||||||
|
sudo_warnx("%s", U_("no command specified"));
|
||||||
|
debug_return_int(-1);
|
||||||
|
}
|
||||||
|
|
||||||
unlimit_nproc();
|
unlimit_nproc();
|
||||||
|
|
||||||
/* Is root even allowed to run sudo? */
|
/* Is root even allowed to run sudo? */
|
||||||
@@ -360,38 +365,26 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Make a local copy of argc/argv, with special handling
|
* Make a local copy of argc/argv, with special handling
|
||||||
* for pseudo-commands and the '-i' option.
|
* for the '-i' option.
|
||||||
*/
|
*/
|
||||||
if (argc == 0) {
|
/* Must leave an extra slot before NewArgv for bash's --login */
|
||||||
NewArgc = 1;
|
NewArgc = argc;
|
||||||
NewArgv = reallocarray(NULL, NewArgc + 1, sizeof(char *));
|
NewArgv = reallocarray(NULL, NewArgc + 2, sizeof(char *));
|
||||||
if (NewArgv == NULL) {
|
if (NewArgv == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
sudoers_gc_add(GC_PTR, NewArgv);
|
||||||
|
NewArgv++; /* reserve an extra slot for --login */
|
||||||
|
memcpy(NewArgv, argv, argc * sizeof(char *));
|
||||||
|
NewArgv[NewArgc] = NULL;
|
||||||
|
if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && runas_pw != NULL) {
|
||||||
|
NewArgv[0] = strdup(runas_pw->pw_shell);
|
||||||
|
if (NewArgv[0] == NULL) {
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sudoers_gc_add(GC_PTR, NewArgv);
|
sudoers_gc_add(GC_PTR, NewArgv[0]);
|
||||||
NewArgv[0] = user_cmnd;
|
|
||||||
NewArgv[1] = NULL;
|
|
||||||
} else {
|
|
||||||
/* Must leave an extra slot before NewArgv for bash's --login */
|
|
||||||
NewArgc = argc;
|
|
||||||
NewArgv = reallocarray(NULL, NewArgc + 2, sizeof(char *));
|
|
||||||
if (NewArgv == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
sudoers_gc_add(GC_PTR, NewArgv);
|
|
||||||
NewArgv++; /* reserve an extra slot for --login */
|
|
||||||
memcpy(NewArgv, argv, argc * sizeof(char *));
|
|
||||||
NewArgv[NewArgc] = NULL;
|
|
||||||
if (ISSET(sudo_mode, MODE_LOGIN_SHELL) && runas_pw != NULL) {
|
|
||||||
NewArgv[0] = strdup(runas_pw->pw_shell);
|
|
||||||
if (NewArgv[0] == NULL) {
|
|
||||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
sudoers_gc_add(GC_PTR, NewArgv[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If given the -P option, set the "preserve_groups" flag. */
|
/* If given the -P option, set the "preserve_groups" flag. */
|
||||||
@@ -930,10 +923,6 @@ set_cmnd(void)
|
|||||||
debug_return_int(NOT_FOUND_ERROR);
|
debug_return_int(NOT_FOUND_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default value for cmnd, overridden by set_cmnd_path() below. */
|
|
||||||
if (user_cmnd == NULL)
|
|
||||||
user_cmnd = NewArgv[0];
|
|
||||||
|
|
||||||
if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT|MODE_CHECK)) {
|
if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT|MODE_CHECK)) {
|
||||||
if (!ISSET(sudo_mode, MODE_EDIT)) {
|
if (!ISSET(sudo_mode, MODE_EDIT)) {
|
||||||
const char *runchroot = user_runchroot;
|
const char *runchroot = user_runchroot;
|
||||||
@@ -968,14 +957,26 @@ set_cmnd(void)
|
|||||||
debug_return_int(NOT_FOUND_ERROR);
|
debug_return_int(NOT_FOUND_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (user_cmnd == NULL) {
|
||||||
|
user_cmnd = strdup(NewArgv[0]);
|
||||||
|
if (user_cmnd == NULL)
|
||||||
|
debug_return_int(NOT_FOUND_ERROR);
|
||||||
|
}
|
||||||
user_base = sudo_basename(user_cmnd);
|
user_base = sudo_basename(user_cmnd);
|
||||||
|
|
||||||
/* Convert "sudo sudoedit" -> "sudoedit" */
|
/* Convert "sudo sudoedit" -> "sudoedit" */
|
||||||
if (ISSET(sudo_mode, MODE_RUN) && strcmp(user_base, "sudoedit") == 0) {
|
if (ISSET(sudo_mode, MODE_RUN) && strcmp(user_base, "sudoedit") == 0) {
|
||||||
|
char *new_cmnd;
|
||||||
|
|
||||||
CLR(sudo_mode, MODE_RUN);
|
CLR(sudo_mode, MODE_RUN);
|
||||||
SET(sudo_mode, MODE_EDIT);
|
SET(sudo_mode, MODE_EDIT);
|
||||||
sudo_warnx("%s", U_("sudoedit doesn't need to be run via sudo"));
|
sudo_warnx("%s", U_("sudoedit doesn't need to be run via sudo"));
|
||||||
user_base = user_cmnd = "sudoedit";
|
if ((new_cmnd = strdup("sudoedit")) == NULL) {
|
||||||
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||||
|
debug_return_int(NOT_FOUND_ERROR);
|
||||||
|
}
|
||||||
|
free(user_cmnd);
|
||||||
|
user_base = user_cmnd = new_cmnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(nss, snl, entries) {
|
TAILQ_FOREACH(nss, snl, entries) {
|
||||||
|
Reference in New Issue
Block a user