changeset 5183:09e3f731e43e draft

privsep: Add --chroot configurable Overrides the directory to chroot to away from the privilege separation users home directory.
author Roy Marples <roy@marples.name>
date Thu, 30 Apr 2020 21:13:45 +0100
parents 72d627ef016e
children 88d5345f56ce
files Makefile.inc configure src/Makefile src/dhcpcd.8.in src/dhcpcd.c src/dhcpcd.h src/if-options.c src/if-options.h src/ipv6nd.c src/privsep-root.c src/privsep.c src/script.c
diffstat 12 files changed, 91 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.inc	Wed Apr 29 22:41:35 2020 +0100
+++ b/Makefile.inc	Thu Apr 30 21:13:45 2020 +0100
@@ -33,3 +33,4 @@
 SED_SCRIPT=		-e 's:@SCRIPT@:${SCRIPT}:g'
 SED_SYS=		-e 's:@SYSCONFDIR@:${SYSCONFDIR}:g'
 SED_DEFAULT_HOSTNAME=	-e 's:@DEFAULT_HOSTNAME@:${DEFAULT_HOSTNAME}:g'
+SED_PRIVSEP_USER=	-e 's:@PRIVSEP_USER@:${PRIVSEP_USER}:g'
--- a/configure	Wed Apr 29 22:41:35 2020 +0100
+++ b/configure	Thu Apr 30 21:13:45 2020 +0100
@@ -578,6 +578,7 @@
 	fi
 
 	echo "CPPFLAGS+=	-DPRIVSEP" >>$CONFIG_MK
+	echo "PRIVSEP_USER?=	$PRIVSEP_USER" >>$CONFIG_MK
 	echo "#ifndef PRIVSEP_USER" >>$CONFIG_H
 	echo "#define PRIVSEP_USER		 \"$PRIVSEP_USER\"" >>$CONFIG_H
 	echo "#endif" >>$CONFIG_H
--- a/src/Makefile	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/Makefile	Thu Apr 30 21:13:45 2020 +0100
@@ -42,7 +42,7 @@
 	${SED} ${SED_RUNDIR} ${SED_DBDIR} ${SED_LIBDIR} ${SED_HOOKDIR} \
 		${SED_SYS} ${SED_SCRIPT} ${SED_DATADIR} \
 		${SED_SERVICEEXISTS} ${SED_SERVICECMD} ${SED_SERVICESTATUS} \
-		${SED_STATUSARG} \
+		${SED_STATUSARG} ${SED_PRIVSEP_USER} \
 		$< > $@
 
 all: ${TOP}/config.h ${PROG} ${SCRIPTS} ${MAN5} ${MAN8}
--- a/src/dhcpcd.8.in	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/dhcpcd.8.in	Thu Apr 30 21:13:45 2020 +0100
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 28, 2020
+.Dd April 30, 2020
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -35,6 +35,7 @@
 .Op Fl 146ABbDdEGgHJKLMNPpqTV
 .Op Fl C , Fl Fl nohook Ar hook
 .Op Fl c , Fl Fl script Ar script
+.Op Fl Fl chroot Ar chroot
 .Op Fl e , Fl Fl env Ar value
 .Op Fl F , Fl Fl fqdn Ar FQDN
 .Op Fl f , Fl Fl config Ar file
@@ -262,6 +263,12 @@
 .Ar script
 instead of the default
 .Pa @SCRIPT@ .
+.It Fl Fl chroot Ar chroot
+.Xr chroot 3
+to the
+.Ar chroot
+directory rather than the privilege separation users home directory.
+The privilege sepatation user is @PRIVSEP_USER@.
 .It Fl D , Fl Fl duid
 Use a DHCP Unique Identifier.
 If a system UUID is available, that will be used to create a DUID-UUID,
--- a/src/dhcpcd.c	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/dhcpcd.c	Thu Apr 30 21:13:45 2020 +0100
@@ -1891,6 +1891,11 @@
 		case 'V':
 			i = 2;
 			break;
+#ifdef PRIVSEP
+		case O_CHROOT:
+			ctx.ps_chroot = optarg;
+			break;
+#endif
 		case '?':
 			if (ctx.options & DHCPCD_PRINT_PIDFILE)
 				continue;
--- a/src/dhcpcd.h	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/dhcpcd.h	Thu Apr 30 21:13:45 2020 +0100
@@ -192,6 +192,7 @@
 
 #ifdef PRIVSEP
 	struct passwd *ps_user;	/* struct passwd for privsep user */
+	const char *ps_chroot;
 	pid_t ps_root_pid;
 	int ps_root_fd;		/* Privileged Actioneer commands */
 	int ps_data_fd;		/* Data from root spawned processes */
--- a/src/if-options.c	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/if-options.c	Thu Apr 30 21:13:45 2020 +0100
@@ -56,58 +56,6 @@
 #include "logerr.h"
 #include "sa.h"
 
-/* These options only make sense in the config file, so don't use any
-   valid short options for them */
-#define O_BASE			MAX('z', 'Z') + 1
-#define O_ARPING		O_BASE + 1
-#define O_FALLBACK		O_BASE + 2
-#define O_DESTINATION		O_BASE + 3
-#define O_IPV6RS		O_BASE + 4
-#define O_NOIPV6RS		O_BASE + 5
-#define O_IPV6RA_FORK		O_BASE + 6
-#define O_LINK_RCVBUF		O_BASE + 7
-#define O_ANONYMOUS		O_BASE + 8
-#define O_NOALIAS		O_BASE + 9
-#define O_IA_NA			O_BASE + 10
-#define O_IA_TA			O_BASE + 11
-#define O_IA_PD			O_BASE + 12
-#define O_HOSTNAME_SHORT	O_BASE + 13
-#define O_DEV			O_BASE + 14
-#define O_NODEV			O_BASE + 15
-#define O_NOIPV4		O_BASE + 16
-#define O_NOIPV6		O_BASE + 17
-#define O_IAID			O_BASE + 18
-#define O_DEFINE		O_BASE + 19
-#define O_DEFINE6		O_BASE + 20
-#define O_EMBED			O_BASE + 21
-#define O_ENCAP			O_BASE + 22
-#define O_VENDOPT		O_BASE + 23
-#define O_VENDCLASS		O_BASE + 24
-#define O_AUTHPROTOCOL		O_BASE + 25
-#define O_AUTHTOKEN		O_BASE + 26
-#define O_AUTHNOTREQUIRED	O_BASE + 27
-#define O_NODHCP		O_BASE + 28
-#define O_NODHCP6		O_BASE + 29
-#define O_DHCP			O_BASE + 30
-#define O_DHCP6			O_BASE + 31
-#define O_IPV4			O_BASE + 32
-#define O_IPV6			O_BASE + 33
-#define O_CONTROLGRP		O_BASE + 34
-#define O_SLAAC			O_BASE + 35
-#define O_GATEWAY		O_BASE + 36
-#define O_NOUP			O_BASE + 37
-#define O_IPV6RA_AUTOCONF	O_BASE + 38
-#define O_IPV6RA_NOAUTOCONF	O_BASE + 39
-#define O_REJECT		O_BASE + 40
-#define O_BOOTP			O_BASE + 42
-#define O_DEFINEND		O_BASE + 43
-#define O_NODELAY		O_BASE + 44
-#define O_INFORM6		O_BASE + 45
-#define O_LASTLEASE_EXTEND	O_BASE + 46
-#define O_INACTIVE		O_BASE + 47
-#define	O_MUDURL		O_BASE + 48
-#define	O_MSUSERCLASS		O_BASE + 49
-
 const struct option cf_options[] = {
 	{"background",      no_argument,       NULL, 'b'},
 	{"script",          required_argument, NULL, 'c'},
@@ -211,6 +159,7 @@
 	{"inactive",        no_argument,       NULL, O_INACTIVE},
 	{"mudurl",          required_argument, NULL, O_MUDURL},
 	{"link_rcvbuf",     required_argument, NULL, O_LINK_RCVBUF},
+	{"chroot",          required_argument, NULL, O_CHROOT},
 	{NULL,              0,                 NULL, '\0'}
 };
 
@@ -712,6 +661,7 @@
 #define ARG_REQUIRED if (arg == NULL) goto arg_required
 
 	switch(opt) {
+	case O_CHROOT: /* FALLTHROUGH */
 	case 'f': /* FALLTHROUGH */
 	case 'g': /* FALLTHROUGH */
 	case 'n': /* FALLTHROUGH */
--- a/src/if-options.h	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/if-options.h	Thu Apr 30 21:13:45 2020 +0100
@@ -128,6 +128,59 @@
 #define DHCPCD_WARNINGS	(DHCPCD_CSR_WARNED | \
 		DHCPCD_ROUTER_HOST_ROUTE_WARNED)
 
+/* These options only make sense in the config file, so don't use any
+   valid short options for them */
+#define O_BASE			MAX('z', 'Z') + 1
+#define O_ARPING		O_BASE + 1
+#define O_FALLBACK		O_BASE + 2
+#define O_DESTINATION		O_BASE + 3
+#define O_IPV6RS		O_BASE + 4
+#define O_NOIPV6RS		O_BASE + 5
+#define O_IPV6RA_FORK		O_BASE + 6
+#define O_LINK_RCVBUF		O_BASE + 7
+#define O_ANONYMOUS		O_BASE + 8
+#define O_NOALIAS		O_BASE + 9
+#define O_IA_NA			O_BASE + 10
+#define O_IA_TA			O_BASE + 11
+#define O_IA_PD			O_BASE + 12
+#define O_HOSTNAME_SHORT	O_BASE + 13
+#define O_DEV			O_BASE + 14
+#define O_NODEV			O_BASE + 15
+#define O_NOIPV4		O_BASE + 16
+#define O_NOIPV6		O_BASE + 17
+#define O_IAID			O_BASE + 18
+#define O_DEFINE		O_BASE + 19
+#define O_DEFINE6		O_BASE + 20
+#define O_EMBED			O_BASE + 21
+#define O_ENCAP			O_BASE + 22
+#define O_VENDOPT		O_BASE + 23
+#define O_VENDCLASS		O_BASE + 24
+#define O_AUTHPROTOCOL		O_BASE + 25
+#define O_AUTHTOKEN		O_BASE + 26
+#define O_AUTHNOTREQUIRED	O_BASE + 27
+#define O_NODHCP		O_BASE + 28
+#define O_NODHCP6		O_BASE + 29
+#define O_DHCP			O_BASE + 30
+#define O_DHCP6			O_BASE + 31
+#define O_IPV4			O_BASE + 32
+#define O_IPV6			O_BASE + 33
+#define O_CONTROLGRP		O_BASE + 34
+#define O_SLAAC			O_BASE + 35
+#define O_GATEWAY		O_BASE + 36
+#define O_NOUP			O_BASE + 37
+#define O_IPV6RA_AUTOCONF	O_BASE + 38
+#define O_IPV6RA_NOAUTOCONF	O_BASE + 39
+#define O_REJECT		O_BASE + 40
+#define O_BOOTP			O_BASE + 42
+#define O_DEFINEND		O_BASE + 43
+#define O_NODELAY		O_BASE + 44
+#define O_INFORM6		O_BASE + 45
+#define O_LASTLEASE_EXTEND	O_BASE + 46
+#define O_INACTIVE		O_BASE + 47
+#define	O_MUDURL		O_BASE + 48
+#define	O_MSUSERCLASS		O_BASE + 49
+#define	O_CHROOT		O_BASE + 50
+
 extern const struct option cf_options[];
 
 struct if_sla {
--- a/src/ipv6nd.c	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/ipv6nd.c	Thu Apr 30 21:13:45 2020 +0100
@@ -1141,8 +1141,10 @@
 		if (ifp == rap->iface)
 			break;
 	}
-	if (rap != NULL && rap->willexpire)
+	if (rap != NULL && rap->willexpire) {
+		logerrx("settng def RA");
 		ipv6nd_applyra(ifp);
+	}
 #endif
 
 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
--- a/src/privsep-root.c	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/privsep-root.c	Thu Apr 30 21:13:45 2020 +0100
@@ -220,8 +220,7 @@
 	struct timeval tv[2];
 #endif
 
-	if (snprintf(path, sizeof(path), "%s/%s",
-	    ctx->ps_user->pw_dir, file) == -1)
+	if (snprintf(path, sizeof(path), "%s/%s", ctx->ps_chroot, file) == -1)
 		return -1;
 	if (stat(file, &from_sb) == -1)
 		return -1;
--- a/src/privsep.c	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/privsep.c	Thu Apr 30 21:13:45 2020 +0100
@@ -99,7 +99,7 @@
 ps_init(struct dhcpcd_ctx *ctx)
 {
 	char path[PATH_MAX];
-	struct passwd *pw = ctx->ps_user;
+	struct passwd *pw;
 
 	errno = 0;
 	if ((ctx->ps_user = pw = getpwnam(PRIVSEP_USER)) == NULL) {
@@ -113,16 +113,22 @@
 		return -1;
 	}
 
+	if (ctx->ps_chroot == NULL)
+		ctx->ps_chroot = pw->pw_dir;
+
 	/* If we pickup the _dhcp user refuse the default directory */
-	if (strcmp(pw->pw_dir, "/var/empty") == 0) {
+	if (*ctx->ps_chroot != '/' ||
+	    strcmp(ctx->ps_chroot, "/var/empty") == 0)
+	{
 		ctx->options &= ~DHCPCD_PRIVSEP;
-		logerrx("refusing chroot: %s: %s", PRIVSEP_USER, pw->pw_dir);
+		logerrx("refusing chroot: %s: %s",
+		    PRIVSEP_USER, ctx->ps_chroot);
 		errno = 0;
 		return -1;
 	}
 
 	/* Create the database directory. */
-	if (snprintf(path, sizeof(path), "%s%s", pw->pw_dir, DBDIR) == -1 ||
+	if (snprintf(path, sizeof(path), "%s%s", ctx->ps_chroot, DBDIR) == -1 ||
 	    ps_mkdir(path) == -1 ||
 	    chown(path, pw->pw_uid, pw->pw_gid) == -1 ||
 	    chmod(path, 0755) == -1)
@@ -142,10 +148,10 @@
 	struct passwd *pw = ctx->ps_user;
 
 	if (!(ctx->options & DHCPCD_FORKED))
-		logdebugx("chrooting to `%s'", pw->pw_dir);
+		logdebugx("chrooting to `%s'", ctx->ps_chroot);
 
-	if (chroot(pw->pw_dir) == -1)
-		logerr("%s: chroot `%s'", __func__, pw->pw_dir);
+	if (chroot(ctx->ps_chroot) == -1)
+		logerr("%s: chroot `%s'", __func__, ctx->ps_chroot);
 	if (chdir("/") == -1)
 		logerr("%s: chdir `/'", __func__);
 
--- a/src/script.c	Wed Apr 29 22:41:35 2020 +0100
+++ b/src/script.c	Thu Apr 30 21:13:45 2020 +0100
@@ -270,8 +270,8 @@
 		goto eexit;
 
 #ifdef PRIVSEP
-	if (ctx->options & DHCPCD_PRIVSEP && ctx->ps_user != NULL) {
-		if (efprintf(fp, "chroot=%s", ctx->ps_user->pw_dir) == -1)
+	if (ctx->options & DHCPCD_PRIVSEP && ctx->ps_chroot != NULL) {
+		if (efprintf(fp, "chroot=%s", ctx->ps_chroot) == -1)
 			goto eexit;
 	}
 	if (strcmp(reason, "CHROOT") == 0)