Control: tags 942322 + patch Control: tags 942322 + pending Hi Bdale,
I've prepared an NMU for sudo (versioned as 1.8.27-1.1) and uploaded it to DELAYED/2. Please feel free to tell me if I should delay it longer. Though it might be better to move to the new upstream version for unstable? Can you as well import the already released updates for stretch-security and buster-security? Regards, Salvatore
diff -Nru sudo-1.8.27/debian/changelog sudo-1.8.27/debian/changelog --- sudo-1.8.27/debian/changelog 2019-01-12 19:10:05.000000000 +0100 +++ sudo-1.8.27/debian/changelog 2019-10-14 21:10:58.000000000 +0200 @@ -1,3 +1,12 @@ +sudo (1.8.27-1.1) unstable; urgency=high + + * Non-maintainer upload. + * Treat an ID of -1 as invalid since that means "no change" (CVE-2019-14287) + (Closes: #942322) + * Fix test failure in plugins/sudoers/regress/testsudoers/test5.sh + + -- Salvatore Bonaccorso <car...@debian.org> Mon, 14 Oct 2019 21:10:58 +0200 + sudo (1.8.27-1) unstable; urgency=medium * new upstream version diff -Nru sudo-1.8.27/debian/patches/series sudo-1.8.27/debian/patches/series --- sudo-1.8.27/debian/patches/series 2019-01-12 19:10:05.000000000 +0100 +++ sudo-1.8.27/debian/patches/series 2019-10-14 21:10:58.000000000 +0200 @@ -1,3 +1,5 @@ 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 diff -Nru sudo-1.8.27/debian/patches/strtoid_minus_1_test_fix.diff sudo-1.8.27/debian/patches/strtoid_minus_1_test_fix.diff --- sudo-1.8.27/debian/patches/strtoid_minus_1_test_fix.diff 1970-01-01 01:00:00.000000000 +0100 +++ sudo-1.8.27/debian/patches/strtoid_minus_1_test_fix.diff 2019-10-14 21:10:58.000000000 +0200 @@ -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.mil...@sudo.ws> +Reviewed-by: Salvatore Bonaccorso <car...@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.mil...@sudo.ws> ++ * Copyright (c) 2014-2019 Todd C. Miller <todd.mil...@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 -Nru sudo-1.8.27/debian/patches/sudo_minus_1_uid.diff sudo-1.8.27/debian/patches/sudo_minus_1_uid.diff --- sudo-1.8.27/debian/patches/sudo_minus_1_uid.diff 1970-01-01 01:00:00.000000000 +0100 +++ sudo-1.8.27/debian/patches/sudo_minus_1_uid.diff 2019-10-14 21:10:58.000000000 +0200 @@ -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.mil...@sudo.ws> +Reviewed-by: Salvatore Bonaccorso <car...@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.mil...@sudo.ws> ++ * Copyright (c) 2013-2019 Todd C. Miller <todd.mil...@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)