From b7b96362087414e52524d3d9d9b3faa21e1db620 Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
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 <tobias@stoeckmann.org>

Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/b7b96362087414e52524d3d9d9b3faa21e1db620]
CVE: CVE-2024-10041
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
---
 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 8f5ed3e0df..7ffcb9e3f2 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 d391973f95..69811048e6 100644
--- a/modules/pam_unix/support.c
+++ b/modules/pam_unix/support.c
@@ -562,13 +562,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 */
