mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-22 01:49:11 +00:00
Treat an ID of -1 as invalid since that means "no change".
Fixes CVE-2019-14287. Found by Joe Vennix from Apple Information Security.
This commit is contained in:
parent
fd5d0f511e
commit
f752ae5cee
4
NEWS
4
NEWS
@ -76,6 +76,10 @@ What's new in Sudo 1.8.28
|
||||
* Fixed a bug where the terminal's file context was not restored
|
||||
when using SELinux RBAC. Bug #898.
|
||||
|
||||
* Fixed CVE-2019-14287, a bug where a sudo user may be able to
|
||||
run a command as root when the Runas specification explicitly
|
||||
disallows root access as long as the ALL keyword is listed first.
|
||||
|
||||
What's new in Sudo 1.8.27
|
||||
|
||||
* On HP-UX, sudo will now update the utmps file when running a command
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* 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
|
||||
@ -48,6 +48,27 @@
|
||||
#include "sudo_debug.h"
|
||||
#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)
|
||||
@ -62,38 +83,35 @@ sudo_strtoid_v1(const char *p, const char *sep, char **endp, const char **errstr
|
||||
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;
|
||||
@ -108,30 +126,15 @@ sudo_strtoid_v1(const char *p, const char *sep, char **endp, const char **errstr
|
||||
{
|
||||
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)
|
||||
@ -144,28 +147,31 @@ sudo_strtoid_v1(const char *p, const char *sep, char **endp, const char **errstr
|
||||
*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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user