git: 1501ecebf5af - stable/13 - comsat: Improve use of setuid()

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Tue, 05 Aug 2025 11:52:48 UTC
The branch stable/13 has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=1501ecebf5af7b47fde0020b888cfb4e4df1074e

commit 1501ecebf5af7b47fde0020b888cfb4e4df1074e
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2024-11-27 20:36:46 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2025-08-05 11:52:26 +0000

    comsat: Improve use of setuid()
    
    Just return from jkfprintf if either (a) user lookup fails (that is,
    getpwnam fails) or (b) setuid() to the user's uid fails.  If comsat is
    invoked from inetd using the default of tty:tty we will now return due
    to setuid() failing rather than fopen() failing.
    
    PR:             270404
    Reviewed by:    kevans
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D47823
    
    (cherry picked from commit 062b69ba045dc0fef3d9b8d73365d2798c05a480)
    
    comsat: Use initgroups and setgid not just setuid
    
    PR:             270404
    Reviewed by:    jlduran
    Obtained from:  NetBSD
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D47828
    
    (cherry picked from commit d4dd9e22c13896e6b5e2a6fc78dad4f8496cc14d)
    
    comsat: move uid/gid setting earlier
    
    It's good to reduce privilege as early as possible.
    
    Suggested by:   jlduran
    Reviewed by:    jlduran
    Obtained from:  NetBSD
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D47869
    
    (cherry picked from commit 91629228e3df14997df12ffc6e7be6b9964e5463)
---
 libexec/comsat/comsat.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/libexec/comsat/comsat.c b/libexec/comsat/comsat.c
index 138881db9e4a..2358336be61a 100644
--- a/libexec/comsat/comsat.c
+++ b/libexec/comsat/comsat.c
@@ -71,7 +71,7 @@ static int	debug = 0;
 
 static char	hostname[MAXHOSTNAMELEN];
 
-static void	jkfprintf(FILE *, char[], char[], off_t);
+static void	jkfprintf(FILE *, char[], off_t);
 static void	mailfor(char *);
 static void	notify(struct utmpx *, char[], off_t, int);
 static void	reapchildren(int);
@@ -159,6 +159,7 @@ notify(struct utmpx *utp, char file[], off_t offset, int folder)
 	FILE *tp;
 	struct stat stb;
 	struct termios tio;
+	struct passwd *p;
 	char tty[20];
 	const char *s = utp->ut_line;
 
@@ -192,6 +193,14 @@ notify(struct utmpx *utp, char file[], off_t offset, int folder)
 	}
 	(void)tcgetattr(fileno(tp), &tio);
 	cr = ((tio.c_oflag & (OPOST|ONLCR)) == (OPOST|ONLCR)) ?  "\n" : "\n\r";
+
+	/* Set uid/gid/groups to user's in case mail drop is on nfs */
+	if ((p = getpwnam(utp->ut_user)) == NULL ||
+	    initgroups(p->pw_name, p->pw_gid) == -1 ||
+	    setgid(p->pw_gid) == -1 ||
+	    setuid(p->pw_uid) == -1)
+		return;
+
 	switch (stb.st_mode & (S_IXUSR | S_IXGRP)) {
 	case S_IXUSR:
 	case (S_IXUSR | S_IXGRP):
@@ -200,7 +209,7 @@ notify(struct utmpx *utp, char file[], off_t offset, int folder)
 		    cr, utp->ut_user, (int)sizeof(hostname), hostname,
 		    folder ? cr : "", folder ? "to " : "", folder ? file : "",
 		    cr, cr);
-		jkfprintf(tp, utp->ut_user, file, offset);
+		jkfprintf(tp, file, offset);
 		break;
 	case S_IXGRP:
 		(void)fprintf(tp, "\007");
@@ -216,18 +225,13 @@ notify(struct utmpx *utp, char file[], off_t offset, int folder)
 }
 
 static void
-jkfprintf(FILE *tp, char user[], char file[], off_t offset)
+jkfprintf(FILE *tp, char file[], off_t offset)
 {
 	unsigned char *cp, ch;
 	FILE *fi;
 	int linecnt, charcnt, inheader;
-	struct passwd *p;
 	unsigned char line[BUFSIZ];
 
-	/* Set effective uid to user in case mail drop is on nfs */
-	if ((p = getpwnam(user)) != NULL)
-		(void) setuid(p->pw_uid);
-
 	if ((fi = fopen(file, "r")) == NULL)
 		return;