From c22b5ff49faaa3f93af82ee84e53304728ea741d Mon Sep 17 00:00:00 2001 From: zhoushuiqing Date: Tue, 13 Jun 2023 11:59:01 +0800 Subject: [PATCH] Backport patches form upstream community (cherry picked from commit 23b42da498fb65fe2292ea1858ee0fe64ff57e03) --- ...LL-pointer-deference-found-by-clang-.patch | 43 +++++ ...cve-2-allows-argv-or-envp-to-be-NULL.patch | 164 ++++++++++++++++++ ...ent-handler-if-we-get-EAGAIN-from-re.patch | 61 +++++++ ...bug-require-that-the-environment-str.patch | 43 +++++ ...er-setting-return-value-until-the-en.patch | 59 +++++++ sudo.spec | 10 +- 6 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 backport-Fix-potential-NULL-pointer-deference-found-by-clang-.patch create mode 100644 backport-Linux-execve-2-allows-argv-or-envp-to-be-NULL.patch create mode 100644 backport-Reinstall-the-event-handler-if-we-get-EAGAIN-from-re.patch create mode 100644 backport-sudo_putenv_nodebug-require-that-the-environment-str.patch create mode 100644 backport-sudoers_main-defer-setting-return-value-until-the-en.patch diff --git a/backport-Fix-potential-NULL-pointer-deference-found-by-clang-.patch b/backport-Fix-potential-NULL-pointer-deference-found-by-clang-.patch new file mode 100644 index 0000000..92f22dc --- /dev/null +++ b/backport-Fix-potential-NULL-pointer-deference-found-by-clang-.patch @@ -0,0 +1,43 @@ +From 3421c8b6cedc582ed5eab573f59d4feddc7e1ab3 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Tue, 26 Jul 2022 11:44:12 -0600 +Subject: [PATCH] Fix potential NULL pointer deference found by clang-analyzer. + +--- + lib/util/sudo_debug.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/util/sudo_debug.c b/lib/util/sudo_debug.c +index a2ead5228..c06ba8cde 100644 +--- a/lib/util/sudo_debug.c ++++ b/lib/util/sudo_debug.c +@@ -861,7 +861,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con + continue; + + /* Log envp for debug level "debug". */ +- if (output->settings[subsys] >= SUDO_DEBUG_DEBUG - 1 && envp[0] != NULL) ++ if (output->settings[subsys] >= SUDO_DEBUG_DEBUG - 1 && envp != NULL) + log_envp = true; + + /* Alloc and build up buffer. */ +@@ -873,7 +873,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con + buflen += strlen(*av) + 1; + buflen--; + } +- if (envp != NULL && log_envp) { ++ if (log_envp && envp[0] != NULL) { + buflen += sizeof(" []") - 1; + for (av = envp; *av; av++) + buflen += strlen(*av) + 1; +@@ -904,7 +904,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con + cp[-1] = ']'; + } + +- if (envp != NULL && log_envp) { ++ if (log_envp && envp[0] != NULL) { + *cp++ = ' '; + *cp++ = '['; + for (av = envp; *av; av++) { +-- +2.33.0 + diff --git a/backport-Linux-execve-2-allows-argv-or-envp-to-be-NULL.patch b/backport-Linux-execve-2-allows-argv-or-envp-to-be-NULL.patch new file mode 100644 index 0000000..9eb2d55 --- /dev/null +++ b/backport-Linux-execve-2-allows-argv-or-envp-to-be-NULL.patch @@ -0,0 +1,164 @@ +From e5652fc65a54ab2d3f161c264254579f00699b00 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Thu, 14 Jul 2022 09:29:40 -0600 +Subject: [PATCH] Linux execve(2) allows argv or envp to be NULL. Add checks to + make sure we don't deference a NULL pointer. + +--- + lib/util/sudo_debug.c | 10 +++++----- + src/exec_intercept.c | 2 +- + src/exec_preload.c | 5 +++++ + src/exec_ptrace.c | 36 +++++++++++++++++++++++++++++------- + src/sudo_intercept.c | 10 ++++++++++ + src/sudo_intercept_common.c | 25 ++++++++++++++----------- + 6 files changed, 64 insertions(+), 24 deletions(-) + +diff --git a/lib/util/sudo_debug.c b/lib/util/sudo_debug.c +index d78536a0c..a2ead5228 100644 +--- a/lib/util/sudo_debug.c ++++ b/lib/util/sudo_debug.c +@@ -831,7 +831,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con + size_t plen; + debug_decl_func(sudo_debug_execve2); + +- if (sudo_debug_active_instance == -1) ++ if (sudo_debug_active_instance == -1 || path == NULL) + goto out; + + /* Extract priority and subsystem from level. */ +@@ -867,13 +867,13 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con + /* Alloc and build up buffer. */ + plen = strlen(path); + buflen = sizeof(EXEC_PREFIX) -1 + plen; +- if (argv[0] != NULL) { ++ if (argv != NULL && argv[0] != NULL) { + buflen += sizeof(" []") - 1; + for (av = argv; *av; av++) + buflen += strlen(*av) + 1; + buflen--; + } +- if (log_envp) { ++ if (envp != NULL && log_envp) { + buflen += sizeof(" []") - 1; + for (av = envp; *av; av++) + buflen += strlen(*av) + 1; +@@ -892,7 +892,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con + cp += plen; + + /* Copy argv. */ +- if (argv[0] != NULL) { ++ if (argv != NULL && argv[0] != NULL) { + *cp++ = ' '; + *cp++ = '['; + for (av = argv; *av; av++) { +@@ -904,7 +904,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con + cp[-1] = ']'; + } + +- if (log_envp) { ++ if (envp != NULL && log_envp) { + *cp++ = ' '; + *cp++ = '['; + for (av = envp; *av; av++) { +diff --git a/src/exec_preload.c b/src/exec_preload.c +index 4f04a0113..81e865333 100644 +--- a/src/exec_preload.c ++++ b/src/exec_preload.c +@@ -44,6 +44,7 @@ sudo_preload_dso(char *const envp[], const char *dso_file, int intercept_fd) + int env_len, len; + int preload_idx = -1; + int intercept_idx = -1; ++ char *const empty[1] = { NULL }; + bool fd_present = false; + bool dso_present = false; + # ifdef RTLD_PRELOAD_ENABLE_VAR +@@ -73,4 +73,8 @@ sudo_preload_dso(char *const envp[], const char *dso_file, int intercept_fd) + * XXX - need to support 32-bit and 64-bit variants + */ + ++ /* Treat a NULL envp as empty, thanks Linux. */ ++ if (envp == NULL) ++ envp = empty; ++ + /* Count entries in envp, looking for LD_PRELOAD as we go. */ +diff --git a/src/sudo_intercept.c b/src/sudo_intercept.c +index 97c612892..48ecc9bc9 100644 +--- a/src/sudo_intercept.c ++++ b/src/sudo_intercept.c +@@ -135,6 +135,11 @@ exec_wrapper(const char *cmnd, char * const argv[], char * const envp[], + void *fn = NULL; + debug_decl(exec_wrapper, SUDO_DEBUG_EXEC); + ++ if (cmnd == NULL) { ++ errno = EINVAL; ++ debug_return_int(-1); ++ } ++ + /* Only check PATH for the command for execlp/execvp/execvpe. */ + if (strchr(cmnd, '/') == NULL) { + if (!is_execvp) { +@@ -201,6 +206,11 @@ execl_wrapper(int type, const char *name, const char *arg, va_list ap) + va_list ap2; + debug_decl(execl_wrapper, SUDO_DEBUG_EXEC); + ++ if (name == NULL || arg == NULL) { ++ errno = EINVAL; ++ debug_return_int(-1); ++ } ++ + va_copy(ap2, ap); + while (va_arg(ap2, char *) != NULL) + argc++; +diff --git a/src/sudo_intercept_common.c b/src/sudo_intercept_common.c +index 102393952..a81a3c880 100644 +--- a/src/sudo_intercept_common.c ++++ b/src/sudo_intercept_common.c +@@ -297,6 +297,7 @@ send_policy_check_req(int sock, const char *cmnd, char * const argv[], + InterceptRequest msg = INTERCEPT_REQUEST__INIT; + PolicyCheckRequest req = POLICY_CHECK_REQUEST__INIT; + char cwdbuf[PATH_MAX]; ++ char *empty[1] = { NULL }; + uint8_t *buf = NULL; + bool ret = false; + uint32_t msg_len; +@@ -313,14 +314,14 @@ send_policy_check_req(int sock, const char *cmnd, char * const argv[], + /* Setup policy check request. */ + req.intercept_fd = sock; + req.command = (char *)cmnd; +- req.argv = (char **)argv; +- for (len = 0; argv[len] != NULL; len++) +- continue; +- req.n_argv = len; +- req.envp = (char **)envp; +- for (len = 0; envp[len] != NULL; len++) +- continue; +- req.n_envp = len; ++ req.argv = argv ? (char **)argv : empty; ++ req.n_argv = 0; ++ while (req.argv[req.n_argv] != NULL) ++ req.n_argv++; ++ req.envp = envp ? (char **)envp : empty; ++ req.n_envp = 0; ++ while (req.envp[req.n_envp] != NULL) ++ req.n_envp++; + if (getcwd(cwdbuf, sizeof(cwdbuf)) != NULL) { + req.cwd = cwdbuf; + } +@@ -409,9 +410,11 @@ command_allowed(const char *cmnd, char * const argv[], + if (sudo_debug_needed(SUDO_DEBUG_INFO)) { + sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, + "req_command: %s", cmnd); +- for (idx = 0; argv[idx] != NULL; idx++) { +- sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, +- "req_argv[%zu]: %s", idx, argv[idx]); ++ if (argv != NULL) { ++ for (idx = 0; argv[idx] != NULL; idx++) { ++ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, ++ "req_argv[%zu]: %s", idx, argv[idx]); ++ } + } + } + +-- +2.33.0 + diff --git a/backport-Reinstall-the-event-handler-if-we-get-EAGAIN-from-re.patch b/backport-Reinstall-the-event-handler-if-we-get-EAGAIN-from-re.patch new file mode 100644 index 0000000..d1dd631 --- /dev/null +++ b/backport-Reinstall-the-event-handler-if-we-get-EAGAIN-from-re.patch @@ -0,0 +1,61 @@ +From c2a131714a6b9eccba7779bde64ce79a0377b541 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Mon, 6 Jun 2022 19:42:07 -0600 +Subject: [PATCH] Reinstall the event handler if we get EAGAIN from read/write + callback. The read and write events do not set SUDO_EV_PERSIST so we need to + explicitly re-enable the event if there is still data to be read. Bug #963. + +--- + src/exec_pty.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/exec_pty.c b/src/exec_pty.c +index 326d8318a..d2fc1ce5c 100644 +--- a/src/exec_pty.c ++++ b/src/exec_pty.c +@@ -676,8 +676,12 @@ read_callback(int fd, int what, void *v) + /* Schedule SIGTTIN to be forwarded to the command. */ + schedule_signal(iob->ec, SIGTTIN); + } +- if (errno == EAGAIN || errno == EINTR) ++ if (errno == EAGAIN || errno == EINTR) { ++ /* Re-enable reader. */ ++ if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1) ++ sudo_fatal("%s", U_("unable to add event to queue")); + break; ++ } + /* treat read error as fatal and close the fd */ + sudo_debug_printf(SUDO_DEBUG_ERROR, + "error reading fd %d: %s", fd, strerror(errno)); +@@ -717,6 +721,8 @@ read_callback(int fd, int what, void *v) + } + break; + } ++ ++ debug_return; + } + + /* +@@ -783,7 +789,9 @@ write_callback(int fd, int what, void *v) + } + FALLTHROUGH; + case EAGAIN: +- /* not an error */ ++ /* Not an error, re-enable writer. */ ++ if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1) ++ sudo_fatal("%s", U_("unable to add event to queue")); + break; + default: + /* XXX - need a way to distinguish non-exec error. */ +@@ -821,6 +829,8 @@ write_callback(int fd, int what, void *v) + } + } + } ++ ++ debug_return; + } + + static void +-- +2.33.0 + diff --git a/backport-sudo_putenv_nodebug-require-that-the-environment-str.patch b/backport-sudo_putenv_nodebug-require-that-the-environment-str.patch new file mode 100644 index 0000000..ddc7896 --- /dev/null +++ b/backport-sudo_putenv_nodebug-require-that-the-environment-str.patch @@ -0,0 +1,43 @@ +From 224d78993a24d1cc31ae0f6a0d0a59c66b765387 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Sat, 9 Jul 2022 09:00:48 -0600 +Subject: [PATCH] sudo_putenv_nodebug: require that the environment string + include a '=' + +--- + plugins/sudoers/env.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/plugins/sudoers/env.c b/plugins/sudoers/env.c +index 99b674300..eaf90f4a0 100644 +--- a/plugins/sudoers/env.c ++++ b/plugins/sudoers/env.c +@@ -314,9 +314,15 @@ int + sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite) + { + char **ep; +- size_t len; ++ const char *equal; + bool found = false; + ++ equal = strchr(str, '='); ++ if (equal == NULL) { ++ errno = EINVAL; ++ return -1; ++ } ++ + /* Make sure there is room for the new entry plus a NULL. */ + if (env.env_size > 2 && env.env_len > env.env_size - 2) { + char **nenvp; +@@ -358,7 +364,7 @@ sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite) + #endif + + if (dupcheck) { +- len = (strchr(str, '=') - str) + 1; ++ size_t len = (size_t)(equal - str) + 1; + for (ep = env.envp; *ep != NULL; ep++) { + if (strncmp(str, *ep, len) == 0) { + if (overwrite) +-- +2.33.0 + diff --git a/backport-sudoers_main-defer-setting-return-value-until-the-en.patch b/backport-sudoers_main-defer-setting-return-value-until-the-en.patch new file mode 100644 index 0000000..2e24b1a --- /dev/null +++ b/backport-sudoers_main-defer-setting-return-value-until-the-en.patch @@ -0,0 +1,59 @@ +From 985a2261bc5ae0491dc0be0977425c4f9a782883 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Thu, 30 Jun 2022 13:35:04 -0600 +Subject: [PATCH] sudoers_main: defer setting return value until the end when + running a command Otherwise, we could return success when there was an error + from a system call or memory allocation failure. + +--- + plugins/sudoers/sudoers.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c +index b48de3e1f..26f19abb5 100644 +--- a/plugins/sudoers/sudoers.c ++++ b/plugins/sudoers/sudoers.c +@@ -699,15 +699,16 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], + switch (sudo_mode & MODE_MASK) { + case MODE_CHECK: + ret = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw); +- break; ++ goto done; + case MODE_LIST: + ret = display_privs(snl, list_pw ? list_pw : sudo_user.pw, verbose); +- break; ++ goto done; + case MODE_VALIDATE: ++ ret = true; ++ goto done; + case MODE_RUN: + case MODE_EDIT: +- /* ret may be overridden by "goto bad" later */ +- ret = true; ++ /* ret will not be set until the very end. */ + break; + default: + /* Should not happen. */ +@@ -715,11 +716,6 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], + goto done; + } + +- if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) { +- /* ret already set appropriately */ +- goto done; +- } +- + /* + * Set umask based on sudoers. + * If user's umask is more restrictive, OR in those bits too +@@ -825,6 +821,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], + env_swap_old(); + } + ++ ret = true; + goto done; + + bad: +-- +2.33.0 + diff --git a/sudo.spec b/sudo.spec index 3490263..3a0d2ce 100644 --- a/sudo.spec +++ b/sudo.spec @@ -1,6 +1,6 @@ Name: sudo Version: 1.9.8p2 -Release: 12 +Release: 13 Summary: Allows restricted root access for specified users License: ISC URL: http://www.courtesan.com/sudo/ @@ -32,6 +32,11 @@ Patch18: backport-Fix-a-NOPASSWD-issue-with-a-non-existent-command-whe.patch Patch19: backport-CVE-2023-27320.patch Patch20: backport-CVE-2023-28486_CVE-2023-28487.patch Patch21: Fix-compilation-error-on-sw64-arch.patch +Patch22: backport-Reinstall-the-event-handler-if-we-get-EAGAIN-from-re.patch +Patch23: backport-sudoers_main-defer-setting-return-value-until-the-en.patch +Patch24: backport-sudo_putenv_nodebug-require-that-the-environment-str.patch +Patch25: backport-Linux-execve-2-allows-argv-or-envp-to-be-NULL.patch +Patch26: backport-Fix-potential-NULL-pointer-deference-found-by-clang-.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: pam @@ -182,6 +187,9 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/etc/pam.d/sudo-i %exclude %{_pkgdocdir}/ChangeLog %changelog +* Tue Jun 13 2023 zhoushuiqing - 1.9.8p2-13 +- Backport patches from upstream community + * Wed Apr 12 2023 wangyu - 1.9.8p2-12 - Fix compilation error on sw64 arch. -- Gitee