Blame SOURCES/pam-1.5.1-pam-keyinit-thread-safe.patch

e0a759
From a35e092e24ee7632346a0e1b4a203c04d4cd2c62 Mon Sep 17 00:00:00 2001
e0a759
From: Iker Pedrosa <ipedrosa@redhat.com>
e0a759
Date: Mon, 24 Jan 2022 15:43:23 +0100
e0a759
Subject: [PATCH] pam_keyinit: thread-safe implementation
e0a759
e0a759
* modules/pam_keyinit/pam_keyinit.c: Bypass setre*id() C library calls
e0a759
with kernel calls and change global variables definitions to be
e0a759
thread-safe.
e0a759
e0a759
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1997969
e0a759
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
e0a759
Co-Authored-By: Andreas Schneider <asn@samba.org>
e0a759
---
e0a759
 modules/pam_keyinit/pam_keyinit.c | 60 ++++++++++++++++++++++---------
e0a759
 1 file changed, 44 insertions(+), 16 deletions(-)
e0a759
e0a759
diff --git a/modules/pam_keyinit/pam_keyinit.c b/modules/pam_keyinit/pam_keyinit.c
e0a759
index 92e4953b..df9804b9 100644
e0a759
--- a/modules/pam_keyinit/pam_keyinit.c
e0a759
+++ b/modules/pam_keyinit/pam_keyinit.c
e0a759
@@ -21,6 +21,7 @@
e0a759
 #include <security/pam_modutil.h>
e0a759
 #include <security/pam_ext.h>
e0a759
 #include <sys/syscall.h>
e0a759
+#include <stdatomic.h>
e0a759
 
e0a759
 #define KEY_SPEC_SESSION_KEYRING	-3 /* ID for session keyring */
e0a759
 #define KEY_SPEC_USER_KEYRING		-4 /* ID for UID-specific keyring */
e0a759
@@ -31,12 +32,12 @@
e0a759
 #define KEYCTL_REVOKE			3 /* revoke a key */
e0a759
 #define KEYCTL_LINK			8 /* link a key into a keyring */
e0a759
 
e0a759
-static int my_session_keyring = 0;
e0a759
-static int session_counter = 0;
e0a759
-static int do_revoke = 0;
e0a759
-static uid_t revoke_as_uid;
e0a759
-static gid_t revoke_as_gid;
e0a759
-static int xdebug = 0;
e0a759
+static _Thread_local int my_session_keyring = 0;
e0a759
+static _Atomic int session_counter = 0;
e0a759
+static _Thread_local int do_revoke = 0;
e0a759
+static _Thread_local uid_t revoke_as_uid;
e0a759
+static _Thread_local gid_t revoke_as_gid;
e0a759
+static _Thread_local int xdebug = 0;
e0a759
 
e0a759
 static void debug(pam_handle_t *pamh, const char *fmt, ...)
e0a759
 	__attribute__((format(printf, 2, 3)));
e0a759
@@ -64,6 +65,33 @@ static void error(pam_handle_t *pamh, const char *fmt, ...)
e0a759
 	va_end(va);
e0a759
 }
e0a759
 
e0a759
+static int pam_setreuid(uid_t ruid, uid_t euid)
e0a759
+{
e0a759
+#if defined(SYS_setreuid32)
e0a759
+    return syscall(SYS_setreuid32, ruid, euid);
e0a759
+#else
e0a759
+    return syscall(SYS_setreuid, ruid, euid);
e0a759
+#endif
e0a759
+}
e0a759
+
e0a759
+static int pam_setregid(gid_t rgid, gid_t egid)
e0a759
+{
e0a759
+#if defined(SYS_setregid32)
e0a759
+    return syscall(SYS_setregid32, rgid, egid);
e0a759
+#else
e0a759
+    return syscall(SYS_setregid, rgid, egid);
e0a759
+#endif
e0a759
+}
e0a759
+
e0a759
+static int pam_setresuid(uid_t ruid, uid_t euid, uid_t suid)
e0a759
+{
e0a759
+#if defined(SYS_setresuid32)
e0a759
+    return syscall(SYS_setresuid32, ruid, euid, suid);
e0a759
+#else
e0a759
+    return syscall(SYS_setresuid, ruid, euid, suid);
e0a759
+#endif
e0a759
+}
e0a759
+
e0a759
 /*
e0a759
  * initialise the session keyring for this process
e0a759
  */
e0a759
@@ -140,14 +168,14 @@ static int kill_keyrings(pam_handle_t *pamh, int error_ret)
e0a759
 
e0a759
 		/* switch to the real UID and GID so that we have permission to
e0a759
 		 * revoke the key */
e0a759
-		if (revoke_as_gid != old_gid && setregid(-1, revoke_as_gid) < 0) {
e0a759
+		if (revoke_as_gid != old_gid && pam_setregid(-1, revoke_as_gid) < 0) {
e0a759
 			error(pamh, "Unable to change GID to %d temporarily\n", revoke_as_gid);
e0a759
 			return error_ret;
e0a759
 		}
e0a759
 
e0a759
-		if (revoke_as_uid != old_uid && setresuid(-1, revoke_as_uid, old_uid) < 0) {
e0a759
+		if (revoke_as_uid != old_uid && pam_setresuid(-1, revoke_as_uid, old_uid) < 0) {
e0a759
 			error(pamh, "Unable to change UID to %d temporarily\n", revoke_as_uid);
e0a759
-			if (getegid() != old_gid && setregid(-1, old_gid) < 0)
e0a759
+			if (getegid() != old_gid && pam_setregid(-1, old_gid) < 0)
e0a759
 				error(pamh, "Unable to change GID back to %d\n", old_gid);
e0a759
 			return error_ret;
e0a759
 		}
e0a759
@@ -157,12 +185,12 @@ static int kill_keyrings(pam_handle_t *pamh, int error_ret)
e0a759
 		}
e0a759
 
e0a759
 		/* return to the original UID and GID (probably root) */
e0a759
-		if (revoke_as_uid != old_uid && setreuid(-1, old_uid) < 0) {
e0a759
+		if (revoke_as_uid != old_uid && pam_setreuid(-1, old_uid) < 0) {
e0a759
 			error(pamh, "Unable to change UID back to %d\n", old_uid);
e0a759
 			ret = error_ret;
e0a759
 		}
e0a759
 
e0a759
-		if (revoke_as_gid != old_gid && setregid(-1, old_gid) < 0) {
e0a759
+		if (revoke_as_gid != old_gid && pam_setregid(-1, old_gid) < 0) {
e0a759
 			error(pamh, "Unable to change GID back to %d\n", old_gid);
e0a759
 			ret = error_ret;
e0a759
 		}
e0a759
@@ -215,14 +243,14 @@ static int do_keyinit(pam_handle_t *pamh, int argc, const char **argv, int error
e0a759
 
e0a759
 	/* switch to the real UID and GID so that the keyring ends up owned by
e0a759
 	 * the right user */
e0a759
-	if (gid != old_gid && setregid(gid, -1) < 0) {
e0a759
+	if (gid != old_gid && pam_setregid(gid, -1) < 0) {
e0a759
 		error(pamh, "Unable to change GID to %d temporarily\n", gid);
e0a759
 		return error_ret;
e0a759
 	}
e0a759
 
e0a759
-	if (uid != old_uid && setreuid(uid, -1) < 0) {
e0a759
+	if (uid != old_uid && pam_setreuid(uid, -1) < 0) {
e0a759
 		error(pamh, "Unable to change UID to %d temporarily\n", uid);
e0a759
-		if (setregid(old_gid, -1) < 0)
e0a759
+		if (pam_setregid(old_gid, -1) < 0)
e0a759
 			error(pamh, "Unable to change GID back to %d\n", old_gid);
e0a759
 		return error_ret;
e0a759
 	}
e0a759
@@ -230,12 +258,12 @@ static int do_keyinit(pam_handle_t *pamh, int argc, const char **argv, int error
e0a759
 	ret = init_keyrings(pamh, force, error_ret);
e0a759
 
e0a759
 	/* return to the original UID and GID (probably root) */
e0a759
-	if (uid != old_uid && setreuid(old_uid, -1) < 0) {
e0a759
+	if (uid != old_uid && pam_setreuid(old_uid, -1) < 0) {
e0a759
 		error(pamh, "Unable to change UID back to %d\n", old_uid);
e0a759
 		ret = error_ret;
e0a759
 	}
e0a759
 
e0a759
-	if (gid != old_gid && setregid(old_gid, -1) < 0) {
e0a759
+	if (gid != old_gid && pam_setregid(old_gid, -1) < 0) {
e0a759
 		error(pamh, "Unable to change GID back to %d\n", old_gid);
e0a759
 		ret = error_ret;
e0a759
 	}
e0a759
-- 
e0a759
2.35.1
e0a759