]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Linux: setup mounts in chroot
authorRoy Marples <roy@marples.name>
Tue, 21 Jan 2020 22:09:14 +0000 (22:09 +0000)
committerRoy Marples <roy@marples.name>
Tue, 21 Jan 2020 22:09:14 +0000 (22:09 +0000)
This allows dhcpcd to work.
udev sadly requires /run/udev as well, so heh ho.

configure
hooks/00-linux [new file with mode: 0644]
src/dhcpcd.c
src/script.c
src/script.h

index 263afbf77566dbcf1abe0283c0b0642c94e79f5f..56d2cac902d70f8a80f87e4fcb2831eda226d683 100755 (executable)
--- a/configure
+++ b/configure
@@ -1709,6 +1709,9 @@ if cd hooks; then
        done
        cd ..
 fi
+if [ "$OS" = linux ]; then
+       HOOKS="$HOOKS${HOOKS:+ }00-linux"
+fi
 echo "HOOKSCRIPTS=     $HOOKS" >>$CONFIG_MK
 echo "EGHOOKSCRIPTS=   $EGHOOKS" >>$CONFIG_MK
 
diff --git a/hooks/00-linux b/hooks/00-linux
new file mode 100644 (file)
index 0000000..b3bf1f5
--- /dev/null
@@ -0,0 +1,11 @@
+# setup chroot mounts
+
+if [ "$reason" = CHROOT ] && [ -n "$chroot" ]; then
+       for d in /dev /proc /sys /run/udev; do
+               [ -d "$d" ] || continue
+               if ! mountpoint -q "$chroot$d"; then
+                       mkdir -p "$chroot$d"
+                       mount --bind $d "$chroot$d"
+               fi
+       done
+fi
index ad2249c4608cd544f62932a397d4a58f49f30ccd..f0456ce6b10adcfe434d5bf79ea61e73b3777678 100644 (file)
@@ -2018,6 +2018,7 @@ printpidfile:
                logerr("ps_init");
                goto exit_failure;
        }
+       script_runchroot(&ctx, ifo->script);
 #endif
 
 #ifdef USE_SIGNALS
@@ -2091,6 +2092,12 @@ printpidfile:
                goto exit_failure;
        }
 
+       /* Start any dev listening plugin which may want to
+        * change the interface name provided by the kernel */
+       if ((ctx.options & (DHCPCD_MASTER | DHCPCD_DEV)) ==
+           (DHCPCD_MASTER | DHCPCD_DEV))
+               dev_start(&ctx);
+
 #ifdef PRIVSEP
        if (ctx.options & DHCPCD_PRIVSEP && ps_dropprivs(&ctx) == -1) {
                logerr("ps_dropprivs");
@@ -2120,12 +2127,6 @@ printpidfile:
         * routes. */
        eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx);
 
-       /* Start any dev listening plugin which may want to
-        * change the interface name provided by the kernel */
-       if ((ctx.options & (DHCPCD_MASTER | DHCPCD_DEV)) ==
-           (DHCPCD_MASTER | DHCPCD_DEV))
-               dev_start(&ctx);
-
        ctx.ifaces = if_discover(&ctx, &ifaddrs, ctx.ifc, ctx.ifv);
        if (ctx.ifaces == NULL) {
                logerr("%s: if_discover", __func__);
index 6b0f37a4dde4499f09f4e46ff09012ebaaf3bbc9..81cae18c968a6105098b807308fafc583717d3e0 100644 (file)
@@ -36,6 +36,7 @@
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
+#include <pwd.h>
 #include <signal.h>
 #include <spawn.h>
 #include <stdarg.h>
@@ -218,14 +219,14 @@ script_buftoenv(struct dhcpcd_ctx *ctx, char *buf, size_t len)
 }
 
 static long
-make_env(const struct interface *ifp, const char *reason)
+make_env(struct dhcpcd_ctx *ctx, const struct interface *ifp,
+    const char *reason)
 {
-       struct dhcpcd_ctx *ctx = ifp->ctx;
        FILE *fp;
        long buf_pos, i;
        char *path;
        int protocol = PROTO_LINK;
-       const struct if_options *ifo = ifp->options;
+       const struct if_options *ifo;
        const struct interface *ifp2;
        int af;
 #ifdef INET
@@ -264,6 +265,24 @@ make_env(const struct interface *ifp, const char *reason)
        }
 #endif
 
+       /* Needed for scripts */
+       path = getenv("PATH");
+       if (efprintf(fp, "PATH=%s", path == NULL ? DEFAULT_PATH:path) == -1)
+               goto eexit;
+       if (efprintf(fp, "reason=%s", reason) == -1)
+               goto eexit;
+       if (efprintf(fp, "pid=%d", getpid()) == -1)
+               goto eexit;
+
+#ifdef PRIVSEP
+       if (strcmp(reason, "CHROOT") == 0) {
+               if (efprintf(fp, "chroot=%s", ctx->ps_user->pw_dir) == -1)
+                       goto eexit;
+               goto make;
+       }
+#endif
+
+       ifo = ifp->options;
 #ifdef INET
        state = D_STATE(ifp);
 #ifdef IPV4LL
@@ -321,19 +340,11 @@ make_env(const struct interface *ifp, const char *reason)
                protocol = PROTO_DHCP;
 #endif
 
-       /* Needed for scripts */
-       path = getenv("PATH");
-       if (efprintf(fp, "PATH=%s", path == NULL ? DEFAULT_PATH:path) == -1)
-               goto eexit;
 
        if (efprintf(fp, "interface=%s", ifp->name) == -1)
                goto eexit;
-       if (efprintf(fp, "reason=%s", reason) == -1)
-               goto eexit;
        if (ifp->ctx->options & DHCPCD_DUMPLEASE)
                goto dumplease;
-       if (efprintf(fp, "pid=%d", getpid()) == -1)
-               goto eexit;
        if (efprintf(fp, "ifcarrier=%s",
            ifp->carrier == LINK_UNKNOWN ? "unknown" :
            ifp->carrier == LINK_UP ? "up" : "down") == -1)
@@ -497,6 +508,7 @@ dumplease:
                                goto eexit;
        }
 
+make:
        /* Convert buffer to argv */
        fflush(fp);
 
@@ -543,7 +555,7 @@ send_interface1(struct fd_list *fd, const struct interface *ifp,
        struct dhcpcd_ctx *ctx = ifp->ctx;
        long len;
 
-       len = make_env(ifp, reason);
+       len = make_env(ifp->ctx, ifp, reason);
        if (len == -1)
                return -1;
        return control_queue(fd, ctx->script_buf,  (size_t)len, 1);
@@ -610,12 +622,41 @@ send_interface(struct fd_list *fd, const struct interface *ifp)
        return retval;
 }
 
+static int
+script_run(struct dhcpcd_ctx *ctx, char **argv)
+{
+       pid_t pid;
+       int status = 0;
+
+       pid = script_exec(ctx, argv, ctx->script_env);
+       if (pid == -1)
+               logerr("%s: %s", __func__, argv[0]);
+       else if (pid != 0) {
+               /* Wait for the script to finish */
+               while (waitpid(pid, &status, 0) == -1) {
+                       if (errno != EINTR) {
+                               logerr("%s: waitpid", __func__);
+                               status = 0;
+                               break;
+                       }
+               }
+               if (WIFEXITED(status)) {
+                       if (WEXITSTATUS(status))
+                               logerrx("%s: %s: WEXITSTATUS %d",
+                                   __func__, argv[0], WEXITSTATUS(status));
+               } else if (WIFSIGNALED(status))
+                       logerrx("%s: %s: %s",
+                           __func__, argv[0], strsignal(WTERMSIG(status)));
+       }
+
+       return WEXITSTATUS(status);
+}
+
 int
 script_runreason(const struct interface *ifp, const char *reason)
 {
        struct dhcpcd_ctx *ctx = ifp->ctx;
        char *argv[2];
-       pid_t pid;
        int status = 0;
        struct fd_list *fd;
 
@@ -624,7 +665,7 @@ script_runreason(const struct interface *ifp, const char *reason)
                return 0;
 
        /* Make our env */
-       if (make_env(ifp, reason) == -1) {
+       if (make_env(ifp->ctx, ifp, reason) == -1) {
                logerr(__func__);
                return -1;
        }
@@ -645,26 +686,7 @@ script_runreason(const struct interface *ifp, const char *reason)
        }
 #endif
 
-       pid = script_exec(ctx, argv, ctx->script_env);
-       if (pid == -1)
-               logerr("%s: %s", __func__, argv[0]);
-       else if (pid != 0) {
-               /* Wait for the script to finish */
-               while (waitpid(pid, &status, 0) == -1) {
-                       if (errno != EINTR) {
-                               logerr("%s: waitpid", __func__);
-                               status = 0;
-                               break;
-                       }
-               }
-               if (WIFEXITED(status)) {
-                       if (WEXITSTATUS(status))
-                               logerrx("%s: %s: WEXITSTATUS %d",
-                                   __func__, argv[0], WEXITSTATUS(status));
-               } else if (WIFSIGNALED(status))
-                       logerrx("%s: %s: %s",
-                           __func__, argv[0], strsignal(WTERMSIG(status)));
-       }
+       status = script_run(ctx, argv);
 
 send_listeners:
        /* Send to our listeners */
@@ -679,5 +701,25 @@ send_listeners:
                        status = 1;
        }
 
-       return WEXITSTATUS(status);
+       return status;
+}
+
+#ifdef PRIVSEP
+int
+script_runchroot(struct dhcpcd_ctx *ctx, char *script)
+{
+       char *argv[2];
+
+       /* Make our env */
+       if (make_env(ctx, NULL, "CHROOT") == -1) {
+               logerr(__func__);
+               return -1;
+       }
+
+       argv[0] = script;
+       argv[1] = NULL;
+       logdebugx("executing `%s' %s", argv[0], "CHROOT");
+
+       return script_run(ctx, argv);
 }
+#endif
index badccd7fe83f547b6cd4bed61440562e126f6062..e35ca86d679982d46de0cd09c6ade22a95cf446a 100644 (file)
@@ -37,5 +37,5 @@ char ** script_buftoenv(struct dhcpcd_ctx *, char *, size_t);
 pid_t script_exec(const struct dhcpcd_ctx *, char *const *, char *const *);
 int send_interface(struct fd_list *, const struct interface *);
 int script_runreason(const struct interface *, const char *);
-
+int script_runchroot(struct dhcpcd_ctx *, char *);
 #endif