From: Roy Marples Date: Thu, 30 Apr 2020 20:13:45 +0000 (+0100) Subject: privsep: Add --chroot configurable X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=949d0f9aee6aefa461c949262202af12fa8143cf;p=thirdparty%2Fdhcpcd.git privsep: Add --chroot configurable Overrides the directory to chroot to away from the privilege separation users home directory. --- diff --git a/Makefile.inc b/Makefile.inc index ec5361a6..6648e832 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -33,3 +33,4 @@ SED_STATUSARG= -e 's:@STATUSARG@:${STATUSARG}:g' 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' diff --git a/configure b/configure index 203b2ba0..3e2e20fd 100755 --- a/configure +++ b/configure @@ -578,6 +578,7 @@ if [ "$PRIVSEP" = yes ]; then 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 diff --git a/src/Makefile b/src/Makefile index 28fb6e35..2cdbe013 100644 --- a/src/Makefile +++ b/src/Makefile @@ -42,7 +42,7 @@ CLEANFILES+= *.tar.xz ${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} diff --git a/src/dhcpcd.8.in b/src/dhcpcd.8.in index 6f7c6567..654cd277 100644 --- a/src/dhcpcd.8.in +++ b/src/dhcpcd.8.in @@ -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 @@ Use this .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, diff --git a/src/dhcpcd.c b/src/dhcpcd.c index ceed1759..67ae0b2e 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -1891,6 +1891,11 @@ main(int argc, char **argv) case 'V': i = 2; break; +#ifdef PRIVSEP + case O_CHROOT: + ctx.ps_chroot = optarg; + break; +#endif case '?': if (ctx.options & DHCPCD_PRINT_PIDFILE) continue; diff --git a/src/dhcpcd.h b/src/dhcpcd.h index 77b80058..69d62cb5 100644 --- a/src/dhcpcd.h +++ b/src/dhcpcd.h @@ -192,6 +192,7 @@ struct dhcpcd_ctx { #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 */ diff --git a/src/if-options.c b/src/if-options.c index 79b2f6bf..f2fb205b 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -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 @@ const struct option cf_options[] = { {"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 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, #define ARG_REQUIRED if (arg == NULL) goto arg_required switch(opt) { + case O_CHROOT: /* FALLTHROUGH */ case 'f': /* FALLTHROUGH */ case 'g': /* FALLTHROUGH */ case 'n': /* FALLTHROUGH */ diff --git a/src/if-options.h b/src/if-options.h index f9d47713..88805699 100644 --- a/src/if-options.h +++ b/src/if-options.h @@ -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 { diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 77719041..73df9109 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -1141,8 +1141,10 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx, 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) { diff --git a/src/privsep-root.c b/src/privsep-root.c index a2aa1448..c3b95e24 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -220,8 +220,7 @@ ps_root_docopychroot(struct dhcpcd_ctx *ctx, const char *file) 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; diff --git a/src/privsep.c b/src/privsep.c index 09e63216..c30bf90f 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -99,7 +99,7 @@ int 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 @@ ps_init(struct dhcpcd_ctx *ctx) 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 @@ ps_dropprivs(struct dhcpcd_ctx *ctx) 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__); diff --git a/src/script.c b/src/script.c index 186b6e05..1caf58ac 100644 --- a/src/script.c +++ b/src/script.c @@ -270,8 +270,8 @@ make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp, 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)