summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-04-30 21:13:45 +0100
committerRoy Marples <roy@marples.name>2020-04-30 21:13:45 +0100
commit949d0f9aee6aefa461c949262202af12fa8143cf (patch)
treea5b0bd6b799e59714196e5774b67f239c7162b86 /src
parent257dae21343e899ad2667aac9b981fa427b7541b (diff)
downloaddhcpcd-949d0f9aee6aefa461c949262202af12fa8143cf.tar.xz
privsep: Add --chroot configurable
Overrides the directory to chroot to away from the privilege separation users home directory.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/dhcpcd.8.in9
-rw-r--r--src/dhcpcd.c5
-rw-r--r--src/dhcpcd.h1
-rw-r--r--src/if-options.c54
-rw-r--r--src/if-options.h53
-rw-r--r--src/ipv6nd.c4
-rw-r--r--src/privsep-root.c3
-rw-r--r--src/privsep.c20
-rw-r--r--src/script.c4
10 files changed, 89 insertions, 66 deletions
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)