basebuilder_pel7ppc64lebuilder0
5 years ago
5 changed files with 466 additions and 15 deletions
@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
|
||||
|
||||
# HG changeset patch |
||||
# User Todd C. Miller <Todd.Miller@sudo.ws> |
||||
# Date 1544201494 25200 |
||||
# Node ID 656aa910fbaf0be517e012c9271c51eb85c1cca5 |
||||
# Parent ef83f35c9cb090a8b4fd36942f1e47e65c285dce |
||||
The fix for bug #843 was incomplete and caused pam_end() to be called early. |
||||
sudo_pam_approval() must not set the global pam status to an error |
||||
value if it returns AUTH_SUCCESS. Otherwise, sudo_pam_cleanup() |
||||
will call pam_end() before sudo_pam_begin_session(). This resulted |
||||
in a NULL PAM handle being used in sudo_pam_begin_session(). |
||||
|
||||
diff -r ef83f35c9cb0 -r 656aa910fbaf plugins/sudoers/auth/pam.c |
||||
--- a/plugins/sudoers/auth/pam.c Wed Dec 05 10:43:14 2018 -0700 |
||||
+++ b/plugins/sudoers/auth/pam.c Fri Dec 07 09:51:34 2018 -0700 |
||||
@@ -210,59 +210,68 @@ |
||||
sudo_pam_approval(struct passwd *pw, sudo_auth *auth, bool exempt) |
||||
{ |
||||
const char *s; |
||||
+ int rc, status = AUTH_SUCCESS; |
||||
int *pam_status = (int *) auth->data; |
||||
debug_decl(sudo_pam_approval, SUDOERS_DEBUG_AUTH) |
||||
|
||||
- *pam_status = pam_acct_mgmt(pamh, PAM_SILENT); |
||||
- switch (*pam_status) { |
||||
+ rc = pam_acct_mgmt(pamh, PAM_SILENT); |
||||
+ switch (rc) { |
||||
case PAM_SUCCESS: |
||||
- debug_return_int(AUTH_SUCCESS); |
||||
+ break; |
||||
case PAM_AUTH_ERR: |
||||
log_warningx(0, N_("account validation failure, " |
||||
"is your account locked?")); |
||||
- debug_return_int(AUTH_FATAL); |
||||
+ status = AUTH_FATAL; |
||||
+ break; |
||||
case PAM_NEW_AUTHTOK_REQD: |
||||
/* Ignore if user is exempt from password restrictions. */ |
||||
if (exempt) |
||||
- debug_return_int(AUTH_SUCCESS); |
||||
+ break; |
||||
/* New password required, try to change it. */ |
||||
log_warningx(0, N_("Account or password is " |
||||
"expired, reset your password and try again")); |
||||
- *pam_status = pam_chauthtok(pamh, |
||||
- PAM_CHANGE_EXPIRED_AUTHTOK); |
||||
- if (*pam_status == PAM_SUCCESS) |
||||
- debug_return_int(AUTH_SUCCESS); |
||||
- if ((s = pam_strerror(pamh, *pam_status)) == NULL) |
||||
+ rc = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); |
||||
+ if (rc == PAM_SUCCESS) |
||||
+ break; |
||||
+ if ((s = pam_strerror(pamh, rc)) == NULL) |
||||
s = "unknown error"; |
||||
log_warningx(0, |
||||
N_("unable to change expired password: %s"), s); |
||||
- debug_return_int(AUTH_FAILURE); |
||||
+ status = AUTH_FAILURE; |
||||
+ break; |
||||
case PAM_AUTHTOK_EXPIRED: |
||||
/* Ignore if user is exempt from password restrictions. */ |
||||
if (exempt) |
||||
- debug_return_int(AUTH_SUCCESS); |
||||
+ break; |
||||
/* Password expired, cannot be updated by user. */ |
||||
log_warningx(0, |
||||
N_("Password expired, contact your system administrator")); |
||||
- debug_return_int(AUTH_FATAL); |
||||
+ status = AUTH_FATAL; |
||||
+ break; |
||||
case PAM_ACCT_EXPIRED: |
||||
log_warningx(0, |
||||
N_("Account expired or PAM config lacks an \"account\" " |
||||
"section for sudo, contact your system administrator")); |
||||
- debug_return_int(AUTH_FATAL); |
||||
+ status = AUTH_FATAL; |
||||
+ break; |
||||
case PAM_AUTHINFO_UNAVAIL: |
||||
case PAM_MAXTRIES: |
||||
case PAM_PERM_DENIED: |
||||
- s = pam_strerror(pamh, *pam_status); |
||||
+ s = pam_strerror(pamh, rc); |
||||
log_warningx(0, N_("PAM account management error: %s"), |
||||
s ? s : "unknown error"); |
||||
- debug_return_int(AUTH_FAILURE); |
||||
+ status = AUTH_FAILURE; |
||||
+ break; |
||||
default: |
||||
- s = pam_strerror(pamh, *pam_status); |
||||
+ s = pam_strerror(pamh, rc); |
||||
log_warningx(0, N_("PAM account management error: %s"), |
||||
s ? s : "unknown error"); |
||||
- debug_return_int(AUTH_FATAL); |
||||
+ status = AUTH_FATAL; |
||||
+ break; |
||||
} |
||||
+ /* Ignore errors if user is exempt from password restrictions. */ |
||||
+ *pam_status = exempt ? PAM_SUCCESS : rc; |
||||
+ debug_return_int(status); |
||||
} |
||||
|
||||
int |
||||
|
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
commit b2f7983c84fd01e0b29895d7df776b4b162fd8a5 |
||||
Author: Todd C. Miller <Todd.Miller@sudo.ws> |
||||
Date: Wed Jan 2 07:39:33 2019 -0700 |
||||
|
||||
Fix setting of utmp entry when running command in a pty. |
||||
Regression introduced in sudo 1.8.22. |
||||
|
||||
diff --git a/src/exec_pty.c b/src/exec_pty.c |
||||
index cbcccca3..68312a98 100644 |
||||
--- a/src/exec_pty.c |
||||
+++ b/src/exec_pty.c |
||||
@@ -140,7 +140,7 @@ pty_cleanup(void) |
||||
* and slavename globals. |
||||
*/ |
||||
static bool |
||||
-pty_setup(uid_t uid, const char *tty) |
||||
+pty_setup(struct command_details *details, const char *tty) |
||||
{ |
||||
debug_decl(pty_setup, SUDO_DEBUG_EXEC); |
||||
|
||||
@@ -152,12 +152,15 @@ pty_setup(uid_t uid, const char *tty) |
||||
} |
||||
|
||||
if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE], |
||||
- slavename, sizeof(slavename), uid)) |
||||
+ slavename, sizeof(slavename), details->euid)) |
||||
sudo_fatal(U_("unable to allocate pty")); |
||||
|
||||
/* Add entry to utmp/utmpx? */ |
||||
- if (utmp_user != NULL) |
||||
+ if (ISSET(details->flags, CD_SET_UTMP)) { |
||||
+ utmp_user = |
||||
+ details->utmp_user ? details->utmp_user : user_details.username; |
||||
utmp_login(tty, slavename, io_fds[SFD_SLAVE], utmp_user); |
||||
+ } |
||||
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, |
||||
"%s: %s fd %d, pty master fd %d, pty slave fd %d", |
||||
@@ -1302,12 +1305,11 @@ exec_pty(struct command_details *details, struct command_status *cstat) |
||||
/* |
||||
* Allocate a pty. |
||||
*/ |
||||
- if (pty_setup(details->euid, user_details.tty)) { |
||||
- if (ISSET(details->flags, CD_SET_UTMP)) |
||||
- utmp_user = details->utmp_user ? details->utmp_user : user_details.username; |
||||
- } else if (TAILQ_EMPTY(&io_plugins)) { |
||||
- /* Not logging I/O and didn't allocate a pty. */ |
||||
- debug_return_bool(false); |
||||
+ if (!pty_setup(details, user_details.tty)) { |
||||
+ if (TAILQ_EMPTY(&io_plugins)) { |
||||
+ /* Not logging I/O and didn't allocate a pty. */ |
||||
+ debug_return_bool(false); |
||||
+ } |
||||
} |
||||
|
||||
/* |
@ -0,0 +1,96 @@
@@ -0,0 +1,96 @@
|
||||
diff -up ./lib/util/regress/atofoo/atofoo_test.c.CVE-strtouid-test ./lib/util/regress/atofoo/atofoo_test.c |
||||
--- ./lib/util/regress/atofoo/atofoo_test.c.CVE-strtouid-test 2018-04-29 21:59:23.000000000 +0200 |
||||
+++ ./lib/util/regress/atofoo/atofoo_test.c 2019-10-16 09:38:31.851404545 +0200 |
||||
@@ -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", 4294967294U, NULL, NULL }, |
||||
+ { "-2", 4294967294U, NULL, NULL, 0 }, |
||||
#endif |
||||
- { "4294967294", 4294967294U, NULL, NULL }, |
||||
- { NULL, 0, NULL, NULL } |
||||
+ { "4294967294", 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 -up ./plugins/sudoers/regress/testsudoers/test5.out.ok.CVE-strtouid-test ./plugins/sudoers/regress/testsudoers/test5.out.ok |
||||
--- ./plugins/sudoers/regress/testsudoers/test5.out.ok.CVE-strtouid-test 2018-04-29 21:59:23.000000000 +0200 |
||||
+++ ./plugins/sudoers/regress/testsudoers/test5.out.ok 2019-10-16 09:29:50.246761680 +0200 |
||||
@@ -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 -up ./plugins/sudoers/regress/testsudoers/test5.sh.CVE-strtouid-test ./plugins/sudoers/regress/testsudoers/test5.sh |
||||
--- ./plugins/sudoers/regress/testsudoers/test5.sh.CVE-strtouid-test 2018-04-29 21:59:23.000000000 +0200 |
||||
+++ ./plugins/sudoers/regress/testsudoers/test5.sh 2019-10-16 09:29:50.246761680 +0200 |
||||
@@ -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 |
||||
|
@ -0,0 +1,172 @@
@@ -0,0 +1,172 @@
|
||||
Treat an ID of -1 as invalid since that means "no change". |
||||
Fixes CVE-2019-14287. |
||||
Found by Joe Vennix from Apple Information Security. |
||||
|
||||
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) |
Loading…
Reference in new issue