Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
ea54c4e87a
!131 Backport patch from upstream community
From: @fly_fzc 
Reviewed-by: @HuaxinLuGitee, @houmingyong 
Signed-off-by: @HuaxinLuGitee
2024-01-31 08:29:01 +00:00
fly_fzc
2158f6ac41 Backport patch from upstream community 2024-01-31 15:11:19 +08:00
openeuler-ci-bot
7a9fce11f6
!130 fix CVE-2023-42465
From: @qsw333 
Reviewed-by: @houmingyong, @licihua 
Signed-off-by: @licihua
2024-01-10 03:03:31 +00:00
qsw333
24edd57599 fix CVE-2023-42465 2024-01-10 10:21:39 +08:00
openeuler-ci-bot
40203fb30b
!115 Backport patches from upstream community
From: @zhangruifang2020 
Reviewed-by: @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
2023-11-29 01:55:25 +00:00
zhangruifang2020
9074a28784 Backport patches from upstream community 2023-11-28 14:18:43 +08:00
openeuler-ci-bot
05637957da
!110 [sync] PR-107: Backport patche from upstream community
From: @openeuler-sync-bot 
Reviewed-by: @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
2023-11-27 01:58:57 +00:00
Zhou Shuiqing
8cfdf2150c Backport patche from upstream community
(cherry picked from commit db3a30170d1db1a2184af79fbf3f2f31bb487761)
2023-11-27 09:47:42 +08:00
openeuler-ci-bot
2f4d35adb1
!105 [sync] PR-102: Backport patches form upstream community
From: @openeuler-sync-bot 
Reviewed-by: @HuaxinLuGitee 
Signed-off-by: @HuaxinLuGitee
2023-06-13 07:07:31 +00:00
zhoushuiqing
5ee298be21 Backport patches form upstream community
(cherry picked from commit 23b42da498fb65fe2292ea1858ee0fe64ff57e03)
2023-06-13 14:28:09 +08:00
12 changed files with 2288 additions and 1 deletions

View 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

View File

@ -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

View File

@ -0,0 +1,43 @@
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

View File

@ -0,0 +1,164 @@
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

View File

@ -0,0 +1,61 @@
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

View File

@ -0,0 +1,25 @@
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

View File

@ -0,0 +1,29 @@
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

View File

@ -0,0 +1,43 @@
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

View File

@ -0,0 +1,59 @@
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

View File

@ -0,0 +1,28 @@
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

View File

@ -1,6 +1,6 @@
Name: sudo
Version: 1.9.8p2
Release: 12
Release: 17
Summary: Allows restricted root access for specified users
License: ISC
URL: http://www.courtesan.com/sudo/
@ -32,6 +32,18 @@ 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
@ -182,6 +194,21 @@ 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.