changeset 4953:109206a59cc6 draft

privsep: Delay control startup after starting privsep This means we don't need to close it for other processes. Add ps_init so that we can change directory permissions before starting privsep itself.
author Roy Marples <roy@marples.name>
date Thu, 09 Jan 2020 15:39:18 +0000
parents e77138b6ec3b
children 52e1039652ea
files src/control.c src/control.h src/dhcpcd.c src/privsep.c src/privsep.h
diffstat 5 files changed, 71 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/src/control.c	Thu Jan 09 14:48:56 2020 +0000
+++ b/src/control.c	Thu Jan 09 15:39:18 2020 +0000
@@ -269,25 +269,22 @@
 	int retval = 0;
 	struct fd_list *l;
 
-	if (ctx->options & DHCPCD_FORKED)
-		goto freeit;
-
-	if (ctx->control_fd == -1)
-		return 0;
-
-	control_close(ctx);
-	if (unlink(ctx->control_sock) == -1)
-		retval = -1;
+	if (ctx->control_fd != -1) {
+		eloop_event_delete(ctx->eloop, ctx->control_fd);
+		close(ctx->control_fd);
+		ctx->control_fd = -1;
+		if (unlink(ctx->control_sock) == -1 && errno != ENOENT)
+			retval = -1;
+	}
 
 	if (ctx->control_unpriv_fd != -1) {
 		eloop_event_delete(ctx->eloop, ctx->control_unpriv_fd);
 		close(ctx->control_unpriv_fd);
 		ctx->control_unpriv_fd = -1;
-		if (unlink(UNPRIVSOCKET) == -1)
+		if (unlink(UNPRIVSOCKET) == -1 && errno != ENOENT)
 			retval = -1;
 	}
 
-freeit:
 	while ((l = TAILQ_FIRST(&ctx->control_fds))) {
 		TAILQ_REMOVE(&ctx->control_fds, l, next);
 		eloop_event_delete(ctx->eloop, l->fd);
@@ -448,14 +445,3 @@
 	eloop_event_add_w(fd->ctx->eloop, fd->fd, control_writeone, fd);
 	return 0;
 }
-
-void
-control_close(struct dhcpcd_ctx *ctx)
-{
-
-	if (ctx->control_fd != -1) {
-		eloop_event_delete(ctx->eloop, ctx->control_fd);
-		close(ctx->control_fd);
-		ctx->control_fd = -1;
-	}
-}
--- a/src/control.h	Thu Jan 09 14:48:56 2020 +0000
+++ b/src/control.h	Thu Jan 09 15:39:18 2020 +0000
@@ -71,6 +71,5 @@
 int control_open(const char *);
 ssize_t control_send(struct dhcpcd_ctx *, int, char * const *);
 int control_queue(struct fd_list *, void *, size_t, bool);
-void control_close(struct dhcpcd_ctx *ctx);
 
 #endif
--- a/src/dhcpcd.c	Thu Jan 09 14:48:56 2020 +0000
+++ b/src/dhcpcd.c	Thu Jan 09 15:39:18 2020 +0000
@@ -1917,7 +1917,6 @@
 		if (ctx.control_fd != -1) {
 			loginfox("sending commands to master dhcpcd process");
 			len = control_send(&ctx, argc, argv);
-			control_close(&ctx);
 			if (len > 0) {
 				logdebugx("send OK");
 				goto exit_success;
@@ -1989,6 +1988,13 @@
 
 	logdebugx(PACKAGE "-" VERSION " starting");
 
+#ifdef PRIVSEP
+	if (ps_init(&ctx) == -1 && errno != 0) {
+		logerr("ps_init");
+		goto exit_failure;
+	}
+#endif
+
 #ifdef USE_SIGNALS
 	if (pipe(sigpipe) == -1) {
 		logerr("pipe");
@@ -2038,6 +2044,21 @@
 	}
 #endif
 
+#ifdef BSD
+	/* Disable the kernel RTADV sysctl as early as possible. */
+	if (ctx.options & DHCPCD_IPV6 && ctx.options & DHCPCD_IPV6RS)
+		if_disable_rtadv();
+#endif
+
+#ifdef PRIVSEP
+	if (ctx.options & DHCPCD_PRIVSEP && ps_start(&ctx) == -1) {
+		logerr("ps_start");
+		goto exit_failure;
+	}
+	if (ctx.options & DHCPCD_FORKED)
+		goto run_loop;
+#endif
+
 	if (control_start(&ctx,
 	    ctx.options & DHCPCD_MASTER ? NULL : argv[optind]) == -1)
 	{
@@ -2050,21 +2071,6 @@
 	    ctx.options & DHCPCD_IPV4 ? " [ip4]" : "",
 	    ctx.options & DHCPCD_IPV6 ? " [ip6]" : "");
 
-#ifdef BSD
-	/* Disable the kernel RTADV sysctl as early as possible. */
-	if (ctx.options & DHCPCD_IPV6 && ctx.options & DHCPCD_IPV6RS)
-		if_disable_rtadv();
-#endif
-
-#ifdef PRIVSEP
-	if (ps_start(&ctx) == -1 && errno != 0) {
-		logerr("ps_start");
-		goto exit_failure;
-	}
-	if (ctx.options & DHCPCD_FORKED)
-		goto run_loop;
-#endif
-
 	if (if_opensockets(&ctx) == -1) {
 		logerr("%s: if_opensockets", __func__);
 		goto exit_failure;
--- a/src/privsep.c	Thu Jan 09 14:48:56 2020 +0000
+++ b/src/privsep.c	Thu Jan 09 15:39:18 2020 +0000
@@ -68,6 +68,35 @@
 #include <util.h>
 #endif
 
+int
+ps_init(struct dhcpcd_ctx *ctx)
+{
+	struct passwd *pw;
+	gid_t gid = (gid_t)-1;
+
+	errno = 0;
+	if ((pw = getpwnam(PRIVSEP_USER)) == NULL) {
+		ctx->options &= ~DHCPCD_PRIVSEP;
+		if (errno == 0) {
+			logerrx("no such user %s", PRIVSEP_USER);
+			/* Just incase logerrx caused an error... */
+			errno = 0;
+		} else
+			logerr("getpwnam");
+		return -1;
+	}
+
+
+	/* Change ownership of stuff we need to drop at exit. */
+	if (chown(ctx->pidfile, pw->pw_uid, gid) == -1)
+		logerr("chown `%s'", ctx->pidfile);
+	if (chown(DBDIR, pw->pw_uid, gid) == -1)
+		logerr("chown `%s'", DBDIR);
+	if (chown(RUNDIR, pw->pw_uid, gid) == -1)
+		logerr("chown `%s'", RUNDIR);
+	return 0;
+}
+
 pid_t
 ps_dostart(struct dhcpcd_ctx *ctx,
     pid_t *priv_pid, int *priv_fd,
@@ -80,51 +109,21 @@
 	int fd[2];
 	pid_t pid;
 
-	/* Even if we're not dropping privs, we need to ensure that the unpriv
-	 * user exists so the processes that do need it startup just fine. */
-	errno = 0;
-	if ((pw = getpwnam(PRIVSEP_USER)) == NULL) {
-		ctx->options &= ~DHCPCD_PRIVSEP;
-		if (errno == 0) {
-			if (ctx == recv_ctx) { /* Only log the once. */
+	if (flags & PSF_DROPPRIVS) {
+		errno = 0;
+		if ((pw = getpwnam(PRIVSEP_USER)) == NULL) {
+			if (errno == 0)
 				logerrx("no such user %s", PRIVSEP_USER);
-				/* Just incase logerrx caused an error... */
-				errno = 0;
-			}
-		} else
-			logerr("getpwnam");
-		return -1;
-	}
-
-	if (!(flags & PSF_DROPPRIVS)) {
+			else
+				logerr("getpwnam");
+			return -1;
+		}
+	} else
 		pw = NULL;
-		goto create_sp;
-	}
 
-	if (priv_pid == NULL) {
-		gid_t gid = (gid_t)-1;
+	if (priv_fd == NULL)
+		goto dropprivs;
 
-		/* Main process - change ownership of stuff we need to
-		 * drop at exit. */
-		if (pw != NULL) {
-			if (chown(ctx->pidfile, pw->pw_uid, gid) == -1)
-				logerr("chown `%s'", ctx->pidfile);
-			if (chown(DBDIR, pw->pw_uid, gid) == -1)
-				logerr("chown `%s'", DBDIR);
-			if (chown(RUNDIR, pw->pw_uid, gid) == -1)
-				logerr("chown `%s'", RUNDIR);
-			if (ctx->options & DHCPCD_MASTER) {
-				if (chown(ctx->control_sock,
-				    pw->pw_uid, gid) == -1)
-					logerr("chown `%s'", ctx->control_sock);
-				if (chown(UNPRIVSOCKET, pw->pw_uid, gid) == -1)
-					logerr("chown `%s'", UNPRIVSOCKET);
-			}
-		}
-		goto dropprivs;
-	}
-
-create_sp:
 	stype = SOCK_CLOEXEC | SOCK_NONBLOCK;
 	if (socketpair(AF_UNIX, SOCK_DGRAM | stype, 0, fd) == -1) {
 		logerr("socketpair");
@@ -159,7 +158,6 @@
 		close(ctx->fork_fd);
 		ctx->fork_fd = -1;
 	}
-	control_close(ctx);
 	pidfile_clean();
 	eloop_clear(ctx->eloop);
 
--- a/src/privsep.h	Thu Jan 09 14:48:56 2020 +0000
+++ b/src/privsep.h	Thu Jan 09 15:39:18 2020 +0000
@@ -130,6 +130,7 @@
 #include "privsep-bpf.h"
 #endif
 
+int ps_init(struct dhcpcd_ctx *);
 int ps_start(struct dhcpcd_ctx *);
 int ps_stop(struct dhcpcd_ctx *);