From: Roy Marples Date: Tue, 21 Jan 2020 22:09:14 +0000 (+0000) Subject: Linux: setup mounts in chroot X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b2888271d79d39d972db7746f5d4ecdcf1372586;p=thirdparty%2Fdhcpcd.git Linux: setup mounts in chroot This allows dhcpcd to work. udev sadly requires /run/udev as well, so heh ho. --- diff --git a/configure b/configure index 263afbf7..56d2cac9 100755 --- 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 index 00000000..b3bf1f50 --- /dev/null +++ b/hooks/00-linux @@ -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 diff --git a/src/dhcpcd.c b/src/dhcpcd.c index ad2249c4..f0456ce6 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -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__); diff --git a/src/script.c b/src/script.c index 6b0f37a4..81cae18c 100644 --- a/src/script.c +++ b/src/script.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -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 diff --git a/src/script.h b/src/script.h index badccd7f..e35ca86d 100644 --- a/src/script.h +++ b/src/script.h @@ -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