tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

'syslogd -u' and pidfile creation



Hello,

20 years ago, I filed bin/27309.  In short, if you use
'syslogd -u user', then syslogd can't create a pidfile
because that is done post-setuid.

My suggested fix (diff attached) is to create the
pidfile and chown it before changing UIDs.  The
subsequent pidfile(3) call will happily take over the
existing file.

One thing to note is that upon termination, the
pidfile will remain (albeit truncated), because the
unprivileged user does not have write permissions on
/var/run.  This shouldn't be a problem: upon start,
pidfile(3) does the right thing in the presence of an
empty existing file.

Does that seem reasonable?

-Jan
Index: syslogd.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.145
diff -u -p -b -u -r1.145 syslogd.c
--- syslogd.c	8 Nov 2024 02:23:54 -0000	1.145
+++ syslogd.c	8 Nov 2024 15:25:47 -0000
@@ -316,6 +316,7 @@ main(int argc, char *argv[])
 	struct group   *gr;
 	struct passwd  *pw;
 	unsigned long l;
+	char pfpath[PATH_MAX];
 
 	/* should we set LC_TIME="C" to ensure correct timestamps&parsing? */
 	(void)setlocale(LC_ALL, "");
@@ -564,6 +565,33 @@ getgroup:
 	    LOG_NFACILITIES, IETF_NUM_PRIVALUES>>3);
 #endif
 
+#ifdef __NetBSD_Version__
+	if ((uid != 0) || (gid != 0)) {
+		/* Create the pidfile here so we can chown it to the target
+		 * user/group and possibly report any error before daemonizing.
+		 * We then call pidfile(3) again to write the actual
+		 * daemon pid below.
+		 *
+		 * Note: this will likely leave the truncated pidfile in
+		 * place upon exit, since the effective user is unlikely
+		 * to have write permissions to _PATH_VARRUN. */
+		if (pidfile(NULL)) {
+			logerror("Failed to create pidfile");
+			die(0, 0, NULL);
+		}
+		j = sizeof(pfpath);
+		if (snprintf(pfpath, l, "%s%s.pid",
+					_PATH_VARRUN, getprogname()) >= j) {
+			logerror("Pidfile path `%s' too long.", pfpath);
+			die(0, 0, NULL);
+		}
+		if (chown(pfpath, uid, gid) < 0) {
+			logerror("Failed to chown pidfile `%s` to `%d:%d`", pfpath, uid, gid);
+			die(0, 0, NULL);
+		}
+	}
+#endif /* __NetBSD_Version__ */
+
 	/*
 	 * All files are open, we can drop privileges and chroot.
 	 */


Home | Main Index | Thread Index | Old Index