diff -Nur ./src/parse_args.c.heap-buffer ./src/parse_args.c --- ./src/parse_args.c.heap-buffer 2012-09-18 09:57:43.000000000 -0400 +++ ./src/parse_args.c 2021-02-05 15:19:50.450000000 -0500 @@ -113,6 +113,13 @@ }; /* +* Default flags allowed when running a command. +*/ +#define DEFAULT_VALID_FLAGS (MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_PRESERVE_GROUPS|MODE_SHELL) +#define EDIT_VALID_FLAGS MODE_NONINTERACTIVE +#define LIST_VALID_FLAGS (MODE_NONINTERACTIVE|MODE_LONG_LIST) +#define VALIDATE_VALID_FLAGS MODE_NONINTERACTIVE +/* * Command line argument parsing. * Sets nargc and nargv which corresponds to the argc/argv we'll use * for the command to be run (if we are running one). @@ -140,6 +147,7 @@ if (strcmp(getprogname(), "sudoedit") == 0) { mode = MODE_EDIT; sudo_settings[ARG_SUDOEDIT].value = "true"; + valid_flags = EDIT_VALID_FLAGS; } /* Load local IP addresses and masks. */ @@ -205,7 +213,7 @@ usage_excl(1); mode = MODE_EDIT; sudo_settings[ARG_SUDOEDIT].value = "true"; - valid_flags = MODE_NONINTERACTIVE; + valid_flags = EDIT_VALID_FLAGS; break; case 'g': runas_group = optarg; @@ -213,6 +221,7 @@ break; case 'H': sudo_settings[ARG_SET_HOME].value = "true"; + SET(flags, MODE_RESET_HOME); break; case 'h': if (mode && mode != MODE_HELP) { @@ -244,7 +253,7 @@ usage_excl(1); } mode = MODE_LIST; - valid_flags = MODE_NONINTERACTIVE|MODE_LONG_LIST; + valid_flags = LIST_VALID_FLAGS; break; case 'n': SET(flags, MODE_NONINTERACTIVE); @@ -252,6 +261,7 @@ break; case 'P': sudo_settings[ARG_PRESERVE_GROUPS].value = "true"; + SET(flags, MODE_PRESERVE_GROUPS); break; case 'p': sudo_settings[ARG_PROMPT].value = optarg; @@ -284,7 +294,7 @@ if (mode && mode != MODE_VALIDATE) usage_excl(1); mode = MODE_VALIDATE; - valid_flags = MODE_NONINTERACTIVE; + valid_flags = VALIDATE_VALID_FLAGS; break; case 'V': if (mode && mode != MODE_VERSION) @@ -317,7 +327,7 @@ if (!mode) { /* Defer -k mode setting until we know whether it is a flag or not */ if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) { - if (argc == 0 && !(flags & (MODE_SHELL|MODE_LOGIN_SHELL))) { + if (argc == 0 && !ISSET(flags, MODE_SHELL|MODE_LOGIN_SHELL)) { mode = MODE_INVALIDATE; /* -k by itself */ sudo_settings[ARG_IGNORE_TICKET].value = NULL; valid_flags = 0; @@ -377,18 +387,22 @@ /* * For shell mode we need to rewrite argv */ - if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { + if (ISSET(flags, MODE_SHELL|MODE_LOGIN_SHELL) && ISSET(mode, MODE_RUN)) { char **av, *cmnd = NULL; int ac = 1; if (argc != 0) { /* shell -c "command" */ char *src, *dst; - size_t cmnd_size = (size_t) (argv[argc - 1] - argv[0]) + - strlen(argv[argc - 1]) + 1; + size_t size = 0; + + for (av = argv; *av != NULL; av++) + size += strlen(*av) + 1; + + if (size == 0 || (cmnd = emalloc2(size, 2)) == NULL) + exit(1); - cmnd = dst = emalloc2(cmnd_size, 2); - for (av = argv; *av != NULL; av++) { + for (dst = cmnd, av = argv; *av != NULL; av++) { for (src = *av; *src != '\0'; src++) { /* quote potential meta characters */ if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-') diff -Nur ./plugins/sudoers/sudoers.c.heap-buffer ./plugins/sudoers/sudoers.c --- ./plugins/sudoers/sudoers.c.heap-buffer 2021-02-04 14:45:39.357000000 -0500 +++ ./plugins/sudoers/sudoers.c 2021-02-04 16:48:14.670000000 -0500 @@ -492,7 +492,7 @@ /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ /* XXX - causes confusion when root is not listed in sudoers */ - if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) { + if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT) && prev_user != NULL) { if (user_uid == 0 && strcmp(prev_user, "root") != 0) { struct passwd *pw; @@ -927,8 +927,8 @@ if (user_cmnd == NULL) user_cmnd = NewArgv[0]; - if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { - if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) { + if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT|MODE_CHECK)) { + if (!ISSET(sudo_mode, MODE_EDIT)) { if (def_secure_path && !user_is_exempt()) path = def_secure_path; set_perms(PERM_RUNAS); @@ -953,7 +953,8 @@ for (size = 0, av = NewArgv + 1; *av; av++) size += strlen(*av) + 1; user_args = emalloc(size); - if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { + if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL) && + ISSET(sudo_mode, MODE_RUN)) { /* * When running a command via a shell, the sudo front-end * escapes potential meta chars. We unescape non-spaces @@ -961,10 +962,18 @@ */ for (to = user_args, av = NewArgv + 1; (from = *av); av++) { while (*from) { - if (from[0] == '\\' && !isspace((unsigned char)from[1])) + if (from[0] == '\\' && from[1] != '\0' && + !isspace((unsigned char)from[1])) { from++; + } + if (size - (to - user_args) < 1) { + errorx(1, _("internal error, %s overflow"), __func__); /*debug_return_int(3);NOT_FOUND_ERROR*/ + } *to++ = *from++; } + if (size - (to - user_args) < 1) { + errorx(1, _("internal error, %s overflow"), __func__); /*debug_return_int(3);NOT_FOUND_ERROR*/ + } *to++ = ' '; } *--to = '\0';