diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 02:23:57 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 02:23:57 +0000 |
commit | 55c1e35c59b51018319d65f62b054c7682d95dd0 (patch) | |
tree | 6c5833e0b794bf046bd392b0544ce960753f4fd9 /debian/patches | |
parent | Adding upstream version 1.8.27. (diff) | |
download | sudo-debian.tar.xz sudo-debian.zip |
Adding debian version 1.8.27-1+deb10u3.debian/1.8.27-1+deb10u3debian
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debian/patches')
13 files changed, 849 insertions, 0 deletions
diff --git a/debian/patches/Add-sudoedit-flag-checks-in-plugin-that-are-consiste.patch b/debian/patches/Add-sudoedit-flag-checks-in-plugin-that-are-consiste.patch new file mode 100644 index 0000000..0fd3071 --- /dev/null +++ b/debian/patches/Add-sudoedit-flag-checks-in-plugin-that-are-consiste.patch @@ -0,0 +1,43 @@ +From 9f8d2f158166512511aac5e32928dcf6c65005c3 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" <Todd.Miller@sudo.ws> +Date: Wed, 20 Jan 2021 09:03:17 +0100 +Subject: [PATCH 2/5] 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. + +[Salvatore Bonaccorso: Backport to 1.8.27: Context changes] +--- + plugins/sudoers/policy.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/plugins/sudoers/policy.c ++++ b/plugins/sudoers/policy.c +@@ -98,10 +98,11 @@ 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; ++ char * const *cur; + bool uid_set = false, gid_set = false; + int flags = 0; + debug_decl(sudoers_policy_deserialize_info, SUDOERS_DEBUG_PLUGIN) +@@ -331,6 +332,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 --git a/debian/patches/Don-t-assume-that-argv-is-allocated-as-a-single-flat.patch b/debian/patches/Don-t-assume-that-argv-is-allocated-as-a-single-flat.patch new file mode 100644 index 0000000..0fa8d84 --- /dev/null +++ b/debian/patches/Don-t-assume-that-argv-is-allocated-as-a-single-flat.patch @@ -0,0 +1,39 @@ +From 61470612e3bc1a0aca268d80bc55c36c1802b7fd Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" <Todd.Miller@sudo.ws> +Date: Wed, 20 Jan 2021 09:04:39 +0100 +Subject: [PATCH 5/5] 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. + +[Salvatore Bonaccorso: Backport to 1.8.27: Context changes] +--- + src/parse_args.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/src/parse_args.c ++++ b/src/parse_args.c +@@ -563,16 +563,16 @@ parse_args(int argc, char **argv, int *n + 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 != '$') diff --git a/debian/patches/Fix-a-buffer-overflow-when-pwfeedback-is-enabled-and.patch b/debian/patches/Fix-a-buffer-overflow-when-pwfeedback-is-enabled-and.patch new file mode 100644 index 0000000..5d6f227 --- /dev/null +++ b/debian/patches/Fix-a-buffer-overflow-when-pwfeedback-is-enabled-and.patch @@ -0,0 +1,95 @@ +From: "Todd C. Miller" <Todd.Miller@sudo.ws> +Date: Wed, 29 Jan 2020 20:15:21 -0700 +Subject: Fix a buffer overflow when pwfeedback is enabled and input is a not a + tty. In getln() if the user enters ^U (erase line) and the write(2) fails, + the remaining buffer size is reset but the current pointer is not. While + here, fix an incorrect break for erase when write(2) fails. Also disable + pwfeedback when input is not a tty as it cannot work. CVE-2019-18634 Credit: + Joe Vennix from Apple Information Security. +Origin: https://github.com/sudo-project/sudo/commit/b5d2010b6514ff45693509273bb07df3abb0bf0a +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-18634 +Bug-Debian: https://bugs.debian.org/950371 + +--HG-- +branch : 1.8 +[Salvatore Bonaccorso: Backport to 1.8.27 for context changes] +--- + src/tgetpass.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +--- a/src/tgetpass.c ++++ b/src/tgetpass.c +@@ -60,7 +60,7 @@ static volatile sig_atomic_t signo[NSIG] + + static bool tty_present(void); + static void tgetpass_handler(int); +-static char *getln(int, char *, size_t, int, enum tgetpass_errval *); ++static char *getln(int, char *, size_t, bool, enum tgetpass_errval *); + static char *sudo_askpass(const char *, const char *); + + static int +@@ -123,6 +123,7 @@ tgetpass(const char *prompt, int timeout + static const char *askpass; + static char buf[SUDO_CONV_REPL_MAX + 1]; + int i, input, output, save_errno, neednl = 0, need_restart; ++ bool feedback = ISSET(flags, TGP_MASK); + enum tgetpass_errval errval; + debug_decl(tgetpass, SUDO_DEBUG_CONV) + +@@ -170,7 +171,7 @@ restart: + */ + if (!ISSET(flags, TGP_ECHO)) { + for (;;) { +- if (ISSET(flags, TGP_MASK)) ++ if (feedback) + neednl = sudo_term_cbreak(input); + else + neednl = sudo_term_noecho(input); +@@ -184,6 +185,9 @@ restart: + } + } + } ++ /* Only use feedback mode when we can disable echo. */ ++ if (!neednl) ++ feedback = false; + + /* + * Catch signals that would otherwise cause the user to end +@@ -209,7 +213,7 @@ restart: + + if (timeout > 0) + alarm(timeout); +- pass = getln(input, buf, sizeof(buf), ISSET(flags, TGP_MASK), &errval); ++ pass = getln(input, buf, sizeof(buf), feedback, &errval); + alarm(0); + save_errno = errno; + +@@ -345,7 +349,7 @@ sudo_askpass(const char *askpass, const + extern int sudo_term_eof, sudo_term_erase, sudo_term_kill; + + static char * +-getln(int fd, char *buf, size_t bufsiz, int feedback, ++getln(int fd, char *buf, size_t bufsiz, bool feedback, + enum tgetpass_errval *errval) + { + size_t left = bufsiz; +@@ -374,15 +378,15 @@ getln(int fd, char *buf, size_t bufsiz, + while (cp > buf) { + if (write(fd, "\b \b", 3) == -1) + break; +- --cp; ++ cp--; + } ++ cp = buf; + left = bufsiz; + continue; + } else if (c == sudo_term_erase) { + if (cp > buf) { +- if (write(fd, "\b \b", 3) == -1) +- break; +- --cp; ++ ignore_result(write(fd, "\b \b", 3)); ++ cp--; + left++; + } + continue; diff --git a/debian/patches/Fix-potential-buffer-overflow-when-unescaping-backsl.patch b/debian/patches/Fix-potential-buffer-overflow-when-unescaping-backsl.patch new file mode 100644 index 0000000..414c0d9 --- /dev/null +++ b/debian/patches/Fix-potential-buffer-overflow-when-unescaping-backsl.patch @@ -0,0 +1,71 @@ +From 1e94630a10326635ea5cdd8dc575f43e40a80469 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" <Todd.Miller@sudo.ws> +Date: Wed, 20 Jan 2021 09:03:43 +0100 +Subject: [PATCH 3/5] Fix potential buffer overflow when unescaping backslashes + in user_args. + +Do not try to unescaping backslashes unless in run mode *and* we are +running the command via a shell. +Found by Qualys. + +[Salvatore Bonaccorso: Backport to 1.8.27: Context changes] +--- + plugins/sudoers/sudoers.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +--- a/plugins/sudoers/sudoers.c ++++ b/plugins/sudoers/sudoers.c +@@ -404,7 +404,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; + +@@ -784,8 +784,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)) +@@ -823,7 +823,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 +@@ -831,10 +832,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 --git a/debian/patches/Fix-the-memset-offset-when-converting-a-v1-timestamp.patch b/debian/patches/Fix-the-memset-offset-when-converting-a-v1-timestamp.patch new file mode 100644 index 0000000..aa46b0f --- /dev/null +++ b/debian/patches/Fix-the-memset-offset-when-converting-a-v1-timestamp.patch @@ -0,0 +1,30 @@ +From 6ab23a7a9fe7be865e5c93363b520c704867326a Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" <Todd.Miller@sudo.ws> +Date: Wed, 20 Jan 2021 09:04:12 +0100 +Subject: [PATCH 4/5] 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. +--- + plugins/sudoers/timestamp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/plugins/sudoers/timestamp.c b/plugins/sudoers/timestamp.c +index ace568e5a4fe..dfc9bdfc5f26 100644 +--- a/plugins/sudoers/timestamp.c ++++ b/plugins/sudoers/timestamp.c +@@ -643,8 +643,8 @@ timestamp_lock(void *vcookie, struct passwd *pw) + 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 { +-- +2.30.0 + diff --git a/debian/patches/Reset-valid_flags-to-MODE_NONINTERACTIVE-for-sudoedi.patch b/debian/patches/Reset-valid_flags-to-MODE_NONINTERACTIVE-for-sudoedi.patch new file mode 100644 index 0000000..ac62729 --- /dev/null +++ b/debian/patches/Reset-valid_flags-to-MODE_NONINTERACTIVE-for-sudoedi.patch @@ -0,0 +1,97 @@ +From 6f726f8a6f5e203ae2f4675902ba4aa03a8393af Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" <Todd.Miller@sudo.ws> +Date: Wed, 20 Jan 2021 09:02:42 +0100 +Subject: [PATCH 1/5] 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. + +[Salvatore Bonaccorso: Backport to 1.8.27: Context changes] +--- + src/parse_args.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/src/parse_args.c ++++ b/src/parse_args.c +@@ -121,7 +121,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 +@@ -265,6 +268,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. */ +@@ -350,7 +354,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') +@@ -360,6 +364,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) { +@@ -409,7 +414,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); +@@ -417,6 +422,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. */ +@@ -460,7 +466,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) +@@ -487,7 +493,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; +@@ -550,7 +556,7 @@ 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; + diff --git a/debian/patches/Sanity-check-size-when-converting-the-first-record-t.patch b/debian/patches/Sanity-check-size-when-converting-the-first-record-t.patch new file mode 100644 index 0000000..c0964be --- /dev/null +++ b/debian/patches/Sanity-check-size-when-converting-the-first-record-t.patch @@ -0,0 +1,107 @@ +From 586b418ad85ff8c2e756eff7063ffaeca631fa02 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" <Todd.Miller@sudo.ws> +Date: Sun, 5 Jan 2020 09:37:09 -0700 +Subject: [PATCH] Sanity check size when converting the first record to + TS_LOCKEXCL Coverity CID 206591 + +[Salvatore Bonaccorso: Backport to 1.8.27: + - Context changes + - Drop hunk about copyright years update + - Cast sizeof(struct timestamp_entry_v1) into ssize_t as 1.8.27 does + not contain the "Add ssizeof macro that returns ssize_t" change. +] +--- + plugins/sudoers/timestamp.c | 65 ++++++++++++++++++++++++++++--------- + 1 file changed, 49 insertions(+), 16 deletions(-) + +--- a/plugins/sudoers/timestamp.c ++++ b/plugins/sudoers/timestamp.c +@@ -611,6 +611,25 @@ done: + } + + /* ++ * Write a TS_LOCKEXCL record at the beginning of the time stamp file. ++ */ ++bool ++timestamp_lock_write(struct ts_cookie *cookie) ++{ ++ struct timestamp_entry entry; ++ bool ret = true; ++ debug_decl(timestamp_lock_write, SUDOERS_DEBUG_AUTH); ++ ++ memset(&entry, 0, sizeof(entry)); ++ entry.version = TS_VERSION; ++ entry.size = sizeof(entry); ++ entry.type = TS_LOCKEXCL; ++ if (ts_write(cookie->fd, cookie->fname, &entry, -1) == -1) ++ ret = false; ++ debug_return_bool(ret); ++} ++ ++/* + * Lock a record in the time stamp file for exclusive access. + * If the record does not exist, it is created (as disabled). + */ +@@ -619,6 +638,7 @@ timestamp_lock(void *vcookie, struct pas + { + struct ts_cookie *cookie = vcookie; + struct timestamp_entry entry; ++ bool overwrite = false; + off_t lock_pos; + ssize_t nread; + debug_decl(timestamp_lock, SUDOERS_DEBUG_AUTH) +@@ -640,26 +660,39 @@ timestamp_lock(void *vcookie, struct pas + /* Make sure the first record is of type TS_LOCKEXCL. */ + memset(&entry, 0, sizeof(entry)); + nread = read(cookie->fd, &entry, sizeof(entry)); +- if (nread == 0) { +- /* New file, add TS_LOCKEXCL record. */ +- entry.version = TS_VERSION; +- entry.size = sizeof(entry); +- entry.type = TS_LOCKEXCL; +- if (ts_write(cookie->fd, cookie->fname, &entry, -1) == -1) +- debug_return_bool(false); ++ if (nread < (ssize_t)sizeof(struct timestamp_entry_v1)) { ++ /* New or invalid time stamp file. */ ++ overwrite = true; + } 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)); +- if (ts_write(cookie->fd, cookie->fname, &entry, 0) == -1) +- debug_return_bool(false); ++ 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)); ++ if (ts_write(cookie->fd, cookie->fname, &entry, 0) == -1) ++ debug_return_bool(false); ++ } else { ++ /* Corrupted time stamp file? Just overwrite it. */ ++ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, ++ "corrupt initial record, type: %hu, size: %hu (expected %zu)", ++ entry.type, entry.size, sizeof(struct timestamp_entry_v1)); ++ overwrite = true; ++ } + } +- if (entry.size != sizeof(entry)) { ++ if (overwrite) { ++ /* Rewrite existing time stamp file or create new one. */ ++ if (ftruncate(cookie->fd, 0) != 0) { ++ sudo_warn(U_("unable to truncate time stamp file to %lld bytes"), ++ 0LL); ++ debug_return_bool(false); ++ } ++ if (!timestamp_lock_write(cookie)) ++ debug_return_bool(false); ++ } else if (entry.size != sizeof(entry)) { + /* Reset position if the lock record has an unexpected size. */ + if (lseek(cookie->fd, entry.size, SEEK_SET) == -1) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, +- "unable to seek to %lld", (long long)entry.size); ++ "unable to seek to %hu", entry.size); + debug_return_bool(false); + } + } diff --git a/debian/patches/Whitelist-DPKG_COLORS-environment-variable.diff b/debian/patches/Whitelist-DPKG_COLORS-environment-variable.diff new file mode 100644 index 0000000..c2e1711 --- /dev/null +++ b/debian/patches/Whitelist-DPKG_COLORS-environment-variable.diff @@ -0,0 +1,24 @@ +From 18087bc16ec20ca2c8f0045a6b0408e94c53075c Mon Sep 17 00:00:00 2001 +From: Guillem Jover <guillem@hadrons.org> +Date: Wed, 4 May 2016 01:53:13 +0200 +Subject: [PATCH] Whitelist DPKG_COLORS environment variable + +--- + plugins/sudoers/env.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/plugins/sudoers/env.c b/plugins/sudoers/env.c +index 9065250..c037bd8 100644 +--- a/plugins/sudoers/env.c ++++ b/plugins/sudoers/env.c +@@ -188,6 +188,7 @@ static const char *initial_checkenv_table[] = { + static const char *initial_keepenv_table[] = { + "COLORS", + "DISPLAY", ++ "DPKG_COLORS", + "HOSTNAME", + "KRB5CCNAME", + "LS_COLORS", +-- +2.8.1 + diff --git a/debian/patches/paths-in-samples.diff b/debian/patches/paths-in-samples.diff new file mode 100644 index 0000000..4fef5d9 --- /dev/null +++ b/debian/patches/paths-in-samples.diff @@ -0,0 +1,40 @@ +--- a/examples/sudoers ++++ b/examples/sudoers +@@ -44,10 +44,10 @@ + # Cmnd alias specification + ## + Cmnd_Alias DUMPS = /usr/sbin/dump, /usr/sbin/rdump, /usr/sbin/restore, \ +- /usr/sbin/rrestore, /usr/bin/mt, \ ++ /usr/sbin/rrestore, /bin/mt, \ + sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \ + /home/operator/bin/start_backups +-Cmnd_Alias KILL = /usr/bin/kill, /usr/bin/top ++Cmnd_Alias KILL = /bin/kill, /usr/bin/top + Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm + Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown + Cmnd_Alias HALT = /usr/sbin/halt +@@ -85,7 +85,7 @@ + sudoedit /etc/printcap, /usr/oper/bin/ + + # joe may su only to operator +-joe ALL = /usr/bin/su operator ++joe ALL = /bin/su operator + + # pete may change passwords for anyone but root on the hp snakes + pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd *root* +@@ -99,13 +99,13 @@ + + # users in the secretaries netgroup need to help manage the printers + # as well as add and remove users +-+secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser +++secretaries ALL = PRINTING, /usr/sbin/adduser + + # fred can run commands as oracle or sybase without a password + fred ALL = (DB) NOPASSWD: ALL + + # on the alphas, john may su to anyone but root and flags are not allowed +-john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root* ++john ALPHA = /bin/su [!-]*, !/bin/su *root* + + # jen can run anything on all machines except the ones + # in the "SERVERS" Host_Alias diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..fe0bf5a --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,12 @@ +typo-in-classic-insults.diff +paths-in-samples.diff +Whitelist-DPKG_COLORS-environment-variable.diff +sudo_minus_1_uid.diff +strtoid_minus_1_test_fix.diff +Fix-a-buffer-overflow-when-pwfeedback-is-enabled-and.patch +Sanity-check-size-when-converting-the-first-record-t.patch +Reset-valid_flags-to-MODE_NONINTERACTIVE-for-sudoedi.patch +Add-sudoedit-flag-checks-in-plugin-that-are-consiste.patch +Fix-potential-buffer-overflow-when-unescaping-backsl.patch +Fix-the-memset-offset-when-converting-a-v1-timestamp.patch +Don-t-assume-that-argv-is-allocated-as-a-single-flat.patch diff --git a/debian/patches/strtoid_minus_1_test_fix.diff b/debian/patches/strtoid_minus_1_test_fix.diff new file mode 100644 index 0000000..6a2f148 --- /dev/null +++ b/debian/patches/strtoid_minus_1_test_fix.diff @@ -0,0 +1,103 @@ +Description: Fix test failure in plugins/sudoers/regress/testsudoers/test5.sh + Fix test failure after fix for CVE-2019-14287 . +Origin: upstream +Author: Todd C. Miller <Todd.Miller@sudo.ws> +Reviewed-by: Salvatore Bonaccorso <carnil@debian.org> +Last-Update: 2019-10-10 + +diff -r fcd7a6d8330e lib/util/regress/atofoo/atofoo_test.c +--- a/lib/util/regress/atofoo/atofoo_test.c Fri Jan 11 13:31:15 2019 -0700 ++++ b/lib/util/regress/atofoo/atofoo_test.c Thu Oct 10 14:02:30 2019 -0600 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014 Todd C. Miller <Todd.Miller@sudo.ws> ++ * Copyright (c) 2014-2019 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 +@@ -24,6 +24,7 @@ + #else + # include "compat/stdbool.h" + #endif ++#include <errno.h> + + #include "sudo_compat.h" + #include "sudo_util.h" +@@ -78,15 +79,20 @@ static struct strtoid_data { + id_t id; + const char *sep; + const char *ep; ++ int errnum; + } strtoid_data[] = { +- { "0,1", 0, ",", "," }, +- { "10", 10, NULL, NULL }, +- { "-2", -2, NULL, NULL }, ++ { "0,1", 0, ",", ",", 0 }, ++ { "10", 10, NULL, NULL, 0 }, ++ { "-1", 0, NULL, NULL, EINVAL }, ++ { "4294967295", 0, NULL, NULL, EINVAL }, ++ { "4294967296", 0, NULL, NULL, ERANGE }, ++ { "-2147483649", 0, NULL, NULL, ERANGE }, ++ { "-2", -2, NULL, NULL, 0 }, + #if SIZEOF_ID_T != SIZEOF_LONG_LONG +- { "-2", (id_t)4294967294U, NULL, NULL }, ++ { "-2", (id_t)4294967294U, NULL, NULL, 0 }, + #endif +- { "4294967294", (id_t)4294967294U, NULL, NULL }, +- { NULL, 0, NULL, NULL } ++ { "4294967294", (id_t)4294967294U, NULL, NULL, 0 }, ++ { NULL, 0, NULL, NULL, 0 } + }; + + static int +@@ -102,11 +108,23 @@ test_strtoid(int *ntests) + (*ntests)++; + errstr = "some error"; + value = sudo_strtoid(d->idstr, d->sep, &ep, &errstr); +- if (errstr != NULL) { +- if (d->id != (id_t)-1) { +- sudo_warnx_nodebug("FAIL: %s: %s", d->idstr, errstr); ++ if (d->errnum != 0) { ++ if (errstr == NULL) { ++ sudo_warnx_nodebug("FAIL: %s: missing errstr for errno %d", ++ d->idstr, d->errnum); ++ errors++; ++ } else if (value != 0) { ++ sudo_warnx_nodebug("FAIL: %s should return 0 on error", ++ d->idstr); ++ errors++; ++ } else if (errno != d->errnum) { ++ sudo_warnx_nodebug("FAIL: %s: errno mismatch, %d != %d", ++ d->idstr, errno, d->errnum); + errors++; + } ++ } else if (errstr != NULL) { ++ sudo_warnx_nodebug("FAIL: %s: %s", d->idstr, errstr); ++ errors++; + } else if (value != d->id) { + sudo_warnx_nodebug("FAIL: %s != %u", d->idstr, (unsigned int)d->id); + errors++; +diff -r fcd7a6d8330e plugins/sudoers/regress/testsudoers/test5.out.ok +--- a/plugins/sudoers/regress/testsudoers/test5.out.ok Fri Jan 11 13:31:15 2019 -0700 ++++ b/plugins/sudoers/regress/testsudoers/test5.out.ok Thu Oct 10 14:02:30 2019 -0600 +@@ -4,7 +4,7 @@ Parse error in sudoers near line 1. + Entries for user root: + + Command unmatched +-testsudoers: test5.inc should be owned by gid 4294967295 ++testsudoers: test5.inc should be owned by gid 4294967294 + Parse error in sudoers near line 1. + + Entries for user root: +diff -r fcd7a6d8330e plugins/sudoers/regress/testsudoers/test5.sh +--- a/plugins/sudoers/regress/testsudoers/test5.sh Fri Jan 11 13:31:15 2019 -0700 ++++ b/plugins/sudoers/regress/testsudoers/test5.sh Thu Oct 10 14:02:30 2019 -0600 +@@ -24,7 +24,7 @@ EOF + + # Test group writable + chmod 664 $TESTFILE +-./testsudoers -U $MYUID -G -1 root id <<EOF ++./testsudoers -U $MYUID -G -2 root id <<EOF + #include $TESTFILE + EOF + diff --git a/debian/patches/sudo_minus_1_uid.diff b/debian/patches/sudo_minus_1_uid.diff new file mode 100644 index 0000000..167b75d --- /dev/null +++ b/debian/patches/sudo_minus_1_uid.diff @@ -0,0 +1,177 @@ +Description: Treat an ID of -1 as invalid since that means "no change". + Fixes CVE-2019-14287. + Found by Joe Vennix from Apple Information Security. +Origin: upstream +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-14287 +Author: Todd C. Miller <Todd.Miller@sudo.ws> +Reviewed-by: Salvatore Bonaccorso <carnil@debian.org> +Last-Update: 2019-10-10 + +diff -r fcd7a6d8330e lib/util/strtoid.c +--- a/lib/util/strtoid.c Fri Jan 11 13:31:15 2019 -0700 ++++ b/lib/util/strtoid.c Thu Oct 10 09:52:12 2019 -0600 +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2016 Todd C. Miller <Todd.Miller@sudo.ws> ++ * Copyright (c) 2013-2019 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 +@@ -47,6 +47,27 @@ + #include "sudo_util.h" + + /* ++ * Make sure that the ID ends with a valid separator char. ++ */ ++static bool ++valid_separator(const char *p, const char *ep, const char *sep) ++{ ++ bool valid = false; ++ debug_decl(valid_separator, SUDO_DEBUG_UTIL) ++ ++ if (ep != p) { ++ /* check for valid separator (including '\0') */ ++ if (sep == NULL) ++ sep = ""; ++ do { ++ if (*ep == *sep) ++ valid = true; ++ } while (*sep++ != '\0'); ++ } ++ debug_return_bool(valid); ++} ++ ++/* + * Parse a uid/gid in string form. + * If sep is non-NULL, it contains valid separator characters (e.g. comma, space) + * If endp is non-NULL it is set to the next char after the ID. +@@ -60,38 +81,35 @@ sudo_strtoid_v1(const char *p, const cha + char *ep; + id_t ret = 0; + long long llval; +- bool valid = false; + debug_decl(sudo_strtoid, SUDO_DEBUG_UTIL) + + /* skip leading space so we can pick up the sign, if any */ + while (isspace((unsigned char)*p)) + p++; +- if (sep == NULL) +- sep = ""; ++ ++ /* While id_t may be 64-bit signed, uid_t and gid_t are 32-bit unsigned. */ + errno = 0; + llval = strtoll(p, &ep, 10); +- if (ep != p) { +- /* check for valid separator (including '\0') */ +- do { +- if (*ep == *sep) +- valid = true; +- } while (*sep++ != '\0'); ++ if ((errno == ERANGE && llval == LLONG_MAX) || llval > (id_t)UINT_MAX) { ++ errno = ERANGE; ++ if (errstr != NULL) ++ *errstr = N_("value too large"); ++ goto done; + } +- if (!valid) { ++ if ((errno == ERANGE && llval == LLONG_MIN) || llval < INT_MIN) { ++ errno = ERANGE; ++ if (errstr != NULL) ++ *errstr = N_("value too small"); ++ goto done; ++ } ++ ++ /* Disallow id -1, which means "no change". */ ++ if (!valid_separator(p, ep, sep) || llval == -1 || llval == (id_t)UINT_MAX) { + if (errstr != NULL) + *errstr = N_("invalid value"); + errno = EINVAL; + goto done; + } +- if (errno == ERANGE) { +- if (errstr != NULL) { +- if (llval == LLONG_MAX) +- *errstr = N_("value too large"); +- else +- *errstr = N_("value too small"); +- } +- goto done; +- } + ret = (id_t)llval; + if (errstr != NULL) + *errstr = NULL; +@@ -106,30 +124,15 @@ sudo_strtoid_v1(const char *p, const cha + { + char *ep; + id_t ret = 0; +- bool valid = false; + debug_decl(sudo_strtoid, SUDO_DEBUG_UTIL) + + /* skip leading space so we can pick up the sign, if any */ + while (isspace((unsigned char)*p)) + p++; +- if (sep == NULL) +- sep = ""; ++ + errno = 0; + if (*p == '-') { + long lval = strtol(p, &ep, 10); +- if (ep != p) { +- /* check for valid separator (including '\0') */ +- do { +- if (*ep == *sep) +- valid = true; +- } while (*sep++ != '\0'); +- } +- if (!valid) { +- if (errstr != NULL) +- *errstr = N_("invalid value"); +- errno = EINVAL; +- goto done; +- } + if ((errno == ERANGE && lval == LONG_MAX) || lval > INT_MAX) { + errno = ERANGE; + if (errstr != NULL) +@@ -142,28 +145,31 @@ sudo_strtoid_v1(const char *p, const cha + *errstr = N_("value too small"); + goto done; + } +- ret = (id_t)lval; +- } else { +- unsigned long ulval = strtoul(p, &ep, 10); +- if (ep != p) { +- /* check for valid separator (including '\0') */ +- do { +- if (*ep == *sep) +- valid = true; +- } while (*sep++ != '\0'); +- } +- if (!valid) { ++ ++ /* Disallow id -1, which means "no change". */ ++ if (!valid_separator(p, ep, sep) || lval == -1) { + if (errstr != NULL) + *errstr = N_("invalid value"); + errno = EINVAL; + goto done; + } ++ ret = (id_t)lval; ++ } else { ++ unsigned long ulval = strtoul(p, &ep, 10); + if ((errno == ERANGE && ulval == ULONG_MAX) || ulval > UINT_MAX) { + errno = ERANGE; + if (errstr != NULL) + *errstr = N_("value too large"); + goto done; + } ++ ++ /* Disallow id -1, which means "no change". */ ++ if (!valid_separator(p, ep, sep) || ulval == UINT_MAX) { ++ if (errstr != NULL) ++ *errstr = N_("invalid value"); ++ errno = EINVAL; ++ goto done; ++ } + ret = (id_t)ulval; + } + if (errstr != NULL) diff --git a/debian/patches/typo-in-classic-insults.diff b/debian/patches/typo-in-classic-insults.diff new file mode 100644 index 0000000..57e78c6 --- /dev/null +++ b/debian/patches/typo-in-classic-insults.diff @@ -0,0 +1,11 @@ +--- a/plugins/sudoers/ins_classic.h ++++ b/plugins/sudoers/ins_classic.h +@@ -30,7 +30,7 @@ + "Where did you learn to type?", + "Are you on drugs?", + "My pet ferret can type better than you!", +- "You type like i drive.", ++ "You type like I drive.", + "Do you think like you type?", + "Your mind just hasn't been the same since the electro-shock, has it?", + |