git: 98edcbcce0a4 - main - libutil: defer setting the MAC label until after the login class

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Wed, 29 Oct 2025 02:37:24 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=98edcbcce0a4650084bd86e704cfa38bf590250c

commit 98edcbcce0a4650084bd86e704cfa38bf590250c
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-10-29 02:37:21 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-10-29 02:37:21 +0000

    libutil: defer setting the MAC label until after the login class
    
    MAC policies, like mac_biba(4), may forbid changing the login class once
    a label has been applied.  For setting up the initial login context,
    this isn't really expected and in-fact may break some class-based
    configuration.
    
    Defer setting the MAC label until after the login class is set, and
    remove the requirement that we have a pwd entry since the label is
    pulled from the login class -- we only use pwd for syslog in this path.
    
    Patch is largely by Kevin Barry, with some modifications and this commit
    message by kevans@.
    
    PR:             177698
    Reviewed by:    des, olce
    MFC after:      3 days
    Co-authored-by: Kevin Barry <ta0kira gmail com>
    Differential Revision:  https://reviews.freebsd.org/D53362
---
 lib/libutil/login_class.c | 55 ++++++++++++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c
index c3c1b0ddda27..9478b4dc98ca 100644
--- a/lib/libutil/login_class.c
+++ b/lib/libutil/login_class.c
@@ -543,7 +543,7 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
 
     /* we need a passwd entry to set these */
     if (pwd == NULL)
-	flags &= ~(LOGIN_SETGROUP | LOGIN_SETLOGIN | LOGIN_SETMAC);
+	flags &= ~(LOGIN_SETGROUP | LOGIN_SETLOGIN);
 
     /* Set the process priority */
     if (flags & LOGIN_SETPRIORITY)
@@ -564,6 +564,27 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
 	}
     }
 
+    /* Set the sessions login */
+    if ((flags & LOGIN_SETLOGIN) && setlogin(pwd->pw_name) != 0) {
+	syslog(LOG_ERR, "setlogin(%s): %m", pwd->pw_name);
+	login_close(llc);
+	return (-1);
+    }
+
+    /* Inform the kernel about current login class */
+    if (lc != NULL && lc->lc_class != NULL && (flags & LOGIN_SETLOGINCLASS)) {
+	error = setloginclass(lc->lc_class);
+	if (error != 0) {
+	    syslog(LOG_ERR, "setloginclass(%s): %m", lc->lc_class);
+#ifdef notyet
+	    login_close(llc);
+	    return (-1);
+#endif
+	}
+    }
+
+    setlogincontext(lc, pwd, flags);
+
     /* Set up the user's MAC label. */
     if ((flags & LOGIN_SETMAC) && mac_is_present(NULL) == 1) {
 	const char *label_string;
@@ -572,8 +593,10 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
 	label_string = login_getcapstr(lc, "label", NULL, NULL);
 	if (label_string != NULL) {
 	    if (mac_from_text(&label, label_string) == -1) {
-		syslog(LOG_ERR, "mac_from_text('%s') for %s: %m",
-		    pwd->pw_name, label_string);
+		syslog(LOG_ERR, "mac_from_text('%s') for %s %s: %m",
+		    label_string, pwd != NULL ? "user" : "class",
+		    pwd != NULL ? pwd->pw_name : lc->lc_class);
+		login_close(llc);
 		return (-1);
 	    }
 	    if (mac_set_proc(label) == -1)
@@ -582,33 +605,15 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
 		error = 0;
 	    mac_free(label);
 	    if (error != 0) {
-		syslog(LOG_ERR, "mac_set_proc('%s') for %s: %s",
-		    label_string, pwd->pw_name, strerror(error));
+		syslog(LOG_ERR, "mac_set_proc('%s') for %s %s: %s",
+		    label_string, pwd != NULL ? "user" : "class",
+		    pwd != NULL ? pwd->pw_name : lc->lc_class, strerror(error));
+		login_close(llc);
 		return (-1);
 	    }
 	}
     }
 
-    /* Set the sessions login */
-    if ((flags & LOGIN_SETLOGIN) && setlogin(pwd->pw_name) != 0) {
-	syslog(LOG_ERR, "setlogin(%s): %m", pwd->pw_name);
-	login_close(llc);
-	return (-1);
-    }
-
-    /* Inform the kernel about current login class */
-    if (lc != NULL && lc->lc_class != NULL && (flags & LOGIN_SETLOGINCLASS)) {
-	error = setloginclass(lc->lc_class);
-	if (error != 0) {
-	    syslog(LOG_ERR, "setloginclass(%s): %m", lc->lc_class);
-#ifdef notyet
-	    login_close(llc);
-	    return (-1);
-#endif
-	}
-    }
-
-    setlogincontext(lc, pwd, flags);
     login_close(llc);
 
     /* This needs to be done after anything that needs root privs */