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)

Reply via email to