Mercurial > hg > dhcpcd
changeset 5255:ee23398a68db draft
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.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Thu, 21 May 2020 18:28:27 +0100 |
| parents | 2b7aae4f02f0 |
| children | 32665ffe1782 |
| files | src/dhcpcd.c src/dhcpcd.h src/if-options.c src/if-options.h src/privsep-root.c src/privsep-root.h src/script.c src/script.h |
| diffstat | 8 files changed, 37 insertions(+), 77 deletions(-) [+] |
line wrap: on
line diff
--- 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();
--- 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 *);
--- 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);
--- 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;
--- 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
--- 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 *);
--- 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");
--- 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
