Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
Re: syslogd separate parent program
To:
Theo de Raadt <deraadt@openbsd.org>
Cc:
tech@openbsd.org
Date:
Mon, 8 Jun 2026 14:46:06 +0200

Download raw body.

Thread
  • renaud@openbsd.org:

    syslogd separate parent program

  • On Sun, Jun 07, 2026 at 10:47:59AM -0600, Theo de Raadt wrote:
    > Theo Buehler <tb@theobuehler.org> wrote:
    > 
    > > On Sun, Jun 07, 2026 at 10:41:11AM -0600, Theo de Raadt wrote:
    > > > Theo de Raadt <deraadt@openbsd.org> wrote:
    > > > 
    > > > > I am happy with one directory make multiple PROG using PROGS=
    > > > 
    > > >   ^^^^^ I am *NOT* happy ...
    > > 
    > > usr.sbin/smtpd/mail/Makefile uses this since 2018.
    > 
    > That is doing a lot less.  It compiles each of the PROGS from a
    > single .c file
    > 
    > It uses none of the _ features that this new proposal uses.
    > 
    > This new proposal will build one .o file, which is used for two build
    > products.  I suspect an #if statement can easily create problems.
    > 
    > Anyways, I think I can confidently predict using more of this will break
    > quickly, and I dislike this feature of bsd.prog.mk and don't think we
    > should be doing this.
    
    Now with Makefile in syslogd and parent subdir.
    
    ok?
    
    bluhm
    
    Index: usr.sbin/syslogd/Makefile
    ===================================================================
    RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/Makefile,v
    diff -u -p -r1.9 Makefile
    --- usr.sbin/syslogd/Makefile	13 Jan 2022 10:34:07 -0000	1.9
    +++ usr.sbin/syslogd/Makefile	8 Jun 2026 12:18:28 -0000
    @@ -1,10 +1,7 @@
    -#	$OpenBSD: Makefile,v 1.9 2022/01/13 10:34:07 martijn Exp $
    +#	$OpenBSD$
     
    -PROG=	syslogd
    -SRCS=	evbuffer_tls.c log.c parsemsg.c privsep.c privsep_fdpass.c ringbuf.c \
    -	syslogd.c ttymsg.c
    -MAN=	syslogd.8 syslog.conf.5
    -LDADD=	-levent -ltls -lssl -lcrypto
    -DPADD=	${LIBEVENT} ${LIBTLS} ${LIBSSL} ${LIBCRYPTO}
    +.include <bsd.own.mk>
     
    -.include <bsd.prog.mk>
    +SUBDIR=	syslogd parent
    +
    +.include <bsd.subdir.mk>
    Index: usr.sbin/syslogd/Makefile.inc
    ===================================================================
    RCS file: usr.sbin/syslogd/Makefile.inc
    diff -N usr.sbin/syslogd/Makefile.inc
    --- /dev/null	1 Jan 1970 00:00:00 -0000
    +++ usr.sbin/syslogd/Makefile.inc	8 Jun 2026 12:24:10 -0000
    @@ -0,0 +1,4 @@
    +#	$OpenBSD$
    +
    +BINDIR?=	/usr/sbin
    +COPTS+=		-Werror-implicit-function-declaration
    Index: usr.sbin/syslogd/parent.c
    ===================================================================
    RCS file: usr.sbin/syslogd/parent.c
    diff -N usr.sbin/syslogd/parent.c
    --- /dev/null	1 Jan 1970 00:00:00 -0000
    +++ usr.sbin/syslogd/parent.c	7 Jun 2026 16:13:52 -0000
    @@ -0,0 +1,136 @@
    +/*	$OpenBSD$	*/
    +
    +/*
    + * Copyright (c) 2026 Alexander Bluhm <bluhm@openbsd.org>
    + *
    + * Permission to use, copy, modify, and distribute this software for any
    + * purpose with or without fee is hereby granted, provided that the above
    + * copyright notice and this permission notice appear in all copies.
    + *
    + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    + */
    +
    +#include <err.h>
    +#include <errno.h>
    +#include <limits.h>
    +#include <paths.h>
    +#include <stdio.h>
    +#include <stdlib.h>
    +#include <syslog.h>
    +#include <unistd.h>
    +
    +#include "log.h"
    +#include "syslogd.h"
    +
    +static int	 verbose;
    +static char	*debug_ebuf;
    +
    +/* parent process is re-execed with reduced arguments, others ignored */
    +
    +static __dead void
    +usage(void)
    +{
    +	(void)fprintf(stderr,
    +	    "usage: syslogd-parent [-dn] [-f config_file] -P child_pid\n");
    +	exit(1);
    +}
    +
    +int
    +main(int argc, char *argv[])
    +{
    +	char *ConfFile = _PATH_LOGCONF;
    +	int Debug = 0;
    +	int PrivChild = 0;
    +	int NoDNS = 0;
    +	const char *errstr;
    +	int ch;
    +
    +	while ((ch = getopt(argc, argv,
    +	    "46a:C:c:dFf:hK:k:m:nP:p:rS:s:T:U:uVZ")) != -1) {
    +		switch (ch) {
    +		case '4':
    +		case '6':
    +		case 'a':
    +		case 'C':
    +		case 'c':
    +		case 'd':		/* debug */
    +			Debug++;
    +			break;
    +		case 'F':
    +			break;
    +		case 'f':		/* configuration file */
    +			ConfFile = optarg;
    +			break;
    +		case 'h':
    +		case 'K':
    +		case 'k':
    +		case 'm':
    +			break;
    +		case 'n':		/* don't do DNS lookups */
    +			NoDNS = 1;
    +			break;
    +		case 'P':		/* used internally, exec the parent */
    +			PrivChild = strtonum(optarg, 2, INT_MAX, &errstr);
    +			if (errstr)
    +				errx(1, "priv child %s: %s", errstr, optarg);
    +			break;
    +		case 'p':
    +		case 'r':
    +		case 'S':
    +		case 's':
    +		case 'T':
    +		case 'U':
    +		case 'u':
    +		case 'V':
    +		case 'Z':
    +			break;
    +		default:
    +			usage();
    +		}
    +	}
    +	if (argc != optind)
    +		usage();
    +	if (PrivChild < 2)
    +		errx(1, "parent requires -P child_pid");
    +
    +	log_init(Debug, LOG_SYSLOG);
    +	priv_exec(ConfFile, NoDNS, PrivChild, argc, argv);
    +
    +	/* NOTREACHED */
    +	return 1;
    +}
    +
    +void
    +log_init(int n_debug, int fac)
    +{
    +	verbose = n_debug;
    +
    +	if (debug_ebuf == NULL)
    +		if ((debug_ebuf = malloc(ERRBUFSIZE)) == NULL)
    +		    err(1, "allocate debug buffer");
    +	debug_ebuf[0] = '\0';
    +}
    +
    +void
    +log_debug(const char *emsg, ...)
    +{
    +	va_list ap;
    +	int saved_errno;
    +
    +	if (verbose) {
    +		saved_errno = errno;
    +		va_start(ap, emsg);
    +		vsnprintf(debug_ebuf, ERRBUFSIZE, emsg, ap);
    +		fprintf(stderr, "[priv]: %s\n", debug_ebuf);
    +		fflush(stderr);
    +		va_end(ap);
    +		errno = saved_errno;
    +	}
    +	debug_ebuf[0] = '\0';
    +}
    Index: usr.sbin/syslogd/privsep.c
    ===================================================================
    RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/privsep.c,v
    diff -u -p -r1.77 privsep.c
    --- usr.sbin/syslogd/privsep.c	12 Oct 2023 22:36:54 -0000	1.77
    +++ usr.sbin/syslogd/privsep.c	7 Jun 2026 16:14:05 -0000
    @@ -96,10 +96,10 @@ static int  may_read(int, void *, size_t
     static struct passwd *pw;
     
     void
    -priv_init(int lockfd, int nullfd, int argc, char *argv[])
    +priv_init(int debug, int lockfd, int nullfd, int argc, char *argv[])
     {
     	int i, socks[2];
    -	char *execpath, childnum[11], **privargv;
    +	char childnum[11], **privargv;
     
     	/* Create sockets */
     	if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1)
    @@ -132,14 +132,10 @@ priv_init(int lockfd, int nullfd, int ar
     	}
     	close(socks[1]);
     
    -	if (strchr(argv[0], '/') == NULL)
    -		execpath = argv[0];
    -	else if ((execpath = realpath(argv[0], NULL)) == NULL)
    -		err(1, "realpath %s", argv[0]);
     	if (chdir("/") != 0)
     		err(1, "chdir /");
     
    -	if (!Debug) {
    +	if (!debug) {
     		close(lockfd);
     		dup2(nullfd, STDIN_FILENO);
     		dup2(nullfd, STDOUT_FILENO);
    @@ -156,18 +152,18 @@ priv_init(int lockfd, int nullfd, int ar
     	snprintf(childnum, sizeof(childnum), "%d", child_pid);
     	if ((privargv = reallocarray(NULL, argc + 3, sizeof(char *))) == NULL)
     		err(1, "alloc priv argv failed");
    -	privargv[0] = execpath;
    +	privargv[0] = "/usr/sbin/syslogd-parent";
     	for (i = 1; i < argc; i++)
     		privargv[i] = argv[i];
     	privargv[i++] = "-P";
     	privargv[i++] = childnum;
     	privargv[i++] = NULL;
    -	execvp(privargv[0], privargv);
    +	execv(privargv[0], privargv);
     	err(1, "exec priv '%s' failed", privargv[0]);
     }
     
     __dead void
    -priv_exec(char *conf, int numeric, int child, int argc, char *argv[])
    +priv_exec(const char *conf, int numeric, int child, int argc, char *argv[])
     {
     	int i, fd, sock, cmd, addr_len, result, restart;
     	size_t path_len, protoname_len, hostname_len, servname_len;
    @@ -235,7 +231,7 @@ priv_exec(char *conf, int numeric, int c
     	sigaction(SIGCHLD, &sa, NULL);
     
     	setproctitle("[priv]");
    -	log_debug("[priv]: fork+exec done");
    +	log_debug("fork+exec done");
     
     	sigemptyset(&sigmask);
     	if (sigprocmask(SIG_SETMASK, &sigmask, NULL) == -1)
    @@ -253,7 +249,7 @@ priv_exec(char *conf, int numeric, int c
     			break;
     		switch (cmd) {
     		case PRIV_OPEN_TTY:
    -			log_debug("[priv]: msg PRIV_OPEN_TTY received");
    +			log_debug("msg PRIV_OPEN_TTY received");
     			/* Expecting: length, path */
     			must_read(sock, &path_len, sizeof(size_t));
     			if (path_len == 0 || path_len > sizeof(path))
    @@ -271,7 +267,7 @@ priv_exec(char *conf, int numeric, int c
     
     		case PRIV_OPEN_LOG:
     		case PRIV_OPEN_PIPE:
    -			log_debug("[priv]: msg PRIV_OPEN_%s received",
    +			log_debug("msg PRIV_OPEN_%s received",
     			    cmd == PRIV_OPEN_PIPE ? "PIPE" : "LOG");
     			/* Expecting: length, path */
     			must_read(sock, &path_len, sizeof(size_t));
    @@ -296,7 +292,7 @@ priv_exec(char *conf, int numeric, int c
     			break;
     
     		case PRIV_OPEN_UTMP:
    -			log_debug("[priv]: msg PRIV_OPEN_UTMP received");
    +			log_debug("msg PRIV_OPEN_UTMP received");
     			fd = open(_PATH_UTMP, O_RDONLY|O_NONBLOCK);
     			send_fd(sock, fd);
     			if (fd == -1)
    @@ -306,7 +302,7 @@ priv_exec(char *conf, int numeric, int c
     			break;
     
     		case PRIV_OPEN_CONFIG:
    -			log_debug("[priv]: msg PRIV_OPEN_CONFIG received");
    +			log_debug("msg PRIV_OPEN_CONFIG received");
     			stat(conf, &cf_info);
     			fd = open(conf, O_RDONLY|O_NONBLOCK);
     			send_fd(sock, fd);
    @@ -317,7 +313,7 @@ priv_exec(char *conf, int numeric, int c
     			break;
     
     		case PRIV_CONFIG_MODIFIED:
    -			log_debug("[priv]: msg PRIV_CONFIG_MODIFIED received");
    +			log_debug("msg PRIV_CONFIG_MODIFIED received");
     			if (stat(conf, &cf_stat) == -1 ||
     			    timespeccmp(&cf_info.st_mtim,
     			    &cf_stat.st_mtim, <) ||
    @@ -335,13 +331,13 @@ priv_exec(char *conf, int numeric, int c
     			if (pledge("stdio rpath wpath cpath dns sendfd id proc exec",
     			    NULL) == -1)
     				err(1, "pledge done config");
    -			log_debug("[priv]: msg PRIV_DONE_CONFIG_PARSE "
    +			log_debug("msg PRIV_DONE_CONFIG_PARSE "
     			    "received");
     			increase_state(STATE_RUNNING);
     			break;
     
     		case PRIV_GETADDRINFO:
    -			log_debug("[priv]: msg PRIV_GETADDRINFO received");
    +			log_debug("msg PRIV_GETADDRINFO received");
     			/* Expecting: len, proto, len, host, len, serv */
     			must_read(sock, &protoname_len, sizeof(size_t));
     			if (protoname_len == 0 ||
    @@ -407,7 +403,7 @@ priv_exec(char *conf, int numeric, int c
     			break;
     
     		case PRIV_GETNAMEINFO:
    -			log_debug("[priv]: msg PRIV_GETNAMEINFO received");
    +			log_debug("msg PRIV_GETNAMEINFO received");
     			if (numeric)
     				errx(1, "rejected attempt to getnameinfo");
     			/* Expecting: length, sockaddr */
    @@ -442,7 +438,8 @@ priv_exec(char *conf, int numeric, int c
     		sigaddset(&sigmask, SIGHUP);
     		if (sigprocmask(SIG_SETMASK, &sigmask, NULL) == -1)
     			err(1, "sigprocmask exec");
    -		execvp(argv[0], argv);
    +		argv[0] = "/usr/sbin/syslogd";
    +		execv(argv[0], argv);
     		err(1, "exec restart '%s' failed", argv[0]);
     	}
     	unlink(_PATH_LOGPID);
    Index: usr.sbin/syslogd/syslogd.c
    ===================================================================
    RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v
    diff -u -p -r1.287 syslogd.c
    --- usr.sbin/syslogd/syslogd.c	26 Jun 2025 19:10:13 -0000	1.287
    +++ usr.sbin/syslogd/syslogd.c	7 Jun 2026 16:14:05 -0000
    @@ -121,7 +121,7 @@
     #include "evbuffer_tls.h"
     #include "parsemsg.h"
     
    -char *ConfFile = _PATH_LOGCONF;
    +const char *ConfFile = _PATH_LOGCONF;
     const char ctty[] = _PATH_CONSOLE;
     
     #define MAXUNAMES	20	/* maximum number of user names */
    @@ -226,7 +226,6 @@ int	Initialized = 0;	/* set when we have
     
     int	MarkInterval = 20 * 60;	/* interval between marks in seconds */
     int	MarkSeq = 0;		/* mark sequence number */
    -int	PrivChild = 0;		/* Exec the privileged parent process */
     int	Repeat = 0;		/* 0 msg repeated, 1 in files only, 2 never */
     int	SecureMode = 1;		/* when true, speak only unix domain socks */
     int	NoDNS = 0;		/* when true, refrain from doing DNS lookups */
    @@ -350,7 +349,6 @@ struct filed *find_dup(struct filed *);
     void	printline(char *, char *);
     void	printsys(char *);
     void	current_time(char *);
    -void	usage(void);
     void	wallmsg(struct filed *, struct iovec *);
     int	loghost_parse(char *, char **, char **, char **);
     int	getmsgbufsize(void);
    @@ -363,6 +361,17 @@ void	set_sockbuf(int);
     void	set_keepalive(int);
     void	tailify_replytext(char *, int);
     
    +static __dead void
    +usage(void)
    +{
    +	(void)fprintf(stderr,
    +	    "usage: syslogd [-46dFhnruVZ] [-a path] [-C CAfile]\n"
    +	    "\t[-c cert_file] [-f config_file] [-K CAfile] [-k key_file]\n"
    +	    "\t[-m mark_interval] [-p log_socket] [-S listen_address]\n"
    +	    "\t[-s reporting_socket] [-T listen_address] [-U bind_address]\n");
    +	exit(1);
    +}
    +
     int
     main(int argc, char *argv[])
     {
    @@ -399,7 +408,7 @@ main(int argc, char *argv[])
     	nbind = nlisten = ntls = 0;
     
     	while ((ch = getopt(argc, argv,
    -	    "46a:C:c:dFf:hK:k:m:nP:p:rS:s:T:U:uVZ")) != -1) {
    +	    "46a:C:c:dFf:hK:k:m:np:rS:s:T:U:uVZ")) != -1) {
     		switch (ch) {
     		case '4':		/* disable IPv6 */
     			Family = PF_INET;
    @@ -446,11 +455,6 @@ main(int argc, char *argv[])
     		case 'n':		/* don't do DNS lookups */
     			NoDNS = 1;
     			break;
    -		case 'P':		/* used internally, exec the parent */
    -			PrivChild = strtonum(optarg, 2, INT_MAX, &errstr);
    -			if (errstr)
    -				errx(1, "priv child %s: %s", errstr, optarg);
    -			break;
     		case 'p':		/* path */
     			path_unix[0] = optarg;
     			break;
    @@ -503,9 +507,6 @@ main(int argc, char *argv[])
     				fatal("dup2 null");
     	}
     
    -	if (PrivChild > 1)
    -		priv_exec(ConfFile, NoDNS, PrivChild, argc, argv);
    -
     	consfile.f_type = F_CONSOLE;
     	(void)strlcpy(consfile.f_un.f_fname, ctty,
     	    sizeof(consfile.f_un.f_fname));
    @@ -757,7 +758,7 @@ main(int argc, char *argv[])
     	}
     
     	/* Privilege separation begins here */
    -	priv_init(lockpipe[1], nullfd, argc, argv);
    +	priv_init(Debug, lockpipe[1], nullfd, argc, argv);
     
     	if (pledge("stdio unix inet recvfd", NULL) == -1)
     		err(1, "pledge");
    @@ -1662,18 +1663,6 @@ tcpbuf_countmsg(struct bufferevent *bufe
     			i++;
     	}
     	return (i);
    -}
    -
    -void
    -usage(void)
    -{
    -
    -	(void)fprintf(stderr,
    -	    "usage: syslogd [-46dFhnruVZ] [-a path] [-C CAfile]\n"
    -	    "\t[-c cert_file] [-f config_file] [-K CAfile] [-k key_file]\n"
    -	    "\t[-m mark_interval] [-p log_socket] [-S listen_address]\n"
    -	    "\t[-s reporting_socket] [-T listen_address] [-U bind_address]\n");
    -	exit(1);
     }
     
     /*
    Index: usr.sbin/syslogd/syslogd.h
    ===================================================================
    RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.h,v
    diff -u -p -r1.37 syslogd.h
    --- usr.sbin/syslogd/syslogd.h	12 Oct 2023 22:36:54 -0000	1.37
    +++ usr.sbin/syslogd/syslogd.h	7 Jun 2026 16:14:05 -0000
    @@ -26,8 +26,8 @@
     extern int	ZuluTime;
     
     /* Privilege separation */
    -void  priv_init(int, int, int, char **);
    -__dead void priv_exec(char *, int, int, int, char **);
    +void  priv_init(int, int, int, int, char **);
    +__dead void priv_exec(const char *, int, int, int, char **);
     int   priv_open_tty(const char *);
     int   priv_open_log(const char *);
     FILE *priv_open_utmp(void);
    @@ -52,7 +52,6 @@ int  receive_fd(int);
     #define ERRBUFSIZE	256
     void vlogmsg(int pri, const char *, const char *, va_list);
     __dead void die(int);
    -extern int Debug;
     
     struct ringbuf {
     	char *buf;
    Index: usr.sbin/syslogd/parent/Makefile
    ===================================================================
    RCS file: usr.sbin/syslogd/parent/Makefile
    diff -N usr.sbin/syslogd/parent/Makefile
    --- /dev/null	1 Jan 1970 00:00:00 -0000
    +++ usr.sbin/syslogd/parent/Makefile	8 Jun 2026 12:21:21 -0000
    @@ -0,0 +1,9 @@
    +#	$OpenBSD$
    +
    +.PATH:	${.CURDIR}/..
    +
    +PROG=	syslogd-parent
    +SRCS=	parent.c privsep.c privsep_fdpass.c
    +NOMAN=	Yes
    +
    +.include <bsd.prog.mk>
    Index: usr.sbin/syslogd/syslogd/Makefile
    ===================================================================
    RCS file: usr.sbin/syslogd/syslogd/Makefile
    diff -N usr.sbin/syslogd/syslogd/Makefile
    --- /dev/null	1 Jan 1970 00:00:00 -0000
    +++ usr.sbin/syslogd/syslogd/Makefile	8 Jun 2026 12:21:34 -0000
    @@ -0,0 +1,12 @@
    +#	$OpenBSD$
    +
    +.PATH:	${.CURDIR}/..
    +
    +PROG=	syslogd
    +SRCS=	evbuffer_tls.c log.c parsemsg.c privsep.c \
    +	privsep_fdpass.c ringbuf.c syslogd.c ttymsg.c
    +LDADD=	-levent -ltls -lssl -lcrypto
    +DPADD=	${LIBEVENT} ${LIBTLS} ${LIBSSL} ${LIBCRYPTO}
    +MAN=	syslogd.8 syslog.conf.5
    +
    +.include <bsd.prog.mk>
    Index: etc/rc.d/syslogd
    ===================================================================
    RCS file: /data/mirror/openbsd/cvs/src/etc/rc.d/syslogd,v
    diff -u -p -r1.5 syslogd
    --- etc/rc.d/syslogd	11 Jan 2018 19:52:12 -0000	1.5
    +++ etc/rc.d/syslogd	7 Jun 2026 08:58:14 -0000
    @@ -6,7 +6,7 @@ daemon="/usr/sbin/syslogd"
     
     . /etc/rc.d/rc.subr
     
    -pexp="syslogd: \[priv\]"
    +pexp="syslogd-parent: \[priv\]"
     
     rc_pre() {
     	rm -f /dev/log
    
    
  • renaud@openbsd.org:

    syslogd separate parent program