b1cf0d
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
b1cf0d
--- Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c.pam_keyinit-thread-safe	2017-02-10 11:10:15.000000000 +0100
b1cf0d
+++ Linux-PAM-1.3.1/modules/pam_keyinit/pam_keyinit.c	2022-04-25 12:10:28.071240439 +0200
b1cf0d
@@ -20,6 +20,7 @@
b1cf0d
 #include <security/pam_modutil.h>
b1cf0d
 #include <security/pam_ext.h>
b1cf0d
 #include <sys/syscall.h>
b1cf0d
+#include <stdatomic.h>
b1cf0d
 
b1cf0d
 #define KEY_SPEC_SESSION_KEYRING	-3 /* ID for session keyring */
b1cf0d
 #define KEY_SPEC_USER_KEYRING		-4 /* ID for UID-specific keyring */
b1cf0d
@@ -30,12 +31,12 @@
b1cf0d
 #define KEYCTL_REVOKE			3 /* revoke a key */
b1cf0d
 #define KEYCTL_LINK			8 /* link a key into a keyring */
b1cf0d
 
b1cf0d
-static int my_session_keyring;
b1cf0d
-static int session_counter;
b1cf0d
-static int do_revoke;
b1cf0d
-static int revoke_as_uid;
b1cf0d
-static int revoke_as_gid;
b1cf0d
-static int xdebug = 0;
b1cf0d
+static _Thread_local int my_session_keyring = 0;
b1cf0d
+static _Atomic int session_counter = 0;
b1cf0d
+static _Thread_local int do_revoke = 0;
b1cf0d
+static _Thread_local uid_t revoke_as_uid;
b1cf0d
+static _Thread_local gid_t revoke_as_gid;
b1cf0d
+static _Thread_local int xdebug = 0;
b1cf0d
 
b1cf0d
 static void debug(pam_handle_t *pamh, const char *fmt, ...)
b1cf0d
 	__attribute__((format(printf, 2, 3)));
b1cf0d
@@ -65,6 +66,33 @@ static int error(pam_handle_t *pamh, con
b1cf0d
 	return PAM_SESSION_ERR;
b1cf0d
 }
b1cf0d
 
b1cf0d
+static int pam_setreuid(uid_t ruid, uid_t euid)
b1cf0d
+{
b1cf0d
+#if defined(SYS_setreuid32)
b1cf0d
+    return syscall(SYS_setreuid32, ruid, euid);
b1cf0d
+#else
b1cf0d
+    return syscall(SYS_setreuid, ruid, euid);
b1cf0d
+#endif
b1cf0d
+}
b1cf0d
+
b1cf0d
+static int pam_setregid(gid_t rgid, gid_t egid)
b1cf0d
+{
b1cf0d
+#if defined(SYS_setregid32)
b1cf0d
+    return syscall(SYS_setregid32, rgid, egid);
b1cf0d
+#else
b1cf0d
+    return syscall(SYS_setregid, rgid, egid);
b1cf0d
+#endif
b1cf0d
+}
b1cf0d
+
b1cf0d
+static int pam_setresuid(uid_t ruid, uid_t euid, uid_t suid)
b1cf0d
+{
b1cf0d
+#if defined(SYS_setresuid32)
b1cf0d
+    return syscall(SYS_setresuid32, ruid, euid, suid);
b1cf0d
+#else
b1cf0d
+    return syscall(SYS_setresuid, ruid, euid, suid);
b1cf0d
+#endif
b1cf0d
+}
b1cf0d
+
b1cf0d
 /*
b1cf0d
  * initialise the session keyring for this process
b1cf0d
  */
b1cf0d
@@ -139,23 +167,25 @@ static void kill_keyrings(pam_handle_t *
b1cf0d
 
b1cf0d
 		/* switch to the real UID and GID so that we have permission to
b1cf0d
 		 * revoke the key */
b1cf0d
-		if (revoke_as_gid != old_gid && setregid(-1, revoke_as_gid) < 0)
b1cf0d
+		if (revoke_as_gid != old_gid && pam_setregid(-1, revoke_as_gid) < 0)
b1cf0d
 			error(pamh, "Unable to change GID to %d temporarily\n",
b1cf0d
 			      revoke_as_gid);
b1cf0d
 
b1cf0d
-		if (revoke_as_uid != old_uid && setresuid(-1, revoke_as_uid, old_uid) < 0)
b1cf0d
+		if (revoke_as_uid != old_uid && pam_setresuid(-1, revoke_as_uid, old_uid) < 0)
b1cf0d
 			error(pamh, "Unable to change UID to %d temporarily\n",
b1cf0d
 			      revoke_as_uid);
b1cf0d
+			if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0)
b1cf0d
+				error(pamh, "Unable to change GID back to %d\n", old_gid);
b1cf0d
 
b1cf0d
 		syscall(__NR_keyctl,
b1cf0d
 			KEYCTL_REVOKE,
b1cf0d
 			my_session_keyring);
b1cf0d
 
b1cf0d
 		/* return to the orignal UID and GID (probably root) */
b1cf0d
-		if (revoke_as_uid != old_uid && setreuid(-1, old_uid) < 0)
b1cf0d
+		if (revoke_as_uid != old_uid && pam_setreuid(-1, old_uid) < 0)
b1cf0d
 			error(pamh, "Unable to change UID back to %d\n", old_uid);
b1cf0d
 
b1cf0d
-		if (revoke_as_gid != old_gid && setregid(-1, old_gid) < 0)
b1cf0d
+		if (revoke_as_gid != old_gid && pam_setregid(-1, old_gid) < 0)
b1cf0d
 			error(pamh, "Unable to change GID back to %d\n", old_gid);
b1cf0d
 
b1cf0d
 		my_session_keyring = 0;
b1cf0d
@@ -210,14 +240,14 @@ int pam_sm_open_session(pam_handle_t *pa
b1cf0d
 
b1cf0d
 	/* switch to the real UID and GID so that the keyring ends up owned by
b1cf0d
 	 * the right user */
b1cf0d
-	if (gid != old_gid && setregid(gid, -1) < 0) {
b1cf0d
+	if (gid != old_gid && pam_setregid(gid, -1) < 0) {
b1cf0d
 		error(pamh, "Unable to change GID to %d temporarily\n", gid);
b1cf0d
 		return PAM_SESSION_ERR;
b1cf0d
 	}
b1cf0d
 
b1cf0d
-	if (uid != old_uid && setreuid(uid, -1) < 0) {
b1cf0d
+	if (uid != old_uid && pam_setreuid(uid, -1) < 0) {
b1cf0d
 		error(pamh, "Unable to change UID to %d temporarily\n", uid);
b1cf0d
-		if (setregid(old_gid, -1) < 0)
b1cf0d
+		if (pam_setregid(old_gid, -1) < 0)
b1cf0d
 			error(pamh, "Unable to change GID back to %d\n", old_gid);
b1cf0d
 		return PAM_SESSION_ERR;
b1cf0d
 	}
b1cf0d
@@ -225,10 +255,10 @@ int pam_sm_open_session(pam_handle_t *pa
b1cf0d
 	ret = init_keyrings(pamh, force);
b1cf0d
 
b1cf0d
 	/* return to the orignal UID and GID (probably root) */
b1cf0d
-	if (uid != old_uid && setreuid(old_uid, -1) < 0)
b1cf0d
+	if (uid != old_uid && pam_setreuid(old_uid, -1) < 0)
b1cf0d
 		ret = error(pamh, "Unable to change UID back to %d\n", old_uid);
b1cf0d
 
b1cf0d
-	if (gid != old_gid && setregid(old_gid, -1) < 0)
b1cf0d
+	if (gid != old_gid && pam_setregid(old_gid, -1) < 0)
b1cf0d
 		ret = error(pamh, "Unable to change GID back to %d\n", old_gid);
b1cf0d
 
b1cf0d
 	return ret;