diff --git a/SOURCES/pam-1.5.1-pam-keyinit-thread-safe.patch b/SOURCES/pam-1.5.1-pam-keyinit-thread-safe.patch new file mode 100644 index 0000000..f898b0b --- /dev/null +++ b/SOURCES/pam-1.5.1-pam-keyinit-thread-safe.patch @@ -0,0 +1,150 @@ +From a35e092e24ee7632346a0e1b4a203c04d4cd2c62 Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Mon, 24 Jan 2022 15:43:23 +0100 +Subject: [PATCH] pam_keyinit: thread-safe implementation + +* modules/pam_keyinit/pam_keyinit.c: Bypass setre*id() C library calls +with kernel calls and change global variables definitions to be +thread-safe. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1997969 +Signed-off-by: Iker Pedrosa +Co-Authored-By: Andreas Schneider +--- + modules/pam_keyinit/pam_keyinit.c | 60 ++++++++++++++++++++++--------- + 1 file changed, 44 insertions(+), 16 deletions(-) + +diff --git a/modules/pam_keyinit/pam_keyinit.c b/modules/pam_keyinit/pam_keyinit.c +index 92e4953b..df9804b9 100644 +--- a/modules/pam_keyinit/pam_keyinit.c ++++ b/modules/pam_keyinit/pam_keyinit.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #define KEY_SPEC_SESSION_KEYRING -3 /* ID for session keyring */ + #define KEY_SPEC_USER_KEYRING -4 /* ID for UID-specific keyring */ +@@ -31,12 +32,12 @@ + #define KEYCTL_REVOKE 3 /* revoke a key */ + #define KEYCTL_LINK 8 /* link a key into a keyring */ + +-static int my_session_keyring = 0; +-static int session_counter = 0; +-static int do_revoke = 0; +-static uid_t revoke_as_uid; +-static gid_t revoke_as_gid; +-static int xdebug = 0; ++static _Thread_local int my_session_keyring = 0; ++static _Atomic int session_counter = 0; ++static _Thread_local int do_revoke = 0; ++static _Thread_local uid_t revoke_as_uid; ++static _Thread_local gid_t revoke_as_gid; ++static _Thread_local int xdebug = 0; + + static void debug(pam_handle_t *pamh, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +@@ -64,6 +65,33 @@ static void error(pam_handle_t *pamh, const char *fmt, ...) + va_end(va); + } + ++static int pam_setreuid(uid_t ruid, uid_t euid) ++{ ++#if defined(SYS_setreuid32) ++ return syscall(SYS_setreuid32, ruid, euid); ++#else ++ return syscall(SYS_setreuid, ruid, euid); ++#endif ++} ++ ++static int pam_setregid(gid_t rgid, gid_t egid) ++{ ++#if defined(SYS_setregid32) ++ return syscall(SYS_setregid32, rgid, egid); ++#else ++ return syscall(SYS_setregid, rgid, egid); ++#endif ++} ++ ++static int pam_setresuid(uid_t ruid, uid_t euid, uid_t suid) ++{ ++#if defined(SYS_setresuid32) ++ return syscall(SYS_setresuid32, ruid, euid, suid); ++#else ++ return syscall(SYS_setresuid, ruid, euid, suid); ++#endif ++} ++ + /* + * initialise the session keyring for this process + */ +@@ -140,14 +168,14 @@ static int kill_keyrings(pam_handle_t *pamh, int error_ret) + + /* switch to the real UID and GID so that we have permission to + * revoke the key */ +- if (revoke_as_gid != old_gid && setregid(-1, revoke_as_gid) < 0) { ++ if (revoke_as_gid != old_gid && pam_setregid(-1, revoke_as_gid) < 0) { + error(pamh, "Unable to change GID to %d temporarily\n", revoke_as_gid); + return error_ret; + } + +- if (revoke_as_uid != old_uid && setresuid(-1, revoke_as_uid, old_uid) < 0) { ++ if (revoke_as_uid != old_uid && pam_setresuid(-1, revoke_as_uid, old_uid) < 0) { + error(pamh, "Unable to change UID to %d temporarily\n", revoke_as_uid); +- if (getegid() != old_gid && setregid(-1, old_gid) < 0) ++ if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0) + error(pamh, "Unable to change GID back to %d\n", old_gid); + return error_ret; + } +@@ -157,12 +185,12 @@ static int kill_keyrings(pam_handle_t *pamh, int error_ret) + } + + /* return to the original UID and GID (probably root) */ +- if (revoke_as_uid != old_uid && setreuid(-1, old_uid) < 0) { ++ if (revoke_as_uid != old_uid && pam_setreuid(-1, old_uid) < 0) { + error(pamh, "Unable to change UID back to %d\n", old_uid); + ret = error_ret; + } + +- if (revoke_as_gid != old_gid && setregid(-1, old_gid) < 0) { ++ if (revoke_as_gid != old_gid && pam_setregid(-1, old_gid) < 0) { + error(pamh, "Unable to change GID back to %d\n", old_gid); + ret = error_ret; + } +@@ -215,14 +243,14 @@ static int do_keyinit(pam_handle_t *pamh, int argc, const char **argv, int error + + /* switch to the real UID and GID so that the keyring ends up owned by + * the right user */ +- if (gid != old_gid && setregid(gid, -1) < 0) { ++ if (gid != old_gid && pam_setregid(gid, -1) < 0) { + error(pamh, "Unable to change GID to %d temporarily\n", gid); + return error_ret; + } + +- if (uid != old_uid && setreuid(uid, -1) < 0) { ++ if (uid != old_uid && pam_setreuid(uid, -1) < 0) { + error(pamh, "Unable to change UID to %d temporarily\n", uid); +- if (setregid(old_gid, -1) < 0) ++ if (pam_setregid(old_gid, -1) < 0) + error(pamh, "Unable to change GID back to %d\n", old_gid); + return error_ret; + } +@@ -230,12 +258,12 @@ static int do_keyinit(pam_handle_t *pamh, int argc, const char **argv, int error + ret = init_keyrings(pamh, force, error_ret); + + /* return to the original UID and GID (probably root) */ +- if (uid != old_uid && setreuid(old_uid, -1) < 0) { ++ if (uid != old_uid && pam_setreuid(old_uid, -1) < 0) { + error(pamh, "Unable to change UID back to %d\n", old_uid); + ret = error_ret; + } + +- if (gid != old_gid && setregid(old_gid, -1) < 0) { ++ if (gid != old_gid && pam_setregid(old_gid, -1) < 0) { + error(pamh, "Unable to change GID back to %d\n", old_gid); + ret = error_ret; + } +-- +2.35.1 + diff --git a/SOURCES/pam-1.5.1-pam-usertype-SYS_UID_MAX.patch b/SOURCES/pam-1.5.1-pam-usertype-SYS_UID_MAX.patch new file mode 100644 index 0000000..df0ac35 --- /dev/null +++ b/SOURCES/pam-1.5.1-pam-usertype-SYS_UID_MAX.patch @@ -0,0 +1,100 @@ +From 370064ef6f99581b08d473a42bb3417d5dda3e4e Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Thu, 17 Feb 2022 10:24:03 +0100 +Subject: [PATCH] pam_usertype: only use SYS_UID_MAX for system users + +* modules/pam_usertype/pam_usertype.c (pam_usertype_is_system): Stop +using SYS_UID_MIN to check if it is a system account, because all +accounts below the SYS_UID_MAX are system users. +* modules/pam_usertype/pam_usertype.8.xml: Remove reference to SYS_UID_MIN +as it is no longer used to calculate the system accounts. +* configure.ac: Remove PAM_USERTYPE_SYSUIDMIN. + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1949137 +Signed-off-by: Iker Pedrosa +--- + configure.ac | 5 ----- + modules/pam_usertype/pam_usertype.8.xml | 2 +- + modules/pam_usertype/pam_usertype.c | 15 ++++++--------- + 3 files changed, 7 insertions(+), 15 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 639fc1ad..79113ad1 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -632,11 +632,6 @@ test -n "$opt_uidmin" || + opt_uidmin=1000 + AC_DEFINE_UNQUOTED(PAM_USERTYPE_UIDMIN, $opt_uidmin, [Minimum regular user uid.]) + +-AC_ARG_WITH([sysuidmin], AS_HELP_STRING([--with-sysuidmin=],[default value for system user min uid (101)]), opt_sysuidmin=$withval) +-test -n "$opt_sysuidmin" || +- opt_sysuidmin=101 +-AC_DEFINE_UNQUOTED(PAM_USERTYPE_SYSUIDMIN, $opt_sysuidmin, [Minimum system user uid.]) +- + AC_ARG_WITH([kernel-overflow-uid], AS_HELP_STRING([--with-kernel-overflow-uid=],[kernel overflow uid, default (uint16_t)-2=65534]), opt_kerneloverflowuid=$withval) + test -n "$opt_kerneloverflowuid" || + opt_kerneloverflowuid=65534 +diff --git a/modules/pam_usertype/pam_usertype.8.xml b/modules/pam_usertype/pam_usertype.8.xml +index 7651da6e..d9307ba3 100644 +--- a/modules/pam_usertype/pam_usertype.8.xml ++++ b/modules/pam_usertype/pam_usertype.8.xml +@@ -31,7 +31,7 @@ + pam_usertype.so is designed to succeed or fail authentication + based on type of the account of the authenticated user. + The type of the account is decided with help of +- SYS_UID_MIN and SYS_UID_MAX ++ SYS_UID_MAX + settings in /etc/login.defs. One use is to select + whether to load other modules based on this test. + +diff --git a/modules/pam_usertype/pam_usertype.c b/modules/pam_usertype/pam_usertype.c +index d03b73b5..cfd9c8bb 100644 +--- a/modules/pam_usertype/pam_usertype.c ++++ b/modules/pam_usertype/pam_usertype.c +@@ -194,7 +194,6 @@ static int + pam_usertype_is_system(pam_handle_t *pamh, uid_t uid) + { + uid_t uid_min; +- uid_t sys_min; + uid_t sys_max; + + if (uid == (uid_t)-1) { +@@ -202,21 +201,19 @@ pam_usertype_is_system(pam_handle_t *pamh, uid_t uid) + return PAM_USER_UNKNOWN; + } + +- if (uid <= 99) { +- /* Reserved. */ +- return PAM_SUCCESS; +- } +- + if (uid == PAM_USERTYPE_OVERFLOW_UID) { + /* nobody */ + return PAM_SUCCESS; + } + + uid_min = pam_usertype_get_id(pamh, "UID_MIN", PAM_USERTYPE_UIDMIN); +- sys_min = pam_usertype_get_id(pamh, "SYS_UID_MIN", PAM_USERTYPE_SYSUIDMIN); + sys_max = pam_usertype_get_id(pamh, "SYS_UID_MAX", uid_min - 1); + +- return uid >= sys_min && uid <= sys_max ? PAM_SUCCESS : PAM_AUTH_ERR; ++ if (uid <= sys_max && uid < uid_min) { ++ return PAM_SUCCESS; ++ } ++ ++ return PAM_AUTH_ERR; + } + + static int +@@ -253,7 +250,7 @@ pam_usertype_evaluate(struct pam_usertype_opts *opts, + + /** + * Arguments: +- * - issystem: uid in ++ * - issystem: uid less than SYS_UID_MAX + * - isregular: not issystem + * - use_uid: use user that runs application not that is being authenticate (same as in pam_succeed_if) + * - audit: log unknown users to syslog +-- +2.36.1 + diff --git a/SPECS/pam.spec b/SPECS/pam.spec index 17a16d2..0886d95 100644 --- a/SPECS/pam.spec +++ b/SPECS/pam.spec @@ -3,7 +3,7 @@ Summary: An extensible library which provides authentication for applications Name: pam Version: 1.5.1 -Release: 9%{?dist}.1 +Release: 12%{?dist} # The library is BSD licensed with option to relicense as GPLv2+ # - this option is redundant as the BSD license allows that anyway. # pam_timestamp, pam_loginuid, and pam_console modules are GPLv2+. @@ -32,9 +32,13 @@ Patch4: pam-1.5.1-timestamp-openssl-hmac-authentication.patch Patch5: pam-1.5.1-pam_filter_close_file_after_controlling_tty.patch # https://github.com/linux-pam/linux-pam/commit/3234488f2c52a021eec87df1990d256314c21bff Patch6: pam-1.5.1-pam-limits-unlimited-value.patch +# https://github.com/linux-pam/linux-pam/commit/a35e092e24ee7632346a0e1b4a203c04d4cd2c62 +Patch7: pam-1.5.1-pam-keyinit-thread-safe.patch # https://github.com/linux-pam/linux-pam/commit/9bcbe96d9e82a23d983c0618178a8dc25596ac2d # https://github.com/linux-pam/linux-pam/commit/fc867a9e22eac2c9a0ed0577776bba4df21c9aad -Patch7: pam-1.5.1-faillock-load-conf-from-file.patch +Patch8: pam-1.5.1-faillock-load-conf-from-file.patch +# https://github.com/linux-pam/linux-pam/commit/370064ef6f99581b08d473a42bb3417d5dda3e4e +Patch9: pam-1.5.1-pam-usertype-SYS_UID_MAX.patch %global _pamlibdir %{_libdir} %global _moduledir %{_libdir}/security @@ -123,7 +127,9 @@ cp %{SOURCE18} . %patch4 -p1 -b .timestamp-openssl-hmac-authentication %patch5 -p1 -b .pam_filter_close_file_after_controlling_tty %patch6 -p1 -b .pam-limits-unlimited-value -%patch7 -p1 -b .faillock-load-conf-from-file +%patch7 -p1 -b .pam-keyinit-thread-safe +%patch8 -p1 -b .faillock-load-conf-from-file +%patch9 -p1 -b .pam-usertype-SYS_UID_MAX autoreconf -i @@ -378,8 +384,14 @@ done %doc doc/sag/*.txt doc/sag/html %changelog -* Mon Aug 1 2022 Iker Pedrosa - 1.5.1-9.1 -- faillock: load configuration from file. Resolves: #2112888 +* Thu Jun 23 2022 Iker Pedrosa - 1.5.1-12 +- pam_usertype: only use SYS_UID_MAX for system users. Resolves: #2078421 + +* Wed May 25 2022 Iker Pedrosa - 1.5.1-11 +- faillock: load configuration from file. Resolves: #2061698 + +* Tue May 17 2022 Iker Pedrosa - 1.5.1-10 +- pam_keyinit: thread-safe implementation. Resolves: #2061696 * Thu Dec 2 2021 Iker Pedrosa - 1.5.1-9 - pam_limits: "Unlimited" is not a valid value for RLIMIT_NOFILE. Resolves: #1989900