basebuilder_pel7ppc64lebuilder0
5 years ago
5 changed files with 466 additions and 15 deletions
@ -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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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