diff options
Diffstat (limited to 'meta/recipes-extended/sudo/files')
7 files changed, 777 insertions, 0 deletions
diff --git a/meta/recipes-extended/sudo/files/CVE-2021-23239.patch b/meta/recipes-extended/sudo/files/CVE-2021-23239.patch new file mode 100644 index 0000000000..e16baecd5a --- /dev/null +++ b/meta/recipes-extended/sudo/files/CVE-2021-23239.patch @@ -0,0 +1,62 @@ + +# HG changeset patch +# User Todd C. Miller <Todd.Miller@sudo.ws> +# Date 1609953360 25200 +# Node ID ea19d0073c02951bbbf35342dd63304da83edce8 +# Parent f1ca39a0d87089d005b78a2556e2b1a2dc17f672 +Fix potential directory existing info leak in sudoedit. +When creating a new file, sudoedit checks to make sure the parent +directory exists so it can provide the user with a sensible error +message. However, this could be used to test for the existence of +directories not normally accessible to the user by pointing to them +with a symbolic link when the parent directory is controlled by the +user. Problem reported by Matthias Gerstner of SUSE. + +Upstream-Status: Backport [https://www.sudo.ws/repos/sudo/rev/ea19d0073c02] +CVE: CVE-2021-23239 +Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> + +diff -r f1ca39a0d870 -r ea19d0073c02 src/sudo_edit.c +--- a/src/sudo_edit.c Wed Jan 06 10:16:00 2021 -0700 ++++ b/src/sudo_edit.c Wed Jan 06 10:16:00 2021 -0700 +@@ -541,14 +541,33 @@ + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details); + if (ofd != -1 || errno == ENOENT) { + if (ofd == -1) { +- /* New file, verify parent dir exists unless in cwd. */ ++ /* ++ * New file, verify parent dir exists unless in cwd. ++ * This fails early so the user knows ahead of time if the ++ * edit won't succeed. Additional checks are performed ++ * when copying the temporary file back to the origin. ++ */ + char *slash = strrchr(files[i], '/'); + if (slash != NULL && slash != files[i]) { +- int serrno = errno; ++ const int sflags = command_details->flags; ++ const int serrno = errno; ++ int dfd; ++ ++ /* ++ * The parent directory is allowed to be a symbolic ++ * link as long as *its* parent is not writable. ++ */ + *slash = '\0'; +- if (stat(files[i], &sb) == 0 && S_ISDIR(sb.st_mode)) { +- memset(&sb, 0, sizeof(sb)); +- rc = 0; ++ SET(command_details->flags, CD_SUDOEDIT_FOLLOW); ++ dfd = sudo_edit_open(files[i], DIR_OPEN_FLAGS, ++ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details); ++ command_details->flags = sflags; ++ if (dfd != -1) { ++ if (fstat(dfd, &sb) == 0 && S_ISDIR(sb.st_mode)) { ++ memset(&sb, 0, sizeof(sb)); ++ rc = 0; ++ } ++ close(dfd); + } + *slash = '/'; + errno = serrno; + + diff --git a/meta/recipes-extended/sudo/files/CVE-2021-23240.patch b/meta/recipes-extended/sudo/files/CVE-2021-23240.patch new file mode 100644 index 0000000000..740a13cd90 --- /dev/null +++ b/meta/recipes-extended/sudo/files/CVE-2021-23240.patch @@ -0,0 +1,419 @@ +Upstream-Status: Backport [https://www.sudo.ws/repos/sudo/rev/8fcb36ef422a] +Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> +CVE: CVE-2021-23240 + +# HG changeset patch +# User Todd C. Miller <Todd.Miller@sudo.ws> +# Date 1609953360 25200 +# Node ID 8fcb36ef422a251fe33738a347551439944a4a37 +# Parent ea19d0073c02951bbbf35342dd63304da83edce8 +Add security checks before using temp files for SELinux RBAC sudoedit. +Otherwise, it may be possible for the user running sudoedit to +replace the newly-created temporary files with a symbolic link and +have sudoedit set the owner of an arbitrary file. +Problem reported by Matthias Gerstner of SUSE. + +diff -r ea19d0073c02 -r 8fcb36ef422a src/copy_file.c +--- a/src/copy_file.c Wed Jan 06 10:16:00 2021 -0700 ++++ b/src/copy_file.c Wed Jan 06 10:16:00 2021 -0700 +@@ -1,7 +1,7 @@ + /* + * SPDX-License-Identifier: ISC + * +- * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws> ++ * Copyright (c) 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -23,6 +23,8 @@ + + #include <config.h> + ++#include <sys/stat.h> ++ + #include <stdlib.h> + #include <unistd.h> + #include <errno.h> +@@ -134,3 +136,34 @@ + sudo_warn(U_("unable to write to %s"), dst); + debug_return_int(-1); + } ++ ++#ifdef HAVE_SELINUX ++bool ++sudo_check_temp_file(int tfd, const char *tfile, uid_t uid, struct stat *sb) ++{ ++ struct stat sbuf; ++ debug_decl(sudo_check_temp_file, SUDO_DEBUG_UTIL); ++ ++ if (sb == NULL) ++ sb = &sbuf; ++ ++ if (fstat(tfd, sb) == -1) { ++ sudo_warn(U_("unable to stat %s"), tfile); ++ debug_return_bool(false); ++ } ++ if (!S_ISREG(sb->st_mode)) { ++ sudo_warnx(U_("%s: not a regular file"), tfile); ++ debug_return_bool(false); ++ } ++ if ((sb->st_mode & ALLPERMS) != (S_IRUSR|S_IWUSR)) { ++ sudo_warnx(U_("%s: bad file mode: 0%o"), tfile, sb->st_mode & ALLPERMS); ++ debug_return_bool(false); ++ } ++ if (sb->st_uid != uid) { ++ sudo_warnx(U_("%s is owned by uid %u, should be %u"), ++ tfile, (unsigned int)sb->st_uid, (unsigned int)uid); ++ debug_return_bool(false); ++ } ++ debug_return_bool(true); ++} ++#endif /* SELINUX */ +diff -r ea19d0073c02 -r 8fcb36ef422a src/sesh.c +--- a/src/sesh.c Wed Jan 06 10:16:00 2021 -0700 ++++ b/src/sesh.c Wed Jan 06 10:16:00 2021 -0700 +@@ -1,7 +1,7 @@ + /* + * SPDX-License-Identifier: ISC + * +- * Copyright (c) 2008, 2010-2018, 2020 Todd C. Miller <Todd.Miller@sudo.ws> ++ * Copyright (c) 2008, 2010-2018, 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -132,7 +132,7 @@ + static int + sesh_sudoedit(int argc, char *argv[]) + { +- int i, oflags_dst, post, ret = SESH_ERR_FAILURE; ++ int i, oflags_src, oflags_dst, post, ret = SESH_ERR_FAILURE; + int fd_src = -1, fd_dst = -1, follow = 0; + struct stat sb; + struct timespec times[2]; +@@ -174,10 +174,12 @@ + debug_return_int(SESH_ERR_BAD_PATHS); + + /* +- * Use O_EXCL if we are not in the post editing stage +- * so that it's ensured that the temporary files are +- * created by us and that we are not opening any symlinks. ++ * In the pre-editing stage, use O_EXCL to ensure that the temporary ++ * files are created by us and that we are not opening any symlinks. ++ * In the post-editing stage, use O_NOFOLLOW so we don't follow symlinks ++ * when opening the temporary files. + */ ++ oflags_src = O_RDONLY|(post ? O_NONBLOCK|O_NOFOLLOW : follow); + oflags_dst = O_WRONLY|O_CREAT|(post ? follow : O_EXCL); + for (i = 0; i < argc - 1; i += 2) { + const char *path_src = argv[i]; +@@ -187,7 +189,7 @@ + * doesn't exist, that's OK, we'll create an empty + * destination file. + */ +- if ((fd_src = open(path_src, O_RDONLY|follow, S_IRUSR|S_IWUSR)) < 0) { ++ if ((fd_src = open(path_src, oflags_src, S_IRUSR|S_IWUSR)) < 0) { + if (errno != ENOENT) { + sudo_warn("%s", path_src); + if (post) { +@@ -197,6 +199,14 @@ + goto cleanup_0; + } + } ++ if (post) { ++ /* Make sure the temporary file is safe and has the proper owner. */ ++ if (!sudo_check_temp_file(fd_src, path_src, geteuid(), &sb)) { ++ ret = SESH_ERR_SOME_FILES; ++ goto nocleanup; ++ } ++ fcntl(fd_src, F_SETFL, fcntl(fd_src, F_GETFL, 0) & ~O_NONBLOCK); ++ } + + if ((fd_dst = open(path_dst, oflags_dst, post ? + (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) : (S_IRUSR|S_IWUSR))) < 0) { +@@ -214,10 +224,7 @@ + off_t len_dst = -1; + + if (post) { +- if (fstat(fd_src, &sb) != 0) { +- ret = SESH_ERR_SOME_FILES; +- goto nocleanup; +- } ++ /* sudo_check_temp_file() filled in sb for us. */ + len_src = sb.st_size; + if (fstat(fd_dst, &sb) != 0) { + ret = SESH_ERR_SOME_FILES; +diff -r ea19d0073c02 -r 8fcb36ef422a src/sudo_edit.c +--- a/src/sudo_edit.c Wed Jan 06 10:16:00 2021 -0700 ++++ b/src/sudo_edit.c Wed Jan 06 10:16:00 2021 -0700 +@@ -1,7 +1,7 @@ + /* + * SPDX-License-Identifier: ISC + * +- * Copyright (c) 2004-2008, 2010-2020 Todd C. Miller <Todd.Miller@sudo.ws> ++ * Copyright (c) 2004-2008, 2010-2021 Todd C. Miller <Todd.Miller@sudo.ws> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -259,8 +259,10 @@ + } else { + len = asprintf(tfile, "%s/%s.XXXXXXXX", edit_tmpdir, cp); + } +- if (len == -1) +- sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); ++ if (len == -1) { ++ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); ++ debug_return_int(-1); ++ } + tfd = mkstemps(*tfile, suff ? strlen(suff) : 0); + sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, + "%s -> %s, fd %d", ofile, *tfile, tfd); +@@ -735,7 +737,8 @@ + + #ifdef HAVE_SELINUX + static int +-selinux_run_helper(char *argv[], char *envp[]) ++selinux_run_helper(uid_t uid, gid_t gid, int ngroups, GETGROUPS_T *groups, ++ char *const argv[], char *const envp[]) + { + int status, ret = SESH_ERR_FAILURE; + const char *sesh; +@@ -755,8 +758,10 @@ + break; + case 0: + /* child runs sesh in new context */ +- if (selinux_setcon() == 0) ++ if (selinux_setcon() == 0) { ++ switch_user(uid, gid, ngroups, groups); + execve(sesh, argv, envp); ++ } + _exit(SESH_ERR_FAILURE); + default: + /* parent waits */ +@@ -775,7 +780,7 @@ + struct tempfile *tf, char *files[], int nfiles) + { + char **sesh_args, **sesh_ap; +- int i, rc, sesh_nargs; ++ int i, error, sesh_nargs, ret = -1; + struct stat sb; + debug_decl(selinux_edit_create_tfiles, SUDO_DEBUG_EDIT); + +@@ -787,7 +792,7 @@ + sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *)); + if (sesh_args == NULL) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); +- debug_return_int(-1); ++ goto done; + } + *sesh_ap++ = "sesh"; + *sesh_ap++ = "-e"; +@@ -795,7 +800,6 @@ + *sesh_ap++ = "-h"; + *sesh_ap++ = "0"; + +- /* XXX - temp files should be created with user's context */ + for (i = 0; i < nfiles; i++) { + char *tfile, *ofile = files[i]; + int tfd; +@@ -813,8 +817,7 @@ + if (tfd == -1) { + sudo_warn("mkstemps"); + free(tfile); +- free(sesh_args); +- debug_return_int(-1); ++ goto done; + } + /* Helper will re-create temp file with proper security context. */ + close(tfd); +@@ -825,8 +828,10 @@ + *sesh_ap = NULL; + + /* Run sesh -e [-h] 0 <o1> <t1> ... <on> <tn> */ +- rc = selinux_run_helper(sesh_args, command_details->envp); +- switch (rc) { ++ error = selinux_run_helper(command_details->uid, command_details->gid, ++ command_details->ngroups, command_details->groups, sesh_args, ++ command_details->envp); ++ switch (error) { + case SESH_SUCCESS: + break; + case SESH_ERR_BAD_PATHS: +@@ -836,21 +841,35 @@ + case SESH_ERR_KILLED: + sudo_fatalx("%s", U_("sesh: killed by a signal")); + default: +- sudo_fatalx(U_("sesh: unknown error %d"), rc); ++ sudo_warnx(U_("sesh: unknown error %d"), error); ++ goto done; + } + +- /* Chown to user's UID so they can edit the temporary files. */ + for (i = 0; i < nfiles; i++) { +- if (chown(tf[i].tfile, user_details.uid, user_details.gid) != 0) { ++ int tfd = open(tf[i].tfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW); ++ if (tfd == -1) { ++ sudo_warn(U_("unable to open %s"), tf[i].tfile); ++ goto done; ++ } ++ if (!sudo_check_temp_file(tfd, tf[i].tfile, command_details->uid, NULL)) { ++ close(tfd); ++ goto done; ++ } ++ if (fchown(tfd, user_details.uid, user_details.gid) != 0) { + sudo_warn("unable to chown(%s) to %d:%d for editing", + tf[i].tfile, user_details.uid, user_details.gid); ++ close(tfd); ++ goto done; + } ++ close(tfd); + } ++ ret = nfiles; + ++done: + /* Contents of tf will be freed by caller. */ + free(sesh_args); + +- return (nfiles); ++ debug_return_int(ret); + } + + static int +@@ -858,7 +877,8 @@ + struct tempfile *tf, int nfiles, struct timespec *times) + { + char **sesh_args, **sesh_ap; +- int i, rc, sesh_nargs, ret = 1; ++ int i, error, sesh_nargs, ret = 1; ++ int tfd = -1; + struct timespec ts; + struct stat sb; + debug_decl(selinux_edit_copy_tfiles, SUDO_DEBUG_EDIT); +@@ -879,33 +899,43 @@ + + /* Construct args for sesh -e 1 */ + for (i = 0; i < nfiles; i++) { +- if (stat(tf[i].tfile, &sb) == 0) { +- mtim_get(&sb, ts); +- if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) { +- /* +- * If mtime and size match but the user spent no measurable +- * time in the editor we can't tell if the file was changed. +- */ +- if (sudo_timespeccmp(×[0], ×[1], !=)) { +- sudo_warnx(U_("%s unchanged"), tf[i].ofile); +- unlink(tf[i].tfile); +- continue; +- } ++ if (tfd != -1) ++ close(tfd); ++ if ((tfd = open(tf[i].tfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW)) == -1) { ++ sudo_warn(U_("unable to open %s"), tf[i].tfile); ++ continue; ++ } ++ if (!sudo_check_temp_file(tfd, tf[i].tfile, user_details.uid, &sb)) ++ continue; ++ mtim_get(&sb, ts); ++ if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) { ++ /* ++ * If mtime and size match but the user spent no measurable ++ * time in the editor we can't tell if the file was changed. ++ */ ++ if (sudo_timespeccmp(×[0], ×[1], !=)) { ++ sudo_warnx(U_("%s unchanged"), tf[i].ofile); ++ unlink(tf[i].tfile); ++ continue; + } + } + *sesh_ap++ = tf[i].tfile; + *sesh_ap++ = tf[i].ofile; +- if (chown(tf[i].tfile, command_details->uid, command_details->gid) != 0) { ++ if (fchown(tfd, command_details->uid, command_details->gid) != 0) { + sudo_warn("unable to chown(%s) back to %d:%d", tf[i].tfile, + command_details->uid, command_details->gid); + } + } + *sesh_ap = NULL; ++ if (tfd != -1) ++ close(tfd); + + if (sesh_ap - sesh_args > 3) { + /* Run sesh -e 1 <t1> <o1> ... <tn> <on> */ +- rc = selinux_run_helper(sesh_args, command_details->envp); +- switch (rc) { ++ error = selinux_run_helper(command_details->uid, command_details->gid, ++ command_details->ngroups, command_details->groups, sesh_args, ++ command_details->envp); ++ switch (error) { + case SESH_SUCCESS: + ret = 0; + break; +@@ -921,7 +951,7 @@ + sudo_warnx("%s", U_("sesh: killed by a signal")); + break; + default: +- sudo_warnx(U_("sesh: unknown error %d"), rc); ++ sudo_warnx(U_("sesh: unknown error %d"), error); + break; + } + if (ret != 0) +@@ -943,7 +973,7 @@ + { + struct command_details saved_command_details; + char **nargv = NULL, **ap, **files = NULL; +- int errors, i, ac, nargc, rc; ++ int errors, i, ac, nargc, ret; + int editor_argc = 0, nfiles = 0; + struct timespec times[2]; + struct tempfile *tf = NULL; +@@ -1038,7 +1068,7 @@ + command_details->ngroups = user_details.ngroups; + command_details->groups = user_details.groups; + command_details->argv = nargv; +- rc = run_command(command_details); ++ ret = run_command(command_details); + if (sudo_gettime_real(×[1]) == -1) { + sudo_warn("%s", U_("unable to read the clock")); + goto cleanup; +@@ -1062,14 +1092,14 @@ + errors = sudo_edit_copy_tfiles(command_details, tf, nfiles, times); + if (errors) { + /* Preserve the edited temporary files. */ +- rc = W_EXITCODE(1, 0); ++ ret = W_EXITCODE(1, 0); + } + + for (i = 0; i < nfiles; i++) + free(tf[i].tfile); + free(tf); + free(nargv); +- debug_return_int(rc); ++ debug_return_int(ret); + + cleanup: + /* Clean up temp files and return. */ +diff -r ea19d0073c02 -r 8fcb36ef422a src/sudo_exec.h +--- a/src/sudo_exec.h Wed Jan 06 10:16:00 2021 -0700 ++++ b/src/sudo_exec.h Wed Jan 06 10:16:00 2021 -0700 +@@ -1,7 +1,7 @@ + /* + * SPDX-License-Identifier: ISC + * +- * Copyright (c) 2010-2016 Todd C. Miller <Todd.Miller@sudo.ws> ++ * Copyright (c) 2010-2017, 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -84,9 +84,11 @@ + */ + struct command_details; + struct command_status; ++struct stat; + + /* copy_file.c */ + int sudo_copy_file(const char *src, int src_fd, off_t src_len, const char *dst, int dst_fd, off_t dst_len); ++bool sudo_check_temp_file(int tfd, const char *tname, uid_t uid, struct stat *sb); + + /* exec.c */ + void exec_cmnd(struct command_details *details, int errfd); + + diff --git a/meta/recipes-extended/sudo/files/CVE-2021-3156-1.patch b/meta/recipes-extended/sudo/files/CVE-2021-3156-1.patch new file mode 100644 index 0000000000..83c277575e --- /dev/null +++ b/meta/recipes-extended/sudo/files/CVE-2021-3156-1.patch @@ -0,0 +1,100 @@ +Upstream-Status: Backport[https://www.sudo.ws/repos/sudo/rev/9b97f1787804] +Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> +CVE: CVE-2021-3156 + +# 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; + + + diff --git a/meta/recipes-extended/sudo/files/CVE-2021-3156-2.patch b/meta/recipes-extended/sudo/files/CVE-2021-3156-2.patch new file mode 100644 index 0000000000..6d051252cb --- /dev/null +++ b/meta/recipes-extended/sudo/files/CVE-2021-3156-2.patch @@ -0,0 +1,53 @@ +From 03d04069468d6633be0d6ef6c4adff07620488da Mon Sep 17 00:00:00 2001 +From: Anuj Mittal <anuj.mittal@intel.com> +Date: Sat, 6 Feb 2021 15:57:55 +0800 +Subject: [PATCH] sudo: fix CVE-2021-3156 + +Upstream-Status: Backport [https://www.sudo.ws/repos/sudo/rev/a97dc92eae6b] +Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> +CVE: CVE-2021-3156 + +# HG changeset patch +# User Todd C. Miller <Todd.Miller@sudo.ws> +# Date 1611416639 25200 +# Node ID a97dc92eae6b60ae285055441341d493c17262ff +# Parent 9b97f1787804aedccaec63c379053b1a91a0e409 +Add sudoedit flag checks in plugin that are consistent with front-end. +Don't assume the sudo front-end is sending reasonable mode flags. +These checks need to be kept consistent between the sudo front-end +and the sudoers plugin. + +--- + plugins/sudoers/policy.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c +index c4749a6..2f18fe1 100644 +--- a/plugins/sudoers/policy.c ++++ b/plugins/sudoers/policy.c +@@ -88,10 +88,11 @@ parse_bool(const char *line, int varlen, int *flags, int fval) + 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_open_info *info = v; +- char * const *cur; + const char *p, *errstr, *groups = NULL; + const char *remhost = NULL; ++ char * const *cur; + int flags = 0; + debug_decl(sudoers_policy_deserialize_info, SUDOERS_DEBUG_PLUGIN); + +@@ -343,6 +344,12 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group) + #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_gid = (gid_t)-1; + user_sid = (pid_t)-1; + user_uid = (gid_t)-1; diff --git a/meta/recipes-extended/sudo/files/CVE-2021-3156-3.patch b/meta/recipes-extended/sudo/files/CVE-2021-3156-3.patch new file mode 100644 index 0000000000..30a574d05c --- /dev/null +++ b/meta/recipes-extended/sudo/files/CVE-2021-3156-3.patch @@ -0,0 +1,73 @@ +Upstream-Status: Backport[https://www.sudo.ws/repos/sudo/rev/049ad90590be] +Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> +CVE: CVE-2021-3156 + +# 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)) { + const char *runchroot = user_runchroot; + if (runchroot == NULL && def_runchroot != NULL && + strcmp(def_runchroot, "*") != 0) +@@ -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'; + + diff --git a/meta/recipes-extended/sudo/files/CVE-2021-3156-4.patch b/meta/recipes-extended/sudo/files/CVE-2021-3156-4.patch new file mode 100644 index 0000000000..c1b00c740e --- /dev/null +++ b/meta/recipes-extended/sudo/files/CVE-2021-3156-4.patch @@ -0,0 +1,29 @@ +Upstream-Status: Backport [https://www.sudo.ws/repos/sudo/rev/09f98816fc89] +Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> +CVE: CVE-2021-3156 + +# HG changeset patch +# User Todd C. Miller <Todd.Miller@sudo.ws> +# Date 1611416640 25200 +# Node ID 09f98816fc8978f1d8623a857073d2d5746f0379 +# Parent 049ad90590be1e5dfb7df2675d2eb3e37c96ab86 +Fix the memset offset when converting a v1 timestamp to TS_LOCKEXCL. +We want to zero the struct starting at flags, not type (which was just set). +Found by Qualys. + +diff -r 049ad90590be -r 09f98816fc89 plugins/sudoers/timestamp.c +--- a/plugins/sudoers/timestamp.c Sat Jan 23 08:43:59 2021 -0700 ++++ b/plugins/sudoers/timestamp.c Sat Jan 23 08:44:00 2021 -0700 +@@ -643,8 +643,8 @@ + if (entry.size == sizeof(struct timestamp_entry_v1)) { + /* 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); + } else { + + diff --git a/meta/recipes-extended/sudo/files/CVE-2021-3156-5.patch b/meta/recipes-extended/sudo/files/CVE-2021-3156-5.patch new file mode 100644 index 0000000000..c04b8e72a6 --- /dev/null +++ b/meta/recipes-extended/sudo/files/CVE-2021-3156-5.patch @@ -0,0 +1,41 @@ +Upstream-Status: Backport [https://www.sudo.ws/repos/sudo/rev/c125fbe68783] +Signed-off-by: Anuj Mittal <anuj.mittal@intel.com> +CVE: CVE-2021-3156 + +# HG changeset patch +# User Todd C. Miller <Todd.Miller@sudo.ws> +# Date 1611416640 25200 +# Node ID c125fbe6878395d10f01d891d3c09b1229ada404 +# Parent 09f98816fc8978f1d8623a857073d2d5746f0379 +Don't assume that argv is allocated as a single flat buffer. +While this is how the kernel behaves it is not a portable assumption. +The assumption may also be violated if getopt_long(3) permutes arguments. +Found by Qualys. + +diff -r 09f98816fc89 -r c125fbe68783 src/parse_args.c +--- a/src/parse_args.c Sat Jan 23 08:44:00 2021 -0700 ++++ b/src/parse_args.c Sat Jan 23 08:44:00 2021 -0700 +@@ -614,16 +614,16 @@ + 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(EXIT_FAILURE); + +- 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 != '$') + + |