]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Add --chroot configurable
authorRoy Marples <roy@marples.name>
Thu, 30 Apr 2020 20:13:45 +0000 (21:13 +0100)
committerRoy Marples <roy@marples.name>
Thu, 30 Apr 2020 20:13:45 +0000 (21:13 +0100)
Overrides the directory to chroot to away from the privilege separation
users home directory.

12 files changed:
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

index ec5361a6ac02808e7b642fbaad399de98ea738d3..6648e832bb4d975a61b290d16d148ec828943a14 100644 (file)
@@ -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'
index 203b2ba0de0a130540b63e5b30d6429190ab24d2..3e2e20fd61c6f07d1660df2ed8648d4cdf09e1ad 100755 (executable)
--- 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
index 28fb6e35655502ca81d0d25df81c763a99ffee2a..2cdbe013a21fd30b40f4eb7fa5a79287a18a73a1 100644 (file)
@@ -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}
index 6f7c6567bc9c247a7c6ae47750b9d8fd845ab656..654cd277557725171b84de9a97ff2e28457c408f 100644 (file)
@@ -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,
index ceed175927ba164321541a0e3587e758f359fa46..67ae0b2ec24fc906badc9b327ff5459d84281a5e 100644 (file)
@@ -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;
index 77b800583a6f3a7989d39e725a076d73fbd736a2..69d62cb5415358ad149eab8a6c060f37e10908d6 100644 (file)
@@ -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 */
index 79b2f6bf7bb21b569dbb8ad337d3a00117a4b642..f2fb205bee7d25c195bbf94eb0b5c0310f31ee5b 100644 (file)
 #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 */
index f9d47713fec58386650e261fc724d1f6de610cb2..888056992d78a3f76d093e3e9d1d069b19d1ed9b 100644 (file)
 #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 {
index 777190419f87a32c75db435b87bb163e1fc23110..73df91097b81c8c91c74cc372352f861fc2f228f 100644 (file)
@@ -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) {
index a2aa144889db052dd8402c5d119b62ce0a8951f5..c3b95e24357ac08f05f60d1020b6d3af49c07f43 100644 (file)
@@ -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;
index 09e63216aac01ce1f5c637e5c1c8298ff601157a..c30bf90f84bb4677c1d897ce4d183e9058d213c2 100644 (file)
@@ -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__);
 
index 186b6e05d435ae37131884545e6466ad96ea3d18..1caf58aca0c9737dca7ec7137b5a111e41fed4bc 100644 (file)
@@ -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)