Compare commits
No commits in common. "ea54c4e87a7f93678d917aacb4f5555d6433ae5a" and "793debb6d66ecea5cd5d3cabfcb317772ad90284" have entirely different histories.
ea54c4e87a
...
793debb6d6
@ -1,442 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,249 +0,0 @@
|
||||
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
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
From 3421c8b6cedc582ed5eab573f59d4feddc7e1ab3 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Tue, 26 Jul 2022 11:44:12 -0600
|
||||
Subject: [PATCH] Fix potential NULL pointer deference found by clang-analyzer.
|
||||
|
||||
---
|
||||
lib/util/sudo_debug.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/util/sudo_debug.c b/lib/util/sudo_debug.c
|
||||
index a2ead5228..c06ba8cde 100644
|
||||
--- a/lib/util/sudo_debug.c
|
||||
+++ b/lib/util/sudo_debug.c
|
||||
@@ -861,7 +861,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con
|
||||
continue;
|
||||
|
||||
/* Log envp for debug level "debug". */
|
||||
- if (output->settings[subsys] >= SUDO_DEBUG_DEBUG - 1 && envp[0] != NULL)
|
||||
+ if (output->settings[subsys] >= SUDO_DEBUG_DEBUG - 1 && envp != NULL)
|
||||
log_envp = true;
|
||||
|
||||
/* Alloc and build up buffer. */
|
||||
@@ -873,7 +873,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con
|
||||
buflen += strlen(*av) + 1;
|
||||
buflen--;
|
||||
}
|
||||
- if (envp != NULL && log_envp) {
|
||||
+ if (log_envp && envp[0] != NULL) {
|
||||
buflen += sizeof(" []") - 1;
|
||||
for (av = envp; *av; av++)
|
||||
buflen += strlen(*av) + 1;
|
||||
@@ -904,7 +904,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con
|
||||
cp[-1] = ']';
|
||||
}
|
||||
|
||||
- if (envp != NULL && log_envp) {
|
||||
+ if (log_envp && envp[0] != NULL) {
|
||||
*cp++ = ' ';
|
||||
*cp++ = '[';
|
||||
for (av = envp; *av; av++) {
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -1,164 +0,0 @@
|
||||
From e5652fc65a54ab2d3f161c264254579f00699b00 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Thu, 14 Jul 2022 09:29:40 -0600
|
||||
Subject: [PATCH] Linux execve(2) allows argv or envp to be NULL. Add checks to
|
||||
make sure we don't deference a NULL pointer.
|
||||
|
||||
---
|
||||
lib/util/sudo_debug.c | 10 +++++-----
|
||||
src/exec_intercept.c | 2 +-
|
||||
src/exec_preload.c | 5 +++++
|
||||
src/exec_ptrace.c | 36 +++++++++++++++++++++++++++++-------
|
||||
src/sudo_intercept.c | 10 ++++++++++
|
||||
src/sudo_intercept_common.c | 25 ++++++++++++++-----------
|
||||
6 files changed, 64 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/lib/util/sudo_debug.c b/lib/util/sudo_debug.c
|
||||
index d78536a0c..a2ead5228 100644
|
||||
--- a/lib/util/sudo_debug.c
|
||||
+++ b/lib/util/sudo_debug.c
|
||||
@@ -831,7 +831,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con
|
||||
size_t plen;
|
||||
debug_decl_func(sudo_debug_execve2);
|
||||
|
||||
- if (sudo_debug_active_instance == -1)
|
||||
+ if (sudo_debug_active_instance == -1 || path == NULL)
|
||||
goto out;
|
||||
|
||||
/* Extract priority and subsystem from level. */
|
||||
@@ -867,13 +867,13 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con
|
||||
/* Alloc and build up buffer. */
|
||||
plen = strlen(path);
|
||||
buflen = sizeof(EXEC_PREFIX) -1 + plen;
|
||||
- if (argv[0] != NULL) {
|
||||
+ if (argv != NULL && argv[0] != NULL) {
|
||||
buflen += sizeof(" []") - 1;
|
||||
for (av = argv; *av; av++)
|
||||
buflen += strlen(*av) + 1;
|
||||
buflen--;
|
||||
}
|
||||
- if (log_envp) {
|
||||
+ if (envp != NULL && log_envp) {
|
||||
buflen += sizeof(" []") - 1;
|
||||
for (av = envp; *av; av++)
|
||||
buflen += strlen(*av) + 1;
|
||||
@@ -892,7 +892,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con
|
||||
cp += plen;
|
||||
|
||||
/* Copy argv. */
|
||||
- if (argv[0] != NULL) {
|
||||
+ if (argv != NULL && argv[0] != NULL) {
|
||||
*cp++ = ' ';
|
||||
*cp++ = '[';
|
||||
for (av = argv; *av; av++) {
|
||||
@@ -904,7 +904,7 @@ sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *con
|
||||
cp[-1] = ']';
|
||||
}
|
||||
|
||||
- if (log_envp) {
|
||||
+ if (envp != NULL && log_envp) {
|
||||
*cp++ = ' ';
|
||||
*cp++ = '[';
|
||||
for (av = envp; *av; av++) {
|
||||
diff --git a/src/exec_preload.c b/src/exec_preload.c
|
||||
index 4f04a0113..81e865333 100644
|
||||
--- a/src/exec_preload.c
|
||||
+++ b/src/exec_preload.c
|
||||
@@ -44,6 +44,7 @@ sudo_preload_dso(char *const envp[], const char *dso_file, int intercept_fd)
|
||||
int env_len, len;
|
||||
int preload_idx = -1;
|
||||
int intercept_idx = -1;
|
||||
+ char *const empty[1] = { NULL };
|
||||
bool fd_present = false;
|
||||
bool dso_present = false;
|
||||
# ifdef RTLD_PRELOAD_ENABLE_VAR
|
||||
@@ -73,4 +73,8 @@ sudo_preload_dso(char *const envp[], const char *dso_file, int intercept_fd)
|
||||
* XXX - need to support 32-bit and 64-bit variants
|
||||
*/
|
||||
|
||||
+ /* Treat a NULL envp as empty, thanks Linux. */
|
||||
+ if (envp == NULL)
|
||||
+ envp = empty;
|
||||
+
|
||||
/* Count entries in envp, looking for LD_PRELOAD as we go. */
|
||||
diff --git a/src/sudo_intercept.c b/src/sudo_intercept.c
|
||||
index 97c612892..48ecc9bc9 100644
|
||||
--- a/src/sudo_intercept.c
|
||||
+++ b/src/sudo_intercept.c
|
||||
@@ -135,6 +135,11 @@ exec_wrapper(const char *cmnd, char * const argv[], char * const envp[],
|
||||
void *fn = NULL;
|
||||
debug_decl(exec_wrapper, SUDO_DEBUG_EXEC);
|
||||
|
||||
+ if (cmnd == NULL) {
|
||||
+ errno = EINVAL;
|
||||
+ debug_return_int(-1);
|
||||
+ }
|
||||
+
|
||||
/* Only check PATH for the command for execlp/execvp/execvpe. */
|
||||
if (strchr(cmnd, '/') == NULL) {
|
||||
if (!is_execvp) {
|
||||
@@ -201,6 +206,11 @@ execl_wrapper(int type, const char *name, const char *arg, va_list ap)
|
||||
va_list ap2;
|
||||
debug_decl(execl_wrapper, SUDO_DEBUG_EXEC);
|
||||
|
||||
+ if (name == NULL || arg == NULL) {
|
||||
+ errno = EINVAL;
|
||||
+ debug_return_int(-1);
|
||||
+ }
|
||||
+
|
||||
va_copy(ap2, ap);
|
||||
while (va_arg(ap2, char *) != NULL)
|
||||
argc++;
|
||||
diff --git a/src/sudo_intercept_common.c b/src/sudo_intercept_common.c
|
||||
index 102393952..a81a3c880 100644
|
||||
--- a/src/sudo_intercept_common.c
|
||||
+++ b/src/sudo_intercept_common.c
|
||||
@@ -297,6 +297,7 @@ send_policy_check_req(int sock, const char *cmnd, char * const argv[],
|
||||
InterceptRequest msg = INTERCEPT_REQUEST__INIT;
|
||||
PolicyCheckRequest req = POLICY_CHECK_REQUEST__INIT;
|
||||
char cwdbuf[PATH_MAX];
|
||||
+ char *empty[1] = { NULL };
|
||||
uint8_t *buf = NULL;
|
||||
bool ret = false;
|
||||
uint32_t msg_len;
|
||||
@@ -313,14 +314,14 @@ send_policy_check_req(int sock, const char *cmnd, char * const argv[],
|
||||
/* Setup policy check request. */
|
||||
req.intercept_fd = sock;
|
||||
req.command = (char *)cmnd;
|
||||
- req.argv = (char **)argv;
|
||||
- for (len = 0; argv[len] != NULL; len++)
|
||||
- continue;
|
||||
- req.n_argv = len;
|
||||
- req.envp = (char **)envp;
|
||||
- for (len = 0; envp[len] != NULL; len++)
|
||||
- continue;
|
||||
- req.n_envp = len;
|
||||
+ req.argv = argv ? (char **)argv : empty;
|
||||
+ req.n_argv = 0;
|
||||
+ while (req.argv[req.n_argv] != NULL)
|
||||
+ req.n_argv++;
|
||||
+ req.envp = envp ? (char **)envp : empty;
|
||||
+ req.n_envp = 0;
|
||||
+ while (req.envp[req.n_envp] != NULL)
|
||||
+ req.n_envp++;
|
||||
if (getcwd(cwdbuf, sizeof(cwdbuf)) != NULL) {
|
||||
req.cwd = cwdbuf;
|
||||
}
|
||||
@@ -409,9 +410,11 @@ command_allowed(const char *cmnd, char * const argv[],
|
||||
if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||
"req_command: %s", cmnd);
|
||||
- for (idx = 0; argv[idx] != NULL; idx++) {
|
||||
- sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||
- "req_argv[%zu]: %s", idx, argv[idx]);
|
||||
+ if (argv != NULL) {
|
||||
+ for (idx = 0; argv[idx] != NULL; idx++) {
|
||||
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||
+ "req_argv[%zu]: %s", idx, argv[idx]);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,61 +0,0 @@
|
||||
From c2a131714a6b9eccba7779bde64ce79a0377b541 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Mon, 6 Jun 2022 19:42:07 -0600
|
||||
Subject: [PATCH] Reinstall the event handler if we get EAGAIN from read/write
|
||||
callback. The read and write events do not set SUDO_EV_PERSIST so we need to
|
||||
explicitly re-enable the event if there is still data to be read. Bug #963.
|
||||
|
||||
---
|
||||
src/exec_pty.c | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/exec_pty.c b/src/exec_pty.c
|
||||
index 326d8318a..d2fc1ce5c 100644
|
||||
--- a/src/exec_pty.c
|
||||
+++ b/src/exec_pty.c
|
||||
@@ -676,8 +676,12 @@ read_callback(int fd, int what, void *v)
|
||||
/* Schedule SIGTTIN to be forwarded to the command. */
|
||||
schedule_signal(iob->ec, SIGTTIN);
|
||||
}
|
||||
- if (errno == EAGAIN || errno == EINTR)
|
||||
+ if (errno == EAGAIN || errno == EINTR) {
|
||||
+ /* Re-enable reader. */
|
||||
+ if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1)
|
||||
+ sudo_fatal("%s", U_("unable to add event to queue"));
|
||||
break;
|
||||
+ }
|
||||
/* treat read error as fatal and close the fd */
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||
"error reading fd %d: %s", fd, strerror(errno));
|
||||
@@ -717,6 +721,8 @@ read_callback(int fd, int what, void *v)
|
||||
}
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -783,7 +789,9 @@ write_callback(int fd, int what, void *v)
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case EAGAIN:
|
||||
- /* not an error */
|
||||
+ /* Not an error, re-enable writer. */
|
||||
+ if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1)
|
||||
+ sudo_fatal("%s", U_("unable to add event to queue"));
|
||||
break;
|
||||
default:
|
||||
/* XXX - need a way to distinguish non-exec error. */
|
||||
@@ -821,6 +829,8 @@ write_callback(int fd, int what, void *v)
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ debug_return;
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
From 0bb41ed82a5849b0c64d7046662825d84e983e4d Mon Sep 17 00:00:00 2001
|
||||
From: Rose <83477269+AtariDreams@users.noreply.github.com>
|
||||
Date: Mon, 26 Jun 2023 15:08:51 -0400
|
||||
Subject: [PATCH] Set command_info to NULL once it is freed
|
||||
|
||||
The lack of setting to NULL is a holdover from when command_info was a local variable and not a global one. However, we given how other global variables are set to NULL, it is best that we do the same here to avoid potential issues should sudoers_policy_store_result be called again after the first time failed, otherwise we could get a double-free.
|
||||
|
||||
---
|
||||
plugins/sudoers/policy.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c
|
||||
index 7157fab2b..f018caca2 100644
|
||||
--- a/plugins/sudoers/policy.c
|
||||
+++ b/plugins/sudoers/policy.c
|
||||
@@ -1054,6 +1054,7 @@ bad:
|
||||
while (info_len--)
|
||||
free(command_info[info_len]);
|
||||
free(command_info);
|
||||
+ command_info = NULL;
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
--
|
||||
2.23.0
|
||||
@ -1,29 +0,0 @@
|
||||
From 2ffcda8e15afe312550be4017d8c40dbb438b786 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Thu, 2 Nov 2023 14:42:42 -0600
|
||||
Subject: [PATCH] role_to_sudoers: only try to reuse a privilege if one is
|
||||
present
|
||||
|
||||
Reference:https://github.com/sudo-project/sudo/commit/2ffcda8e15afe312550be4017d8c40dbb438b786
|
||||
Conflict:NA
|
||||
|
||||
---
|
||||
plugins/sudoers/parse_ldif.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/plugins/sudoers/parse_ldif.c b/plugins/sudoers/parse_ldif.c
|
||||
index 87c94125c..180e7da6c 100644
|
||||
--- a/plugins/sudoers/parse_ldif.c
|
||||
+++ b/plugins/sudoers/parse_ldif.c
|
||||
@@ -427,7 +427,7 @@ role_to_sudoers(struct sudoers_parse_tree *parse_tree, struct sudo_role *role,
|
||||
U_("unable to allocate memory"));
|
||||
}
|
||||
|
||||
- if (reuse_privilege) {
|
||||
+ if (reuse_privilege && !TAILQ_EMPTY(&us->privileges)) {
|
||||
/* Hostspec unchanged, append cmndlist to previous privilege. */
|
||||
struct privilege *prev_priv = TAILQ_LAST(&us->privileges, privilege_list);
|
||||
if (reuse_runas) {
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
From 224d78993a24d1cc31ae0f6a0d0a59c66b765387 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Sat, 9 Jul 2022 09:00:48 -0600
|
||||
Subject: [PATCH] sudo_putenv_nodebug: require that the environment string
|
||||
include a '='
|
||||
|
||||
---
|
||||
plugins/sudoers/env.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/plugins/sudoers/env.c b/plugins/sudoers/env.c
|
||||
index 99b674300..eaf90f4a0 100644
|
||||
--- a/plugins/sudoers/env.c
|
||||
+++ b/plugins/sudoers/env.c
|
||||
@@ -314,9 +314,15 @@ int
|
||||
sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite)
|
||||
{
|
||||
char **ep;
|
||||
- size_t len;
|
||||
+ const char *equal;
|
||||
bool found = false;
|
||||
|
||||
+ equal = strchr(str, '=');
|
||||
+ if (equal == NULL) {
|
||||
+ errno = EINVAL;
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
/* Make sure there is room for the new entry plus a NULL. */
|
||||
if (env.env_size > 2 && env.env_len > env.env_size - 2) {
|
||||
char **nenvp;
|
||||
@@ -358,7 +364,7 @@ sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite)
|
||||
#endif
|
||||
|
||||
if (dupcheck) {
|
||||
- len = (strchr(str, '=') - str) + 1;
|
||||
+ size_t len = (size_t)(equal - str) + 1;
|
||||
for (ep = env.envp; *ep != NULL; ep++) {
|
||||
if (strncmp(str, *ep, len) == 0) {
|
||||
if (overwrite)
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
From 985a2261bc5ae0491dc0be0977425c4f9a782883 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Thu, 30 Jun 2022 13:35:04 -0600
|
||||
Subject: [PATCH] sudoers_main: defer setting return value until the end when
|
||||
running a command Otherwise, we could return success when there was an error
|
||||
from a system call or memory allocation failure.
|
||||
|
||||
---
|
||||
plugins/sudoers/sudoers.c | 15 ++++++---------
|
||||
1 file changed, 6 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c
|
||||
index b48de3e1f..26f19abb5 100644
|
||||
--- a/plugins/sudoers/sudoers.c
|
||||
+++ b/plugins/sudoers/sudoers.c
|
||||
@@ -699,15 +699,16 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
||||
switch (sudo_mode & MODE_MASK) {
|
||||
case MODE_CHECK:
|
||||
ret = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw);
|
||||
- break;
|
||||
+ goto done;
|
||||
case MODE_LIST:
|
||||
ret = display_privs(snl, list_pw ? list_pw : sudo_user.pw, verbose);
|
||||
- break;
|
||||
+ goto done;
|
||||
case MODE_VALIDATE:
|
||||
+ ret = true;
|
||||
+ goto done;
|
||||
case MODE_RUN:
|
||||
case MODE_EDIT:
|
||||
- /* ret may be overridden by "goto bad" later */
|
||||
- ret = true;
|
||||
+ /* ret will not be set until the very end. */
|
||||
break;
|
||||
default:
|
||||
/* Should not happen. */
|
||||
@@ -715,11 +716,6 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
||||
goto done;
|
||||
}
|
||||
|
||||
- if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) {
|
||||
- /* ret already set appropriately */
|
||||
- goto done;
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Set umask based on sudoers.
|
||||
* If user's umask is more restrictive, OR in those bits too
|
||||
@@ -825,6 +821,7 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
||||
env_swap_old();
|
||||
}
|
||||
|
||||
+ ret = true;
|
||||
goto done;
|
||||
|
||||
bad:
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
From a712af5a26d886d1db88d77575b7998a1944d3a9 Mon Sep 17 00:00:00 2001
|
||||
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
|
||||
Date: Fri, 18 Aug 2023 12:22:43 -0600
|
||||
Subject: [PATCH] sudoers_parse_ldif: do not free parse_tree before using
|
||||
|
||||
The user is expected to pass in an initialized and empty parse_tree
|
||||
so there is no need to free it first.
|
||||
---
|
||||
plugins/sudoers/parse_ldif.c | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
diff --git a/plugins/sudoers/parse_ldif.c b/plugins/sudoers/parse_ldif.c
|
||||
index a9944171b..98d84488a 100644
|
||||
--- a/plugins/sudoers/parse_ldif.c
|
||||
+++ b/plugins/sudoers/parse_ldif.c
|
||||
@@ -582,9 +582,6 @@ sudoers_parse_ldif(struct sudoers_parse_tree *parse_tree,
|
||||
int errors = 0;
|
||||
debug_decl(sudoers_parse_ldif, SUDOERS_DEBUG_UTIL);
|
||||
|
||||
- /* Free old contents of the parse tree (if any). */
|
||||
- free_parse_tree(parse_tree);
|
||||
-
|
||||
/*
|
||||
* We cache user, group and host lists to make it eay to detect when there
|
||||
* are identical lists (simple pointer compare). This makes it possible
|
||||
--
|
||||
2.33.0
|
||||
|
||||
29
sudo.spec
29
sudo.spec
@ -1,6 +1,6 @@
|
||||
Name: sudo
|
||||
Version: 1.9.8p2
|
||||
Release: 17
|
||||
Release: 12
|
||||
Summary: Allows restricted root access for specified users
|
||||
License: ISC
|
||||
URL: http://www.courtesan.com/sudo/
|
||||
@ -32,18 +32,6 @@ Patch18: backport-Fix-a-NOPASSWD-issue-with-a-non-existent-command-whe.patch
|
||||
Patch19: backport-CVE-2023-27320.patch
|
||||
Patch20: backport-CVE-2023-28486_CVE-2023-28487.patch
|
||||
Patch21: Fix-compilation-error-on-sw64-arch.patch
|
||||
Patch22: backport-Reinstall-the-event-handler-if-we-get-EAGAIN-from-re.patch
|
||||
Patch23: backport-sudoers_main-defer-setting-return-value-until-the-en.patch
|
||||
Patch24: backport-sudo_putenv_nodebug-require-that-the-environment-str.patch
|
||||
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
|
||||
Patch32: backport-role_to_sudoers-only-try-to-reuse-a-privilege-if-one.patch
|
||||
|
||||
|
||||
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
Requires: pam
|
||||
@ -194,21 +182,6 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/etc/pam.d/sudo-i
|
||||
%exclude %{_pkgdocdir}/ChangeLog
|
||||
|
||||
%changelog
|
||||
* Wed Jan 31 2024 fuanan <fuanan3@h-partners.com> - 1.9.8p2-17
|
||||
- Backport patch from upstream community
|
||||
|
||||
* Wed Jan 10 2024 wangqingsan <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
|
||||
|
||||
* Mon Aug 07 2023 zhoushuiqing <zhoushuiqing2@huawei.com> - 1.9.8p2-14
|
||||
- Backport patche from upstream community
|
||||
|
||||
* Tue Jun 13 2023 zhoushuiqing <zhoushuiqing2@huawei.com> - 1.9.8p2-13
|
||||
- Backport patches from upstream community
|
||||
|
||||
* Wed Apr 12 2023 wangyu <wangyu283@huawei.com> - 1.9.8p2-12
|
||||
- Fix compilation error on sw64 arch.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user