You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
8.0 KiB
207 lines
8.0 KiB
diff -up ./plugins/sudoers/policy.c.heap-buffer ./plugins/sudoers/policy.c |
|
--- ./plugins/sudoers/policy.c.heap-buffer 2021-01-20 13:10:29.368619293 +0100 |
|
+++ ./plugins/sudoers/policy.c 2021-01-20 15:56:12.915095745 +0100 |
|
@@ -93,11 +93,12 @@ parse_bool(const char *line, int varlen, |
|
int |
|
sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group) |
|
{ |
|
+ const int edit_mask = MODE_EDIT|MODE_IGNORE_TICKET|MODE_NONINTERACTIVE; |
|
struct sudoers_policy_open_info *info = v; |
|
- char * const *cur; |
|
const char *p, *errstr, *groups = NULL; |
|
const char *remhost = NULL; |
|
bool uid_set = false, gid_set = false; |
|
+ char * const *cur; |
|
int flags = 0; |
|
debug_decl(sudoers_policy_deserialize_info, SUDOERS_DEBUG_PLUGIN) |
|
|
|
@@ -326,6 +327,12 @@ sudoers_policy_deserialize_info(void *v, |
|
#endif |
|
} |
|
|
|
+ /* Sudo front-end should restrict mode flags for sudoedit. */ |
|
+ if (ISSET(flags, MODE_EDIT) && (flags & edit_mask) != flags) { |
|
+ sudo_warnx(U_("invalid mode flags from sudo front end: 0x%x"), flags); |
|
+ goto bad; |
|
+ } |
|
+ |
|
user_umask = (mode_t)-1; |
|
for (cur = info->user_info; *cur != NULL; cur++) { |
|
if (MATCHES(*cur, "user=")) { |
|
diff -up ./plugins/sudoers/sudoers.c.heap-buffer ./plugins/sudoers/sudoers.c |
|
--- ./plugins/sudoers/sudoers.c.heap-buffer 2021-01-20 13:10:29.350619537 +0100 |
|
+++ ./plugins/sudoers/sudoers.c 2021-01-20 13:10:29.369619280 +0100 |
|
@@ -416,7 +416,7 @@ sudoers_policy_main(int argc, char * con |
|
|
|
/* 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; |
|
|
|
@@ -796,8 +796,8 @@ set_cmnd(void) |
|
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; |
|
if (!set_perms(PERM_RUNAS)) |
|
@@ -835,7 +835,8 @@ set_cmnd(void) |
|
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
|
debug_return_int(-1); |
|
} |
|
- 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 |
|
@@ -843,10 +844,22 @@ set_cmnd(void) |
|
*/ |
|
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) { |
|
+ sudo_warnx(U_("internal error, %s overflow"), |
|
+ __func__); |
|
+ debug_return_int(NOT_FOUND_ERROR); |
|
+ } |
|
*to++ = *from++; |
|
} |
|
+ if (size - (to - user_args) < 1) { |
|
+ sudo_warnx(U_("internal error, %s overflow"), |
|
+ __func__); |
|
+ debug_return_int(NOT_FOUND_ERROR); |
|
+ } |
|
*to++ = ' '; |
|
} |
|
*--to = '\0'; |
|
diff -up ./plugins/sudoers/timestamp.c.heap-buffer ./plugins/sudoers/timestamp.c |
|
--- ./plugins/sudoers/timestamp.c.heap-buffer 2018-09-02 14:30:08.000000000 +0200 |
|
+++ ./plugins/sudoers/timestamp.c 2021-01-20 13:10:29.369619280 +0100 |
|
@@ -646,8 +646,8 @@ timestamp_lock(void *vcookie, struct pas |
|
} else if (entry.type != TS_LOCKEXCL) { |
|
/* Old sudo record, convert it to TS_LOCKEXCL. */ |
|
entry.type = TS_LOCKEXCL; |
|
- memset((char *)&entry + offsetof(struct timestamp_entry, type), 0, |
|
- nread - offsetof(struct timestamp_entry, type)); |
|
+ memset((char *)&entry + offsetof(struct timestamp_entry, flags), 0, |
|
+ nread - offsetof(struct timestamp_entry, flags)); |
|
if (ts_write(cookie->fd, cookie->fname, &entry, 0) == -1) |
|
debug_return_bool(false); |
|
} |
|
diff -up ./src/parse_args.c.heap-buffer ./src/parse_args.c |
|
--- ./src/parse_args.c.heap-buffer 2018-08-18 16:10:25.000000000 +0200 |
|
+++ ./src/parse_args.c 2021-01-20 16:01:42.500778441 +0100 |
|
@@ -116,7 +116,10 @@ struct environment { |
|
/* |
|
* 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_SHELL) |
|
+#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 |
|
|
|
/* Option number for the --host long option due to ambiguity of the -h flag. */ |
|
#define OPT_HOSTNAME 256 |
|
@@ -260,6 +263,7 @@ parse_args(int argc, char **argv, int *n |
|
progname = "sudoedit"; |
|
mode = MODE_EDIT; |
|
sudo_settings[ARG_SUDOEDIT].value = "true"; |
|
+ valid_flags = EDIT_VALID_FLAGS; |
|
} |
|
|
|
/* Load local IP addresses and masks. */ |
|
@@ -345,7 +349,7 @@ parse_args(int argc, char **argv, int *n |
|
usage_excl(1); |
|
mode = MODE_EDIT; |
|
sudo_settings[ARG_SUDOEDIT].value = "true"; |
|
- valid_flags = MODE_NONINTERACTIVE; |
|
+ valid_flags = EDIT_VALID_FLAGS; |
|
break; |
|
case 'g': |
|
if (*optarg == '\0') |
|
@@ -355,6 +359,7 @@ parse_args(int argc, char **argv, int *n |
|
break; |
|
case 'H': |
|
sudo_settings[ARG_SET_HOME].value = "true"; |
|
+ SET(flags, MODE_RESET_HOME); |
|
break; |
|
case 'h': |
|
if (optarg == NULL) { |
|
@@ -404,7 +409,7 @@ parse_args(int argc, char **argv, int *n |
|
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); |
|
@@ -412,6 +417,7 @@ parse_args(int argc, char **argv, int *n |
|
break; |
|
case 'P': |
|
sudo_settings[ARG_PRESERVE_GROUPS].value = "true"; |
|
+ SET(flags, MODE_PRESERVE_GROUPS); |
|
break; |
|
case 'p': |
|
/* An empty prompt is allowed. */ |
|
@@ -455,7 +461,7 @@ parse_args(int argc, char **argv, int *n |
|
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) |
|
@@ -482,7 +488,7 @@ parse_args(int argc, char **argv, int *n |
|
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; |
|
@@ -545,23 +551,24 @@ parse_args(int argc, char **argv, int *n |
|
/* |
|
* 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; |
|
|
|
- cmnd = dst = reallocarray(NULL, cmnd_size, 2); |
|
- if (cmnd == NULL) |
|
+ for (av = argv; *av != NULL; av++) |
|
+ size += strlen(*av) + 1; |
|
+ |
|
+ if (size == 0 || (cmnd = reallocarray(NULL, size, 2)) == NULL) |
|
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
|
if (!gc_add(GC_PTR, cmnd)) |
|
exit(1); |
|
|
|
- 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 != '-' && *src != '$')
|
|
|