git: 3dec4c30c76b - stable/14 - setusercontext(): umask: Set it only once (in the common case)

From: Olivier Certner <olce_at_FreeBSD.org>
Date: Thu, 01 Feb 2024 21:31:05 UTC
The branch stable/14 has been updated by olce:

URL: https://cgit.FreeBSD.org/src/commit/?id=3dec4c30c76b1646c835768863c876f516852fc3

commit 3dec4c30c76b1646c835768863c876f516852fc3
Author:     Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2023-05-25 12:18:45 +0000
Commit:     Olivier Certner <olce@FreeBSD.org>
CommitDate: 2024-02-01 21:28:27 +0000

    setusercontext(): umask: Set it only once (in the common case)
    
    Simplify the code and make it more coherent (umask was the only context
    setting not modified by setlogincontext() directly).
    
    Preserve the current behavior of not changing the umask if none is
    specified in the login class capabilities database, but without the
    superfluous umask() dance.  (The only exception to this is that
    a special value no user is likely to input in the database now stands
    for no specification.)
    
    If some user has a 'umask' override in its '~/.login_conf', the umask
    will still be set twice as before (as is the case for all other context
    settings overriden in '~/.login_conf').
    
    Log a warning in case of an invalid umask specification.
    
    This change makes it apparent that the value of LOGIN_DEFUMASK doesn't
    matter.  It will be removed in a subsequent commit.
    
    PR:                     271747
    Reviewed by:            emaste, kib (earlier version)
    Approved by:            emaste
    MFC after:              3 days
    Sponsored by:           Kumacom SAS
    Differential Revision:  https://reviews.freebsd.org/D40344
    
    (cherry picked from commit e99c28e93bd4d04ff877459734e9ce06ad2335a7)
    
    Approved by:            markj (mentor)
---
 lib/libutil/login_class.c | 45 +++++++++++++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 14 deletions(-)

diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c
index 1036e9f9208c..2b85425d8d8e 100644
--- a/lib/libutil/login_class.c
+++ b/lib/libutil/login_class.c
@@ -38,6 +38,7 @@
 #include <login_cap.h>
 #include <paths.h>
 #include <pwd.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -385,17 +386,40 @@ setclasscontext(const char *classname, unsigned int flags)
  * Private function which takes care of processing
  */
 
-static mode_t
-setlogincontext(login_cap_t *lc, const struct passwd *pwd,
-		mode_t mymask, unsigned long flags)
+static void
+setlogincontext(login_cap_t *lc, const struct passwd *pwd, unsigned long flags)
 {
     if (lc) {
 	/* Set resources */
 	if (flags & LOGIN_SETRESOURCES)
 	    setclassresources(lc);
 	/* See if there's a umask override */
-	if (flags & LOGIN_SETUMASK)
-	    mymask = (mode_t)login_getcapnum(lc, "umask", mymask, mymask);
+	if (flags & LOGIN_SETUMASK) {
+	    /*
+	     * Make it unlikely that someone would input our default sentinel
+	     * indicating no specification.
+	     */
+	    const rlim_t def_val = INT64_MIN + 1, err_val = INT64_MIN;
+	    const rlim_t val = login_getcapnum(lc, "umask", def_val, err_val);
+
+	    if (val != def_val) {
+		if (val < 0 || val > UINT16_MAX) {
+		    /* We get here also on 'err_val'. */
+		    syslog(LOG_WARNING,
+			"%s%s%sLogin class '%s': "
+			"Invalid umask specification: '%s'",
+			pwd ? "Login '" : "",
+			pwd ? pwd->pw_name : "",
+			pwd ? "': " : "",
+			lc->lc_class,
+			login_getcapstr(lc, "umask", "", ""));
+		} else {
+		    const mode_t mode = val;
+
+		    umask(mode);
+		}
+	    }
+	}
 	/* Set paths */
 	if (flags & LOGIN_SETPATH)
 	    setclassenvironment(lc, pwd, 1);
@@ -406,7 +430,6 @@ setlogincontext(login_cap_t *lc, const struct passwd *pwd,
 	if (flags & LOGIN_SETCPUMASK)
 	    setclasscpumask(lc);
     }
-    return (mymask);
 }
 
 
@@ -429,7 +452,6 @@ int
 setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned int flags)
 {
     rlim_t	p;
-    mode_t	mymask;
     login_cap_t *llc = NULL;
     struct rtprio rtp;
     int error;
@@ -533,8 +555,7 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
 	}
     }
 
-    mymask = (flags & LOGIN_SETUMASK) ? umask(LOGIN_DEFUMASK) : 0;
-    mymask = setlogincontext(lc, pwd, mymask, flags);
+    setlogincontext(lc, pwd, flags);
     login_close(llc);
 
     /* This needs to be done after anything that needs root privs */
@@ -547,13 +568,9 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
      * Now, we repeat some of the above for the user's private entries
      */
     if (geteuid() == uid && (lc = login_getuserclass(pwd)) != NULL) {
-	mymask = setlogincontext(lc, pwd, mymask, flags);
+	setlogincontext(lc, pwd, flags);
 	login_close(lc);
     }
 
-    /* Finally, set any umask we've found */
-    if (flags & LOGIN_SETUMASK)
-	umask(mymask);
-
     return (0);
 }