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'
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
${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}
.\" 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
.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
.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,
case 'V':
i = 2;
break;
+#ifdef PRIVSEP
+ case O_CHROOT:
+ ctx.ps_chroot = optarg;
+ break;
+#endif
case '?':
if (ctx.options & DHCPCD_PRINT_PIDFILE)
continue;
#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 */
#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'},
{"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'}
};
#define ARG_REQUIRED if (arg == NULL) goto arg_required
switch(opt) {
+ case O_CHROOT: /* FALLTHROUGH */
case 'f': /* FALLTHROUGH */
case 'g': /* FALLTHROUGH */
case 'n': /* FALLTHROUGH */
#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 {
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) {
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;
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) {
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)
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__);
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)