git: 57b08d98db0a - stable/14 - libutil: defer setting the MAC label until after the login class

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Tue, 20 Jan 2026 04:09:39 UTC
The branch stable/14 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=57b08d98db0a5bc16a6f0b47ade5b25021564d14

commit 57b08d98db0a5bc16a6f0b47ade5b25021564d14
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-10-29 02:37:21 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2026-01-20 04:05:44 +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
    Co-authored-by: Kevin Barry <ta0kira gmail com>
    
    (cherry picked from commit 98edcbcce0a4650084bd86e704cfa38bf590250c)
---
 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 172da78aaf17..db0218f94371 100644
--- a/lib/libutil/login_class.c
+++ b/lib/libutil/login_class.c
@@ -544,7 +544,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)
@@ -565,6 +565,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;
@@ -573,8 +594,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)
@@ -583,33 +606,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 */