# HG changeset patch # User Roy Marples # Date 1590082107 -3600 # Node ID ee23398a68dbc4185dea93f1d642cbb19751eec6 # Parent 2b7aae4f02f0d5f3fe30be30445e41ca84895c04 dhcpcd: Move the script file from per interface to global context This *should* affect no-one, but you never know. The primary motivation for this is to ensure that nothing arbitary can be executed by the root process if anyone breaks into the chrooted unprivileged master process. It also makes for smaller code. diff -r 2b7aae4f02f0 -r ee23398a68db src/dhcpcd.c --- a/src/dhcpcd.c Thu May 21 17:03:54 2020 +0100 +++ b/src/dhcpcd.c Thu May 21 18:28:27 2020 +0100 @@ -98,6 +98,8 @@ #define IF_UPANDRUNNING(a) \ (((a)->flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) +const char *dhcpcd_default_script = SCRIPT; + static void usage(void) { @@ -1837,6 +1839,7 @@ ifo = NULL; ctx.cffile = CONFIG; + ctx.script = UNCONST(dhcpcd_default_script); ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1; ctx.pf_inet_fd = -1; @@ -2172,7 +2175,7 @@ #ifdef PRIVSEP if (ps_init(&ctx) == 0) - script_runchroot(&ctx, ifo->script); + script_runchroot(&ctx); #endif #ifdef USE_SIGNALS @@ -2456,6 +2459,8 @@ eloop_free(ctx.ps_eloop); #endif eloop_free(ctx.eloop); + if (ctx.script != dhcpcd_default_script) + free(ctx.script); if (ctx.options & DHCPCD_STARTED && !(ctx.options & DHCPCD_FORKED)) loginfox(PACKAGE " exited"); logclose(); diff -r 2b7aae4f02f0 -r ee23398a68db src/dhcpcd.h --- a/src/dhcpcd.h Thu May 21 17:03:54 2020 +0100 +++ b/src/dhcpcd.h Thu May 21 18:28:27 2020 +0100 @@ -164,6 +164,7 @@ #endif struct eloop *eloop; + char *script; #ifdef HAVE_OPEN_MEMSTREAM FILE *script_fp; #endif @@ -253,6 +254,8 @@ extern const size_t dhcpcd_signals_ignore_len; #endif +extern const char *dhcpcd_default_script; + int dhcpcd_ifafwaiting(const struct interface *); int dhcpcd_afwaiting(const struct dhcpcd_ctx *); void dhcpcd_daemonise(struct dhcpcd_ctx *); diff -r 2b7aae4f02f0 -r ee23398a68db src/if-options.c --- a/src/if-options.c Thu May 21 17:03:54 2020 +0100 +++ b/src/if-options.c Thu May 21 18:28:27 2020 +0100 @@ -161,8 +161,6 @@ {NULL, 0, NULL, '\0'} }; -static const char *default_script = SCRIPT; - static char * add_environ(char ***array, const char *value, int uniq) { @@ -675,26 +673,32 @@ break; case 'c': ARG_REQUIRED; - if (ifo->script != default_script) - free(ifo->script); + if (ifname != NULL) { + logerrx("%s: per interface scripts" + " are no longer supported", + ifname); + return -1; + } + if (ctx->script != dhcpcd_default_script) + free(ctx->script); s = parse_nstring(NULL, 0, arg); if (s == 0) { - ifo->script = NULL; + ctx->script = NULL; break; } dl = (size_t)s; - if (s == -1 || (ifo->script = malloc(dl)) == NULL) { - ifo->script = NULL; + if (s == -1 || (ctx->script = malloc(dl)) == NULL) { + ctx->script = NULL; logerr(__func__); return -1; } - s = parse_nstring(ifo->script, dl, arg); + s = parse_nstring(ctx->script, dl, arg); if (s == -1 || - ifo->script[0] == '\0' || - strcmp(ifo->script, "/dev/null") == 0) + ctx->script[0] == '\0' || + strcmp(ctx->script, "/dev/null") == 0) { - free(ifo->script); - ifo->script = NULL; + free(ctx->script); + ctx->script = NULL; } break; case 'd': @@ -2315,7 +2319,6 @@ ifo->options |= DHCPCD_IF_UP | DHCPCD_LINK | DHCPCD_INITIAL_DELAY; ifo->timeout = DEFAULT_TIMEOUT; ifo->reboot = DEFAULT_REBOOT; - ifo->script = UNCONST(default_script); ifo->metric = -1; ifo->auth.options |= DHCPCD_AUTH_REQUIRE; rb_tree_init(&ifo->routes, &rt_compare_list_ops); @@ -2667,8 +2670,6 @@ #endif rt_headclear0(ctx, &ifo->routes, AF_UNSPEC); - if (ifo->script != default_script) - free(ifo->script); free(ifo->arping); free(ifo->blacklist); free(ifo->fallback); diff -r 2b7aae4f02f0 -r ee23398a68db src/if-options.h --- a/src/if-options.h Thu May 21 17:03:54 2020 +0100 +++ b/src/if-options.h Thu May 21 18:28:27 2020 +0100 @@ -243,7 +243,6 @@ char **config; char **environ; - char *script; char hostname[HOSTNAME_MAX_LEN + 1]; /* We don't store the length */ uint8_t fqdn; diff -r 2b7aae4f02f0 -r ee23398a68db src/privsep-root.c --- a/src/privsep-root.c Thu May 21 17:03:54 2020 +0100 +++ b/src/privsep-root.c Thu May 21 18:28:27 2020 +0100 @@ -259,34 +259,13 @@ ps_root_run_script(struct dhcpcd_ctx *ctx, const void *data, size_t len) { const char *envbuf = data; - char * const argv[] = { UNCONST(data), NULL }; + char * const argv[] = { ctx->script, NULL }; pid_t pid; int status; -#ifdef PRIVSEP_DEBUG - logdebugx("%s: IN %zu", __func__, len); -#endif - if (len == 0) return 0; - /* Script is the first one, find the environment buffer. */ - while (*envbuf != '\0') { - if (len == 0) - return EINVAL; - envbuf++; - len--; - } - - if (len != 0) { - envbuf++; - len--; - } - -#ifdef PRIVSEP_DEBUG - logdebugx("%s: run script: %s", __func__, argv[0]); -#endif - if (script_buftoenv(ctx, UNCONST(envbuf), len) == NULL) return -1; @@ -678,39 +657,12 @@ } ssize_t -ps_root_script(const struct interface *ifp, const void *data, size_t len) +ps_root_script(struct dhcpcd_ctx *ctx, const void *data, size_t len) { - char buf[PS_BUFLEN], *p = buf; - size_t blen = PS_BUFLEN, slen = strlen(ifp->options->script) + 1; -#ifdef PRIVSEP_DEBUG - logdebugx("%s: sending script: %zu %s len %zu", - __func__, slen, ifp->options->script, len); -#endif - - if (slen > blen) { - errno = ENOBUFS; + if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_SCRIPT, 0, data, len) == -1) return -1; - } - memcpy(p, ifp->options->script, slen); - p += slen; - blen -= slen; - - if (len > blen) { - errno = ENOBUFS; - return -1; - } - memcpy(p, data, len); - -#ifdef PRIVSEP_DEBUG - logdebugx("%s: sending script data: %zu", __func__, slen + len); -#endif - - if (ps_sendcmd(ifp->ctx, ifp->ctx->ps_root_fd, PS_SCRIPT, 0, - buf, slen + len) == -1) - return -1; - - return ps_root_readerror(ifp->ctx, NULL, 0); + return ps_root_readerror(ctx, NULL, 0); } ssize_t diff -r 2b7aae4f02f0 -r ee23398a68db src/privsep-root.h --- a/src/privsep-root.h Thu May 21 17:03:54 2020 +0100 +++ b/src/privsep-root.h Thu May 21 18:28:27 2020 +0100 @@ -42,7 +42,7 @@ ssize_t ps_root_readfile(struct dhcpcd_ctx *, const char *, void *, size_t); ssize_t ps_root_writefile(struct dhcpcd_ctx *, const char *, mode_t, const void *, size_t); -ssize_t ps_root_script(const struct interface *, const void *, size_t); +ssize_t ps_root_script(struct dhcpcd_ctx *, const void *, size_t); int ps_root_getifaddrs(struct dhcpcd_ctx *, struct ifaddrs **); ssize_t ps_root_os(struct ps_msghdr *, struct msghdr *); diff -r 2b7aae4f02f0 -r ee23398a68db src/script.c --- a/src/script.c Thu May 21 17:03:54 2020 +0100 +++ b/src/script.c Thu May 21 18:28:27 2020 +0100 @@ -691,7 +691,7 @@ int status = 0; struct fd_list *fd; - if (ifp->options->script == NULL && + if (ctx->script == NULL && TAILQ_FIRST(&ifp->ctx->control_fds) == NULL) return 0; @@ -701,16 +701,16 @@ return -1; } - if (ifp->options->script == NULL) + if (ctx->script == NULL) goto send_listeners; - argv[0] = ifp->options->script; + argv[0] = ctx->script; argv[1] = NULL; logdebugx("%s: executing `%s' %s", ifp->name, argv[0], reason); #ifdef PRIVSEP if (ctx->options & DHCPCD_PRIVSEP) { - if (ps_root_script(ifp, + if (ps_root_script(ctx, ctx->script_buf, ctx->script_buflen) == -1) logerr(__func__); goto send_listeners; @@ -737,7 +737,7 @@ #ifdef PRIVSEP int -script_runchroot(struct dhcpcd_ctx *ctx, char *script) +script_runchroot(struct dhcpcd_ctx *ctx) { char *argv[2]; @@ -747,7 +747,7 @@ return -1; } - argv[0] = script; + argv[0] = ctx->script; argv[1] = NULL; logdebugx("executing `%s' %s", argv[0], "CHROOT"); diff -r 2b7aae4f02f0 -r ee23398a68db src/script.h --- a/src/script.h Thu May 21 17:03:54 2020 +0100 +++ b/src/script.h Thu May 21 18:28:27 2020 +0100 @@ -37,5 +37,5 @@ pid_t script_exec(char *const *, char *const *); int send_interface(struct fd_list *, const struct interface *, int); int script_runreason(const struct interface *, const char *); -int script_runchroot(struct dhcpcd_ctx *, char *); +int script_runchroot(struct dhcpcd_ctx *); #endif