summaryrefslogtreecommitdiff
path: root/system/sudo/CVE-2021-3156.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/sudo/CVE-2021-3156.patch')
-rw-r--r--system/sudo/CVE-2021-3156.patch165
1 files changed, 165 insertions, 0 deletions
diff --git a/system/sudo/CVE-2021-3156.patch b/system/sudo/CVE-2021-3156.patch
new file mode 100644
index 000000000..7cb492d61
--- /dev/null
+++ b/system/sudo/CVE-2021-3156.patch
@@ -0,0 +1,165 @@
+
+# HG changeset patch
+# User Todd C. Miller <Todd.Miller@sudo.ws>
+# Date 1611416639 25200
+# Node ID 049ad90590be1e5dfb7df2675d2eb3e37c96ab86
+# Parent a97dc92eae6b60ae285055441341d493c17262ff
+Fix potential buffer overflow when unescaping backslashes in user_args.
+Also, do not try to unescaping backslashes unless in run mode *and*
+we are running the command via a shell.
+Found by Qualys, this fixes CVE-2021-3156.
+
+diff -r a97dc92eae6b -r 049ad90590be plugins/sudoers/sudoers.c
+--- a/plugins/sudoers/sudoers.c Sat Jan 23 08:43:59 2021 -0700
++++ b/plugins/sudoers/sudoers.c Sat Jan 23 08:43:59 2021 -0700
+@@ -547,7 +547,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;
+
+@@ -932,8 +932,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;
+ if (!set_perms(PERM_RUNAS))
+@@ -961,7 +961,8 @@
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+- 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
+@@ -969,10 +970,22 @@
+ */
+ 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';
+
+
+# HG changeset patch
+# User Todd C. Miller <Todd.Miller@sudo.ws>
+# Date 1611416639 25200
+# Node ID 9b97f1787804aedccaec63c379053b1a91a0e409
+# Parent 90aba6ba6e03f3bc33b4eabf16358396ed83642d
+Reset valid_flags to MODE_NONINTERACTIVE for sudoedit.
+This is consistent with how the -e option is handled.
+Also reject -H and -P flags for sudoedit as was done in sudo 1.7.
+Found by Qualys, this is part of the fix for CVE-2021-3156.
+
+diff -r 90aba6ba6e03 -r 9b97f1787804 src/parse_args.c
+--- a/src/parse_args.c Mon Jan 18 12:30:52 2021 +0100
++++ b/src/parse_args.c Sat Jan 23 08:43:59 2021 -0700
+@@ -117,7 +117,10 @@
+ /*
+ * 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
+@@ -262,6 +265,7 @@
+ progname = "sudoedit";
+ mode = MODE_EDIT;
+ sudo_settings[ARG_SUDOEDIT].value = "true";
++ valid_flags = EDIT_VALID_FLAGS;
+ }
+
+ /* Load local IP addresses and masks. */
+@@ -365,7 +369,7 @@
+ usage_excl();
+ mode = MODE_EDIT;
+ sudo_settings[ARG_SUDOEDIT].value = "true";
+- valid_flags = MODE_NONINTERACTIVE;
++ valid_flags = EDIT_VALID_FLAGS;
+ break;
+ case 'g':
+ assert(optarg != NULL);
+@@ -377,6 +381,7 @@
+ break;
+ case 'H':
+ sudo_settings[ARG_SET_HOME].value = "true";
++ SET(flags, MODE_RESET_HOME);
+ break;
+ case 'h':
+ if (optarg == NULL) {
+@@ -431,7 +436,7 @@
+ usage_excl();
+ }
+ mode = MODE_LIST;
+- valid_flags = MODE_NONINTERACTIVE|MODE_LONG_LIST;
++ valid_flags = LIST_VALID_FLAGS;
+ break;
+ case 'n':
+ SET(flags, MODE_NONINTERACTIVE);
+@@ -439,6 +444,7 @@
+ break;
+ case 'P':
+ sudo_settings[ARG_PRESERVE_GROUPS].value = "true";
++ SET(flags, MODE_PRESERVE_GROUPS);
+ break;
+ case 'p':
+ /* An empty prompt is allowed. */
+@@ -505,7 +511,7 @@
+ if (mode && mode != MODE_VALIDATE)
+ usage_excl();
+ mode = MODE_VALIDATE;
+- valid_flags = MODE_NONINTERACTIVE;
++ valid_flags = VALIDATE_VALID_FLAGS;
+ break;
+ case 'V':
+ if (mode && mode != MODE_VERSION)
+@@ -533,7 +539,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;
+@@ -601,7 +607,7 @@
+ /*
+ * 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;
+
+