diff -up Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c --- Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe 2017-02-10 11:10:15.000000000 +0100 +++ Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c 2022-04-25 12:10:28.071240439 +0200 @@ -20,6 +20,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 */ @@ -30,12 +31,12 @@ #define KEYCTL_REVOKE 3 /* revoke a key */ #define KEYCTL_LINK 8 /* link a key into a keyring */ -static int my_session_keyring; -static int session_counter; -static int do_revoke; -static int revoke_as_uid; -static int 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))); @@ -65,6 +66,33 @@ static int error(pam_handle_t *pamh, con return PAM_SESSION_ERR; } +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 */ @@ -139,23 +167,25 @@ static void kill_keyrings(pam_handle_t * /* 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); - 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 && pam_setregid(-1, old_gid) < 0) + error(pamh, "Unable to change GID back to %d\n", old_gid); syscall(__NR_keyctl, KEYCTL_REVOKE, my_session_keyring); /* return to the orignal 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); - 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); my_session_keyring = 0; @@ -210,14 +240,14 @@ int pam_sm_open_session(pam_handle_t *pa /* 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 PAM_SESSION_ERR; } - 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 PAM_SESSION_ERR; } @@ -225,10 +255,10 @@ int pam_sm_open_session(pam_handle_t *pa ret = init_keyrings(pamh, force); /* return to the orignal UID and GID (probably root) */ - if (uid != old_uid && setreuid(old_uid, -1) < 0) + if (uid != old_uid && pam_setreuid(old_uid, -1) < 0) ret = error(pamh, "Unable to change UID back to %d\n", old_uid); - if (gid != old_gid && setregid(old_gid, -1) < 0) + if (gid != old_gid && pam_setregid(old_gid, -1) < 0) ret = error(pamh, "Unable to change GID back to %d\n", old_gid); return ret;