From 26162d887631f6524c96753e02d207a777b8edd7 Mon Sep 17 00:00:00 2001 From: dongyuzhen Date: Tue, 17 Dec 2024 14:31:54 +0800 Subject: [PATCH] fix CVE-2024-10041 --- ...-try-to-set-uid-to-0-for-unix_chkpwd.patch | 78 +++++++++++++++ backport-CVE-2024-10041.patch | 94 +++++++++++++++++++ ....so-to-run-without-being-setuid-root.patch | 58 ++++++++++++ ...und-the-problem-caused-by-libnss_sys.patch | 44 +++++++++ pam.spec | 9 +- 5 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2024-10041-pam_unix-try-to-set-uid-to-0-for-unix_chkpwd.patch create mode 100644 backport-CVE-2024-10041.patch create mode 100644 backport-Permit-unix_chkpwd-pam_unix.so-to-run-without-being-setuid-root.patch create mode 100644 backport-pam_unix-workaround-the-problem-caused-by-libnss_sys.patch diff --git a/backport-CVE-2024-10041-pam_unix-try-to-set-uid-to-0-for-unix_chkpwd.patch b/backport-CVE-2024-10041-pam_unix-try-to-set-uid-to-0-for-unix_chkpwd.patch new file mode 100644 index 0000000..0c0e544 --- /dev/null +++ b/backport-CVE-2024-10041-pam_unix-try-to-set-uid-to-0-for-unix_chkpwd.patch @@ -0,0 +1,78 @@ +From b7b96362087414e52524d3d9d9b3faa21e1db620 Mon Sep 17 00:00:00 2001 +From: Tobias Stoeckmann +Date: Wed, 24 Jan 2024 18:57:42 +0100 +Subject: [PATCH] pam_unix: try to set uid to 0 for unix_chkpwd + +The geteuid check does not cover all cases. If a program runs with +elevated capabilities like CAP_SETUID then we can still check +credentials of other users. + +Keep logging for future analysis though. + +Resolves: https://github.com/linux-pam/linux-pam/issues/747 +Fixes: b3020da7da38 ("pam_unix/passverify: always run the helper to obtain shadow password file entries") + +Signed-off-by: Tobias Stoeckmann + +Conflict:NA +Reference:https://github.com/linux-pam/linux-pam/commit/b7b96362087414e52524d3d9d9b3faa21e1db620 +--- + modules/pam_unix/pam_unix_acct.c | 17 +++++++++-------- + modules/pam_unix/support.c | 14 +++++++------- + 2 files changed, 16 insertions(+), 15 deletions(-) + +diff --git a/modules/pam_unix/pam_unix_acct.c b/modules/pam_unix/pam_unix_acct.c +index de8d65c..9df961a 100644 +--- a/modules/pam_unix/pam_unix_acct.c ++++ b/modules/pam_unix/pam_unix_acct.c +@@ -110,14 +110,15 @@ int _unix_run_verify_binary(pam_handle_t *pamh, unsigned long long ctrl, + _exit(PAM_AUTHINFO_UNAVAIL); + } + +- if (geteuid() == 0) { +- /* must set the real uid to 0 so the helper will not error +- out if pam is called from setuid binary (su, sudo...) */ +- if (setuid(0) == -1) { +- pam_syslog(pamh, LOG_ERR, "setuid failed: %m"); +- printf("-1\n"); +- fflush(stdout); +- _exit(PAM_AUTHINFO_UNAVAIL); ++ /* must set the real uid to 0 so the helper will not error ++ out if pam is called from setuid binary (su, sudo...) */ ++ if (setuid(0) == -1) { ++ uid_t euid = geteuid(); ++ pam_syslog(pamh, euid == 0 ? LOG_ERR : LOG_DEBUG, "setuid failed: %m"); ++ if (euid == 0) { ++ printf("-1\n"); ++ fflush(stdout); ++ _exit(PAM_AUTHINFO_UNAVAIL); + } + } + +diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c +index 2af3aea..f04fcdd 100644 +--- a/modules/pam_unix/support.c ++++ b/modules/pam_unix/support.c +@@ -513,13 +513,13 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd, + _exit(PAM_AUTHINFO_UNAVAIL); + } + +- if (geteuid() == 0) { +- /* must set the real uid to 0 so the helper will not error +- out if pam is called from setuid binary (su, sudo...) */ +- if (setuid(0) == -1) { +- D(("setuid failed")); +- _exit(PAM_AUTHINFO_UNAVAIL); +- } ++ /* must set the real uid to 0 so the helper will not error ++ out if pam is called from setuid binary (su, sudo...) */ ++ if (setuid(0) == -1) { ++ D(("setuid failed")); ++ if (geteuid() == 0) { ++ _exit(PAM_AUTHINFO_UNAVAIL); ++ } + } + + /* exec binary helper */ +-- +2.46.0 diff --git a/backport-CVE-2024-10041.patch b/backport-CVE-2024-10041.patch new file mode 100644 index 0000000..74d472d --- /dev/null +++ b/backport-CVE-2024-10041.patch @@ -0,0 +1,94 @@ +From b3020da7da384d769f27a8713257fbe1001878be Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Mon, 1 Jan 2024 12:00:00 +0000 +Subject: [PATCH] pam_unix/passverify: always run the helper to obtain shadow + password file entries + +Initially, when pam_unix.so verified the password, it used to try to +obtain the shadow password file entry for the given user by invoking +getspnam(3), and only when that didn't work and the effective uid +was nonzero, pam_unix.so used to invoke the helper as a fallback. + +When SELinux support was introduced by commit +67aab1ff5515054341a438cf9804e9c9b3a88033, the fallback was extended +also for the case when SELinux was enabled. + +Later, commit f220cace205332a3dc34e7b37a85e7627e097e7d extended the +fallback conditions for the case when pam_modutil_getspnam() failed +with EACCES. + +Since commit 470823c4aacef5cb3b1180be6ed70846b61a3752, the helper is +invoked as a fallback when pam_modutil_getspnam() fails for any reason. + +The ultimate solution for the case when pam_unix.so does not have +permissions to obtain the shadow password file entry is to stop trying +to use pam_modutil_getspnam() and to invoke the helper instead. +Here are two recent examples. + +https://github.com/linux-pam/linux-pam/pull/484 describes a system +configuration where libnss_systemd is enabled along with libnss_files +in the shadow entry of nsswitch.conf, so when libnss_files is unable +to obtain the shadow password file entry for the root user, e.g. when +SELinux is enabled, NSS falls back to libnss_systemd which returns +a synthesized shadow password file entry for the root user, which +in turn locks the root user out. + +https://bugzilla.redhat.com/show_bug.cgi?id=2150155 describes +essentially the same problem in a similar system configuration. + +This commit is the final step in the direction of addressing the issue: +for password verification pam_unix.so now invokes the helper instead of +making the pam_modutil_getspnam() call. + +* modules/pam_unix/passverify.c (get_account_info) [!HELPER_COMPILE]: +Always return PAM_UNIX_RUN_HELPER instead of trying to obtain +the shadow password file entry. + +Complements: https://github.com/linux-pam/linux-pam/pull/386 +Resolves: https://github.com/linux-pam/linux-pam/pull/484 +Link: https://github.com/authselect/authselect/commit/1e78f7e048747024a846fd22d68afc6993734e92 + +Conflict:NA +Reference:https://github.com/linux-pam/linux-pam/commit/b3020da7da384d769f27a8713257fbe1001878be +--- + modules/pam_unix/passverify.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index eb0fa74..1bb7c89 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -239,20 +239,21 @@ PAMH_ARG_DECL(int get_account_info, + return PAM_UNIX_RUN_HELPER; + #endif + } else if (is_pwd_shadowed(*pwd)) { ++#ifdef HELPER_COMPILE + /* +- * ...and shadow password file entry for this user, ++ * shadow password file entry for this user, + * if shadowing is enabled + */ +- *spwdent = pam_modutil_getspnam(pamh, name); +- if (*spwdent == NULL) { +-#ifndef HELPER_COMPILE +- /* still a chance the user can authenticate */ +- return PAM_UNIX_RUN_HELPER; +-#endif +- return PAM_AUTHINFO_UNAVAIL; +- } +- if ((*spwdent)->sp_pwdp == NULL) ++ *spwdent = getspnam(name); ++ if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) + return PAM_AUTHINFO_UNAVAIL; ++#else ++ /* ++ * The helper has to be invoked to deal with ++ * the shadow password file entry. ++ */ ++ return PAM_UNIX_RUN_HELPER; ++#endif + } + } else { + return PAM_USER_UNKNOWN; +-- +2.46.0 diff --git a/backport-Permit-unix_chkpwd-pam_unix.so-to-run-without-being-setuid-root.patch b/backport-Permit-unix_chkpwd-pam_unix.so-to-run-without-being-setuid-root.patch new file mode 100644 index 0000000..c14b73a --- /dev/null +++ b/backport-Permit-unix_chkpwd-pam_unix.so-to-run-without-being-setuid-root.patch @@ -0,0 +1,58 @@ +From f220cace205332a3dc34e7b37a85e7627e097e7d Mon Sep 17 00:00:00 2001 +From: "Andrew G. Morgan" +Date: Sat, 26 Jun 2021 14:18:08 -0700 +Subject: [PATCH] Permit unix_chkpwd & pam_unix.so to run without being + setuid-root. + +Remove the hard-coding of the idea that the only way pam_unix.so can +read the shadow file is if it can, in some way, run setuid-root. +Linux capabilities only require cap_dac_override to read the /etc/shadow +file. + +This change achieves two things: it opens a path for a linux-pam +application to run without being setuid-root; further, it allows +unix_chkpwd to run non-setuid-root if it is installed: + + sudo setcap cap_dac_override=ep unix_chkpwd + +If we wanted to link against libcap, we could install this binary with +cap_dac_override=p, and use cap_set_proc() to raise the effective bit +at runtime. However, some distributions already link unix_chkpwd +against libcap-ng for some, likely spurious, reason so "ep" is fine +for now. + +Signed-off-by: Andrew G. Morgan + +Conflict:NA +Reference:https://github.com/linux-pam/linux-pam/commit/f220cace205332a3dc34e7b37a85e7627e097e7d +--- + modules/pam_unix/passverify.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index fc2eaff..5bb518e 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -243,12 +243,16 @@ PAMH_ARG_DECL(int get_account_info, + * ...and shadow password file entry for this user, + * if shadowing is enabled + */ ++ *spwdent = pam_modutil_getspnam(pamh, name); ++ if (*spwdent == NULL) { + #ifndef HELPER_COMPILE +- if (geteuid() || SELINUX_ENABLED) +- return PAM_UNIX_RUN_HELPER; ++ /* still a chance the user can authenticate */ ++ if (errno == EACCES || SELINUX_ENABLED) ++ return PAM_UNIX_RUN_HELPER; + #endif +- *spwdent = pam_modutil_getspnam(pamh, name); +- if (*spwdent == NULL || (*spwdent)->sp_pwdp == NULL) ++ return PAM_AUTHINFO_UNAVAIL; ++ } ++ if ((*spwdent)->sp_pwdp == NULL) + return PAM_AUTHINFO_UNAVAIL; + } + } else { +-- +2.46.0 diff --git a/backport-pam_unix-workaround-the-problem-caused-by-libnss_sys.patch b/backport-pam_unix-workaround-the-problem-caused-by-libnss_sys.patch new file mode 100644 index 0000000..876a395 --- /dev/null +++ b/backport-pam_unix-workaround-the-problem-caused-by-libnss_sys.patch @@ -0,0 +1,44 @@ +From 470823c4aacef5cb3b1180be6ed70846b61a3752 Mon Sep 17 00:00:00 2001 +From: "Dmitry V. Levin" +Date: Thu, 19 Aug 2021 08:00:00 +0000 +Subject: [PATCH] pam_unix: workaround the problem caused by libnss_systemd + +The getspnam(3) manual page says that errno shall be set to EACCES when +the caller does not have permission to access the shadow password file. +Unfortunately, this contract is broken when libnss_systemd is used in +the nss stack. + +Workaround this problem by falling back to the helper invocation when +pam_modutil_getspnam returns NULL regardless of errno. As pam_unix +already behaves this way when selinux is enabled, it should be OK +for the case when selinux is not enabled, too. + +* modules/pam_unix/passverify.c (get_account_info): When +pam_modutil_getspnam returns NULL, unconditionally fall back +to the helper invocation. + +Complements: f220cace2053 ("Permit unix_chkpwd & pam_unix.so to run without being setuid-root") +Resolves: https://github.com/linux-pam/linux-pam/issues/379 + +Conflict:NA +Reference:https://github.com/linux-pam/linux-pam/commit/470823c4aacef5cb3b1180be6ed70846b61a3752 +--- + modules/pam_unix/passverify.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/modules/pam_unix/passverify.c b/modules/pam_unix/passverify.c +index 5bb518e..eb0fa74 100644 +--- a/modules/pam_unix/passverify.c ++++ b/modules/pam_unix/passverify.c +@@ -247,8 +247,7 @@ PAMH_ARG_DECL(int get_account_info, + if (*spwdent == NULL) { + #ifndef HELPER_COMPILE + /* still a chance the user can authenticate */ +- if (errno == EACCES || SELINUX_ENABLED) +- return PAM_UNIX_RUN_HELPER; ++ return PAM_UNIX_RUN_HELPER; + #endif + return PAM_AUTHINFO_UNAVAIL; + } +-- +2.46.0 diff --git a/pam.spec b/pam.spec index cc78f47..d0243d5 100644 --- a/pam.spec +++ b/pam.spec @@ -4,7 +4,7 @@ %define _pamconfdir %{_sysconfdir}/pam.d Name: pam Version: 1.4.0 -Release: 12 +Release: 13 Summary: Pluggable Authentication Modules for Linux License: BSD and GPLv2+ URL: http://www.linux-pam.org/ @@ -37,6 +37,10 @@ Patch6004: backport-pam_access-clean-up-the-remote-host-matching-code.patch Patch6005: backport-pam_access-handle-hostnames-in-access.conf.patch Patch6006: backport-pam_access-make-non-resolveable-hostname-a-debug-out.patch Patch6007: backport-CVE-2024-10963.patch +Patch6008: backport-Permit-unix_chkpwd-pam_unix.so-to-run-without-being-setuid-root.patch +Patch6009: backport-pam_unix-workaround-the-problem-caused-by-libnss_sys.patch +Patch6010: backport-CVE-2024-10041.patch +Patch6011: backport-CVE-2024-10041-pam_unix-try-to-set-uid-to-0-for-unix_chkpwd.patch Patch9000: add-sm3-crypt-support.patch @@ -191,6 +195,9 @@ fi %changelog +* Tue Dec 17 2024 dongyuzhen - 1.4.0-13 +- fix CVE-2024-10041 + * Fri Nov 29 2024 hugel - 1.4.0-12 - fix CVE-2024-10963