!130 fix CVE-2023-42465
From: @qsw333 Reviewed-by: @houmingyong, @licihua Signed-off-by: @licihua
This commit is contained in:
commit
7a9fce11f6
442
backport-CVE-2023-42465.patch
Normal file
442
backport-CVE-2023-42465.patch
Normal file
@ -0,0 +1,442 @@
|
||||
From 7873f8334c8d31031f8cfa83bd97ac6029309e4f Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Sat, 9 Sep 2023 14:07:04 -0600
|
||||
Subject: [PATCH] Try to make sudo less vulnerable to ROWHAMMER attacks.
|
||||
|
||||
We now use ROWHAMMER-resistent values for ALLOW, DENY, AUTH_SUCCESS,
|
||||
AUTH_FAILURE, AUTH_ERROR and AUTH_NONINTERACTIVE. In addition, we
|
||||
explicitly test for expected values instead of using a negated test
|
||||
against an error value. In the parser match functions this means
|
||||
explicitly checking for ALLOW or DENY instead of accepting anything
|
||||
that is not set to UNSPEC.
|
||||
|
||||
Thanks to Andrew J. Adiletta, M. Caner Tol, Yarkin Doroz, and Berk
|
||||
Sunar, all affiliated with the Vernam Applied Cryptography and
|
||||
Cybersecurity Lab at Worcester Polytechnic Institute, for the report.
|
||||
Paper preprint: https://arxiv.org/abs/2309.02545
|
||||
|
||||
Reference: https://github.com/sudo-project/sudo/commit/7873f8334c8d31031f8cfa83bd97ac6029309e4f
|
||||
Conflict: passwd.c sudo_auth.h match.c parse.c
|
||||
---
|
||||
plugins/sudoers/auth/passwd.c | 27 ++++++++++-------
|
||||
plugins/sudoers/auth/sudo_auth.c | 51 ++++++++++++++++++++++----------
|
||||
plugins/sudoers/auth/sudo_auth.h | 10 +++----
|
||||
plugins/sudoers/match.c | 25 ++++++++--------
|
||||
plugins/sudoers/parse.c | 6 ++--
|
||||
plugins/sudoers/parse.h | 23 ++++++++++----
|
||||
6 files changed, 92 insertions(+), 50 deletions(-)
|
||||
|
||||
diff --git a/plugins/sudoers/auth/passwd.c b/plugins/sudoers/auth/passwd.c
|
||||
index bb9f2d6..8f163cb 100644
|
||||
--- a/plugins/sudoers/auth/passwd.c
|
||||
+++ b/plugins/sudoers/auth/passwd.c
|
||||
@@ -62,7 +62,7 @@ sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_c
|
||||
char des_pass[9], *epass;
|
||||
char *pw_epasswd = auth->data;
|
||||
size_t pw_len;
|
||||
- int matched = 0;
|
||||
+ int ret;
|
||||
debug_decl(sudo_passwd_verify, SUDOERS_DEBUG_AUTH);
|
||||
|
||||
/* An empty plain-text password must match an empty encrypted password. */
|
||||
@@ -74,7 +74,7 @@ sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_c
|
||||
*/
|
||||
pw_len = strlen(pw_epasswd);
|
||||
if (pw_len == DESLEN || HAS_AGEINFO(pw_epasswd, pw_len)) {
|
||||
- strlcpy(des_pass, pass, sizeof(des_pass));
|
||||
+ (void)strlcpy(des_pass, pass, sizeof(des_pass));
|
||||
pass = des_pass;
|
||||
}
|
||||
|
||||
@@ -84,29 +84,36 @@ sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_c
|
||||
* only compare the first DESLEN characters in that case.
|
||||
*/
|
||||
epass = (char *) crypt(pass, pw_epasswd);
|
||||
+ ret = AUTH_FAILURE;
|
||||
if (epass != NULL) {
|
||||
- if (HAS_AGEINFO(pw_epasswd, pw_len) && strlen(epass) == DESLEN)
|
||||
- matched = !strncmp(pw_epasswd, epass, DESLEN);
|
||||
- else
|
||||
- matched = !strcmp(pw_epasswd, epass);
|
||||
+ if (HAS_AGEINFO(pw_epasswd, pw_len) && strlen(epass) == DESLEN) {
|
||||
+ if (strncmp(pw_epasswd, epass, DESLEN) == 0)
|
||||
+ ret = AUTH_SUCCESS;
|
||||
+ } else {
|
||||
+ if (strcmp(pw_epasswd, epass) == 0)
|
||||
+ ret = AUTH_SUCCESS;
|
||||
+ }
|
||||
}
|
||||
|
||||
explicit_bzero(des_pass, sizeof(des_pass));
|
||||
|
||||
- debug_return_int(matched ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||
+ debug_return_int(ret);
|
||||
}
|
||||
#else
|
||||
int
|
||||
sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
|
||||
{
|
||||
char *pw_passwd = auth->data;
|
||||
- int matched;
|
||||
+ int ret;
|
||||
debug_decl(sudo_passwd_verify, SUDOERS_DEBUG_AUTH);
|
||||
|
||||
/* Simple string compare for systems without crypt(). */
|
||||
- matched = !strcmp(pass, pw_passwd);
|
||||
+ if (strcmp(pass, pw_passwd) == 0)
|
||||
+ ret = AUTH_SUCCESS;
|
||||
+ else
|
||||
+ ret = AUTH_FAILURE;
|
||||
|
||||
- debug_return_int(matched ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||
+ debug_return_int(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c
|
||||
index 188b65f..467233a 100644
|
||||
--- a/plugins/sudoers/auth/sudo_auth.c
|
||||
+++ b/plugins/sudoers/auth/sudo_auth.c
|
||||
@@ -112,10 +112,16 @@ sudo_auth_init(struct passwd *pw)
|
||||
if (auth->init && !IS_DISABLED(auth)) {
|
||||
/* Disable if it failed to init unless there was a fatal error. */
|
||||
status = (auth->init)(pw, auth);
|
||||
- if (status == AUTH_FAILURE)
|
||||
+ switch (status) {
|
||||
+ case AUTH_SUCCESS:
|
||||
+ break;
|
||||
+ case AUTH_FAILURE:
|
||||
SET(auth->flags, FLAG_DISABLED);
|
||||
- else if (status == AUTH_FATAL)
|
||||
- break; /* assume error msg already printed */
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* Assume error msg already printed. */
|
||||
+ debug_return_int(-1);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +167,7 @@ sudo_auth_init(struct passwd *pw)
|
||||
}
|
||||
}
|
||||
|
||||
- debug_return_int(status == AUTH_FATAL ? -1 : 0);
|
||||
+ debug_return_int(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -202,7 +208,7 @@ sudo_auth_cleanup(struct passwd *pw, bool force)
|
||||
for (auth = auth_switch; auth->name; auth++) {
|
||||
if (auth->cleanup && !IS_DISABLED(auth)) {
|
||||
int status = (auth->cleanup)(pw, auth, force);
|
||||
- if (status == AUTH_FATAL) {
|
||||
+ if (status != AUTH_SUCCESS) {
|
||||
/* Assume error msg already printed. */
|
||||
debug_return_int(-1);
|
||||
}
|
||||
@@ -297,7 +303,7 @@ verify_user(struct passwd *pw, char *prompt, int validated,
|
||||
status = (auth->setup)(pw, &prompt, auth);
|
||||
if (status == AUTH_FAILURE)
|
||||
SET(auth->flags, FLAG_DISABLED);
|
||||
- else if (status == AUTH_FATAL || user_interrupted())
|
||||
+ else if (status != AUTH_SUCCESS || user_interrupted())
|
||||
goto done; /* assume error msg already printed */
|
||||
}
|
||||
}
|
||||
@@ -348,7 +354,6 @@ done:
|
||||
log_auth_failure(validated, ntries);
|
||||
ret = false;
|
||||
break;
|
||||
- case AUTH_FATAL:
|
||||
default:
|
||||
log_auth_failure(validated, 0);
|
||||
ret = -1;
|
||||
@@ -360,24 +365,32 @@ done:
|
||||
|
||||
/*
|
||||
* Call authentication method begin session hooks.
|
||||
- * Returns 1 on success and -1 on error.
|
||||
+ * Returns true on success, false on failure and -1 on error.
|
||||
*/
|
||||
int
|
||||
sudo_auth_begin_session(struct passwd *pw, char **user_env[])
|
||||
{
|
||||
sudo_auth *auth;
|
||||
+ int ret = true;
|
||||
debug_decl(sudo_auth_begin_session, SUDOERS_DEBUG_AUTH);
|
||||
|
||||
for (auth = auth_switch; auth->name; auth++) {
|
||||
if (auth->begin_session && !IS_DISABLED(auth)) {
|
||||
int status = (auth->begin_session)(pw, user_env, auth);
|
||||
- if (status != AUTH_SUCCESS) {
|
||||
+ switch (status) {
|
||||
+ case AUTH_SUCCESS:
|
||||
+ break;
|
||||
+ case AUTH_FAILURE:
|
||||
+ ret = false;
|
||||
+ break;
|
||||
+ default:
|
||||
/* Assume error msg already printed. */
|
||||
- debug_return_int(-1);
|
||||
+ ret = -1;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
}
|
||||
- debug_return_int(1);
|
||||
+ debug_return_int(ret);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -398,25 +411,33 @@ sudo_auth_needs_end_session(void)
|
||||
|
||||
/*
|
||||
* Call authentication method end session hooks.
|
||||
- * Returns 1 on success and -1 on error.
|
||||
+ * Returns true on success, false on failure and -1 on error.
|
||||
*/
|
||||
int
|
||||
sudo_auth_end_session(struct passwd *pw)
|
||||
{
|
||||
sudo_auth *auth;
|
||||
+ int ret = true;
|
||||
int status;
|
||||
debug_decl(sudo_auth_end_session, SUDOERS_DEBUG_AUTH);
|
||||
|
||||
for (auth = auth_switch; auth->name; auth++) {
|
||||
if (auth->end_session && !IS_DISABLED(auth)) {
|
||||
status = (auth->end_session)(pw, auth);
|
||||
- if (status == AUTH_FATAL) {
|
||||
+ switch (status) {
|
||||
+ case AUTH_SUCCESS:
|
||||
+ break;
|
||||
+ case AUTH_FAILURE:
|
||||
+ ret = false;
|
||||
+ break;
|
||||
+ default:
|
||||
/* Assume error msg already printed. */
|
||||
- debug_return_int(-1);
|
||||
+ ret = -1;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
}
|
||||
- debug_return_int(1);
|
||||
+ debug_return_int(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/plugins/sudoers/auth/sudo_auth.h b/plugins/sudoers/auth/sudo_auth.h
|
||||
index 9ee408d..0b30d0c 100644
|
||||
--- a/plugins/sudoers/auth/sudo_auth.h
|
||||
+++ b/plugins/sudoers/auth/sudo_auth.h
|
||||
@@ -19,11 +19,11 @@
|
||||
#ifndef SUDO_AUTH_H
|
||||
#define SUDO_AUTH_H
|
||||
|
||||
-/* Auth function return values. */
|
||||
-#define AUTH_SUCCESS 0
|
||||
-#define AUTH_FAILURE 1
|
||||
-#define AUTH_INTR 2
|
||||
-#define AUTH_FATAL 3
|
||||
+/* Auth function return values (rowhammer resistent). */
|
||||
+#define AUTH_SUCCESS 0x52a2925 /* 0101001010100010100100100101 */
|
||||
+#define AUTH_FAILURE 0xad5d6da /* 1010110101011101011011011010 */
|
||||
+#define AUTH_INTR 0x69d61fc8 /* 1101001110101100001111111001000 */
|
||||
+#define AUTH_FATAL 0x1629e037 /* 0010110001010011110000000110111 */
|
||||
|
||||
typedef struct sudo_auth {
|
||||
int flags; /* various flags, see below */
|
||||
diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c
|
||||
index 9324159..0891d63 100644
|
||||
--- a/plugins/sudoers/match.c
|
||||
+++ b/plugins/sudoers/match.c
|
||||
@@ -92,7 +92,7 @@ user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
|
||||
if ((a = alias_get(parse_tree, m->name, USERALIAS)) != NULL) {
|
||||
/* XXX */
|
||||
const int rc = userlist_matches(parse_tree, pw, &a->members);
|
||||
- if (rc != UNSPEC) {
|
||||
+ if (SPECIFIED(rc)) {
|
||||
if (m->negated) {
|
||||
matched = rc == ALLOW ? DENY : ALLOW;
|
||||
} else {
|
||||
@@ -124,7 +124,8 @@ userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
|
||||
debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH);
|
||||
|
||||
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
||||
- if ((matched = user_matches(parse_tree, pw, m)) != UNSPEC)
|
||||
+ matched = user_matches(parse_tree, pw, m);
|
||||
+ if (SPECIFIED(matched))
|
||||
break;
|
||||
}
|
||||
debug_return_int(matched);
|
||||
@@ -194,7 +195,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
||||
if (a != NULL) {
|
||||
rc = runaslist_matches(parse_tree, &a->members,
|
||||
&empty, matching_user, NULL);
|
||||
- if (rc != UNSPEC) {
|
||||
+ if (SPECIFIED(rc)) {
|
||||
if (m->negated) {
|
||||
user_matched = rc == ALLOW ? DENY : ALLOW;
|
||||
} else {
|
||||
@@ -215,7 +216,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
||||
user_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
}
|
||||
- if (user_matched != UNSPEC) {
|
||||
+ if (SPECIFIED(user_matched)) {
|
||||
if (matching_user != NULL && m->type != ALIAS)
|
||||
*matching_user = m;
|
||||
break;
|
||||
@@ -228,7 +229,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
||||
* Skip checking runas group if none was specified.
|
||||
*/
|
||||
if (ISSET(sudo_user.flags, RUNAS_GROUP_SPECIFIED)) {
|
||||
- if (user_matched == UNSPEC) {
|
||||
+ if (!SPECIFIED(user_matched)) {
|
||||
if (strcmp(user_name, runas_pw->pw_name) == 0)
|
||||
user_matched = ALLOW; /* only changing group */
|
||||
}
|
||||
@@ -243,7 +244,7 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
||||
if (a != NULL) {
|
||||
rc = runaslist_matches(parse_tree, &empty,
|
||||
&a->members, NULL, matching_group);
|
||||
- if (rc != UNSPEC) {
|
||||
+ if (SPECIFIED(rc)) {
|
||||
if (m->negated) {
|
||||
group_matched = rc == ALLOW ? DENY : ALLOW;
|
||||
} else {
|
||||
@@ -259,14 +260,14 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
||||
group_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
}
|
||||
- if (group_matched != UNSPEC) {
|
||||
+ if (SPECIFIED(group_matched)) {
|
||||
if (matching_group != NULL && m->type != ALIAS)
|
||||
*matching_group = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
- if (group_matched == UNSPEC) {
|
||||
+ if (!SPECIFIED(group_matched)) {
|
||||
struct gid_list *runas_groups;
|
||||
/*
|
||||
* The runas group was not explicitly allowed by sudoers.
|
||||
@@ -310,7 +311,7 @@ hostlist_matches_int(struct sudoers_parse_tree *parse_tree,
|
||||
|
||||
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
||||
matched = host_matches(parse_tree, pw, lhost, shost, m);
|
||||
- if (matched != UNSPEC)
|
||||
+ if (SPECIFIED(matched))
|
||||
break;
|
||||
}
|
||||
debug_return_int(matched);
|
||||
@@ -361,7 +362,7 @@ host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
|
||||
/* XXX */
|
||||
const int rc = hostlist_matches_int(parse_tree, pw, lhost,
|
||||
shost, &a->members);
|
||||
- if (rc != UNSPEC) {
|
||||
+ if (SPECIFIED(rc)) {
|
||||
if (m->negated) {
|
||||
matched = rc == ALLOW ? DENY : ALLOW;
|
||||
} else {
|
||||
@@ -395,7 +396,7 @@ cmndlist_matches(struct sudoers_parse_tree *parse_tree,
|
||||
|
||||
TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
|
||||
matched = cmnd_matches(parse_tree, m, runchroot, info);
|
||||
- if (matched != UNSPEC)
|
||||
+ if (SPECIFIED(matched))
|
||||
break;
|
||||
}
|
||||
debug_return_int(matched);
|
||||
@@ -425,7 +426,7 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m,
|
||||
a = alias_get(parse_tree, m->name, CMNDALIAS);
|
||||
if (a != NULL) {
|
||||
rc = cmndlist_matches(parse_tree, &a->members, runchroot, info);
|
||||
- if (rc != UNSPEC) {
|
||||
+ if (SPECIFIED(rc)) {
|
||||
if (m->negated) {
|
||||
matched = rc == ALLOW ? DENY : ALLOW;
|
||||
} else {
|
||||
diff --git a/plugins/sudoers/parse.c b/plugins/sudoers/parse.c
|
||||
index d3bf8a5..e38e7e9 100644
|
||||
--- a/plugins/sudoers/parse.c
|
||||
+++ b/plugins/sudoers/parse.c
|
||||
@@ -153,7 +153,7 @@ sudoers_lookup_check(struct sudo_nss *nss, struct passwd *pw,
|
||||
if (runas_match == ALLOW) {
|
||||
cmnd_match = cmnd_matches(nss->parse_tree, cs->cmnd,
|
||||
cs->runchroot, info);
|
||||
- if (cmnd_match != UNSPEC) {
|
||||
+ if (SPECIFIED(cmnd_match)) {
|
||||
/*
|
||||
* If user is running command as himself,
|
||||
* set runas_pw = sudo_user.pw.
|
||||
@@ -396,7 +396,7 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int *cmnd_status,
|
||||
}
|
||||
|
||||
m = sudoers_lookup_check(nss, pw, &validated, &info, &cs, &defs, now);
|
||||
- if (m != UNSPEC) {
|
||||
+ if (SPECIFIED(m)) {
|
||||
match = m;
|
||||
parse_tree = nss->parse_tree;
|
||||
}
|
||||
@@ -404,7 +404,7 @@ sudoers_lookup(struct sudo_nss_list *snl, struct passwd *pw, int *cmnd_status,
|
||||
if (!sudo_nss_can_continue(nss, m))
|
||||
break;
|
||||
}
|
||||
- if (match != UNSPEC) {
|
||||
+ if (SPECIFIED(match)) {
|
||||
if (info.cmnd_path != NULL) {
|
||||
/* Update user_cmnd, user_stat, cmnd_status from matching entry. */
|
||||
free(user_cmnd);
|
||||
diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h
|
||||
index ea2a179..8559849 100644
|
||||
--- a/plugins/sudoers/parse.h
|
||||
+++ b/plugins/sudoers/parse.h
|
||||
@@ -34,15 +34,28 @@
|
||||
# define SUDOERS_NAME_MATCH
|
||||
#endif
|
||||
|
||||
+/* Allowed by policy (rowhammer resistent). */
|
||||
+#undef ALLOW
|
||||
+#define ALLOW 0x52a2925 /* 0101001010100010100100100101 */
|
||||
+
|
||||
+/* Denied by policy (rowhammer resistent). */
|
||||
+#undef DENY
|
||||
+#define DENY 0xad5d6da /* 1010110101011101011011011010 */
|
||||
+
|
||||
+/* Neither allowed, nor denied. */
|
||||
#undef UNSPEC
|
||||
#define UNSPEC -1
|
||||
-#undef DENY
|
||||
-#define DENY 0
|
||||
-#undef ALLOW
|
||||
-#define ALLOW 1
|
||||
+
|
||||
+/* Tag implied by root access (SETENV only). */
|
||||
#undef IMPLIED
|
||||
#define IMPLIED 2
|
||||
|
||||
+/*
|
||||
+ * We must explicitly check against ALLOW and DENY instead testing
|
||||
+ * that the value is not UNSPEC to avoid potential ROWHAMMER issues.
|
||||
+ */
|
||||
+#define SPECIFIED(_v) ((_v) == ALLOW || (_v) == DENY)
|
||||
+
|
||||
/*
|
||||
* Initialize all tags to UNSPEC.
|
||||
*/
|
||||
@@ -92,7 +105,7 @@
|
||||
* Returns true if the specified tag is not UNSPEC or IMPLIED, else false.
|
||||
*/
|
||||
#define TAG_SET(tt) \
|
||||
- ((tt) != UNSPEC && (tt) != IMPLIED)
|
||||
+ ((tt) == true || (tt) == false)
|
||||
|
||||
/*
|
||||
* Returns true if any tags set in nt differ between ot and nt, else false.
|
||||
--
|
||||
2.42.0.windows.2
|
||||
|
||||
@ -0,0 +1,249 @@
|
||||
From cf00568d888c90a8c5d06a06283bc87a45992933 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Sat, 26 Aug 2023 10:32:37 -0600
|
||||
Subject: [PATCH] Do not rely on the definition of ALLOW/DENY being true/false.
|
||||
|
||||
We now explicitly check for ALLOW and DENY when checking return
|
||||
values and negating values.
|
||||
|
||||
Reference: https://github.com/sudo-project/sudo/commit/cf00568d888c90a8c5d06a06283bc87a45992933
|
||||
Conflict: cvtsudoers.c match.c
|
||||
---
|
||||
plugins/sudoers/cvtsudoers.c | 6 +--
|
||||
plugins/sudoers/match.c | 83 +++++++++++++++++++++++-------------
|
||||
2 files changed, 57 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/plugins/sudoers/cvtsudoers.c b/plugins/sudoers/cvtsudoers.c
|
||||
index 79558c3..8cedcc6 100644
|
||||
--- a/plugins/sudoers/cvtsudoers.c
|
||||
+++ b/plugins/sudoers/cvtsudoers.c
|
||||
@@ -690,7 +690,7 @@ userlist_matches_filter(struct sudoers_parse_tree *parse_tree,
|
||||
pw.pw_uid = (uid_t)-1;
|
||||
pw.pw_gid = (gid_t)-1;
|
||||
|
||||
- if (user_matches(parse_tree, &pw, m) == true)
|
||||
+ if (user_matches(parse_tree, &pw, m) == ALLOW)
|
||||
matched = true;
|
||||
} else {
|
||||
STAILQ_FOREACH(s, &filters->users, entries) {
|
||||
@@ -716,7 +716,7 @@ userlist_matches_filter(struct sudoers_parse_tree *parse_tree,
|
||||
if (pw == NULL)
|
||||
continue;
|
||||
|
||||
- if (user_matches(parse_tree, pw, m) == true)
|
||||
+ if (user_matches(parse_tree, pw, m) == ALLOW)
|
||||
matched = true;
|
||||
sudo_pw_delref(pw);
|
||||
|
||||
@@ -792,7 +792,7 @@ hostlist_matches_filter(struct sudoers_parse_tree *parse_tree,
|
||||
|
||||
/* Only need one host in the filter to match. */
|
||||
/* XXX - can't use netgroup_tuple with NULL pw */
|
||||
- if (host_matches(parse_tree, NULL, lhost, shost, m) == true) {
|
||||
+ if (host_matches(parse_tree, NULL, lhost, shost, m) == ALLOW) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c
|
||||
index 9801f38..9324159 100644
|
||||
--- a/plugins/sudoers/match.c
|
||||
+++ b/plugins/sudoers/match.c
|
||||
@@ -76,31 +76,36 @@ user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
|
||||
|
||||
switch (m->type) {
|
||||
case ALL:
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case NETGROUP:
|
||||
if (netgr_matches(m->name,
|
||||
def_netgroup_tuple ? lhost : NULL,
|
||||
def_netgroup_tuple ? shost : NULL, pw->pw_name))
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case USERGROUP:
|
||||
if (usergr_matches(m->name, pw->pw_name, pw))
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case ALIAS:
|
||||
if ((a = alias_get(parse_tree, m->name, USERALIAS)) != NULL) {
|
||||
/* XXX */
|
||||
- int rc = userlist_matches(parse_tree, pw, &a->members);
|
||||
- if (rc != UNSPEC)
|
||||
- matched = m->negated ? !rc : rc;
|
||||
+ const int rc = userlist_matches(parse_tree, pw, &a->members);
|
||||
+ if (rc != UNSPEC) {
|
||||
+ if (m->negated) {
|
||||
+ matched = rc == ALLOW ? DENY : ALLOW;
|
||||
+ } else {
|
||||
+ matched = rc;
|
||||
+ }
|
||||
+ }
|
||||
alias_put(a);
|
||||
break;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case WORD:
|
||||
if (userpw_matches(m->name, pw->pw_name, pw))
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
}
|
||||
debug_return_int(matched);
|
||||
@@ -171,38 +176,43 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
||||
TAILQ_FOREACH_REVERSE(m, user_list, member_list, entries) {
|
||||
switch (m->type) {
|
||||
case ALL:
|
||||
- user_matched = !m->negated;
|
||||
+ user_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case NETGROUP:
|
||||
if (netgr_matches(m->name,
|
||||
def_netgroup_tuple ? lhost : NULL,
|
||||
def_netgroup_tuple ? shost : NULL,
|
||||
runas_pw->pw_name))
|
||||
- user_matched = !m->negated;
|
||||
+ user_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case USERGROUP:
|
||||
if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
|
||||
- user_matched = !m->negated;
|
||||
+ user_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case ALIAS:
|
||||
a = alias_get(parse_tree, m->name, RUNASALIAS);
|
||||
if (a != NULL) {
|
||||
rc = runaslist_matches(parse_tree, &a->members,
|
||||
&empty, matching_user, NULL);
|
||||
- if (rc != UNSPEC)
|
||||
- user_matched = m->negated ? !rc : rc;
|
||||
+ if (rc != UNSPEC) {
|
||||
+ if (m->negated) {
|
||||
+ user_matched = rc == ALLOW ? DENY : ALLOW;
|
||||
+ } else {
|
||||
+ user_matched = rc;
|
||||
+ }
|
||||
+ }
|
||||
alias_put(a);
|
||||
break;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case WORD:
|
||||
if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
|
||||
- user_matched = !m->negated;
|
||||
+ user_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case MYSELF:
|
||||
if (!ISSET(sudo_user.flags, RUNAS_USER_SPECIFIED) ||
|
||||
strcmp(user_name, runas_pw->pw_name) == 0)
|
||||
- user_matched = !m->negated;
|
||||
+ user_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
}
|
||||
if (user_matched != UNSPEC) {
|
||||
@@ -226,22 +236,27 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
|
||||
TAILQ_FOREACH_REVERSE(m, group_list, member_list, entries) {
|
||||
switch (m->type) {
|
||||
case ALL:
|
||||
- group_matched = !m->negated;
|
||||
+ group_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case ALIAS:
|
||||
a = alias_get(parse_tree, m->name, RUNASALIAS);
|
||||
if (a != NULL) {
|
||||
rc = runaslist_matches(parse_tree, &empty,
|
||||
&a->members, NULL, matching_group);
|
||||
- if (rc != UNSPEC)
|
||||
- group_matched = m->negated ? !rc : rc;
|
||||
+ if (rc != UNSPEC) {
|
||||
+ if (m->negated) {
|
||||
+ group_matched = rc == ALLOW ? DENY : ALLOW;
|
||||
+ } else {
|
||||
+ group_matched = rc;
|
||||
+ }
|
||||
+ }
|
||||
alias_put(a);
|
||||
break;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case WORD:
|
||||
if (group_matches(m->name, runas_gr))
|
||||
- group_matched = !m->negated;
|
||||
+ group_matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
}
|
||||
if (group_matched != UNSPEC) {
|
||||
@@ -329,32 +344,37 @@ host_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
|
||||
|
||||
switch (m->type) {
|
||||
case ALL:
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case NETGROUP:
|
||||
if (netgr_matches(m->name, lhost, shost,
|
||||
def_netgroup_tuple ? pw->pw_name : NULL))
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case NTWKADDR:
|
||||
if (addr_matches(m->name))
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case ALIAS:
|
||||
a = alias_get(parse_tree, m->name, HOSTALIAS);
|
||||
if (a != NULL) {
|
||||
/* XXX */
|
||||
- int rc = hostlist_matches_int(parse_tree, pw, lhost, shost,
|
||||
- &a->members);
|
||||
- if (rc != UNSPEC)
|
||||
- matched = m->negated ? !rc : rc;
|
||||
+ const int rc = hostlist_matches_int(parse_tree, pw, lhost,
|
||||
+ shost, &a->members);
|
||||
+ if (rc != UNSPEC) {
|
||||
+ if (m->negated) {
|
||||
+ matched = rc == ALLOW ? DENY : ALLOW;
|
||||
+ } else {
|
||||
+ matched = rc;
|
||||
+ }
|
||||
+ }
|
||||
alias_put(a);
|
||||
break;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case WORD:
|
||||
if (hostname_matches(shost, lhost, m->name))
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
}
|
||||
debug_return_int(matched);
|
||||
@@ -399,14 +419,19 @@ cmnd_matches(struct sudoers_parse_tree *parse_tree, const struct member *m,
|
||||
case COMMAND:
|
||||
c = (struct sudo_command *)m->name;
|
||||
if (command_matches(c->cmnd, c->args, runchroot, info, &c->digests))
|
||||
- matched = !m->negated;
|
||||
+ matched = m->negated ? DENY : ALLOW;
|
||||
break;
|
||||
case ALIAS:
|
||||
a = alias_get(parse_tree, m->name, CMNDALIAS);
|
||||
if (a != NULL) {
|
||||
rc = cmndlist_matches(parse_tree, &a->members, runchroot, info);
|
||||
- if (rc != UNSPEC)
|
||||
- matched = m->negated ? !rc : rc;
|
||||
+ if (rc != UNSPEC) {
|
||||
+ if (m->negated) {
|
||||
+ matched = rc == ALLOW ? DENY : ALLOW;
|
||||
+ } else {
|
||||
+ matched = rc;
|
||||
+ }
|
||||
+ }
|
||||
alias_put(a);
|
||||
}
|
||||
break;
|
||||
--
|
||||
2.42.0.windows.2
|
||||
|
||||
1117
backport-Make-all-match-functions-return-ALLOW-DENY-.patch
Normal file
1117
backport-Make-all-match-functions-return-ALLOW-DENY-.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
Name: sudo
|
||||
Version: 1.9.8p2
|
||||
Release: 15
|
||||
Release: 16
|
||||
Summary: Allows restricted root access for specified users
|
||||
License: ISC
|
||||
URL: http://www.courtesan.com/sudo/
|
||||
@ -39,6 +39,10 @@ Patch25: backport-Linux-execve-2-allows-argv-or-envp-to-be-NULL.patch
|
||||
Patch26: backport-Fix-potential-NULL-pointer-deference-found-by-clang-.patch
|
||||
Patch27: backport-Set-command_info-to-NULL-once-it-is-freed.patch
|
||||
Patch28: backport-sudoers_parse_ldif-do-not-free-parse_tree-before-usi.patch
|
||||
Patch29: backport-Do-not-rely-on-the-definition-of-ALLOW-DENY-being-tr.patch
|
||||
Patch30: backport-CVE-2023-42465.patch
|
||||
Patch31: backport-Make-all-match-functions-return-ALLOW-DENY-.patch
|
||||
|
||||
|
||||
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
Requires: pam
|
||||
@ -189,6 +193,9 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/etc/pam.d/sudo-i
|
||||
%exclude %{_pkgdocdir}/ChangeLog
|
||||
|
||||
%changelog
|
||||
* Wed Jan 10 2024 zhangruifang <wangqingsan@huawei.com> - 1.9.8p2-16
|
||||
- fix CVE-2023-42465
|
||||
|
||||
* Tue Nov 28 2023 zhangruifang <zhangruifang1@h-partners.com> - 1.9.8p2-15
|
||||
- Backport patches from upstream community
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user