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.
#define IF_UPANDRUNNING(a) \
(((a)->flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
+const char *dhcpcd_default_script = SCRIPT;
+
static void
usage(void)
{
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;
#ifdef PRIVSEP
if (ps_init(&ctx) == 0)
- script_runchroot(&ctx, ifo->script);
+ script_runchroot(&ctx);
#endif
#ifdef USE_SIGNALS
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();
#endif
struct eloop *eloop;
+ char *script;
#ifdef HAVE_OPEN_MEMSTREAM
FILE *script_fp;
#endif
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 *);
{NULL, 0, NULL, '\0'}
};
-static const char *default_script = SCRIPT;
-
static char *
add_environ(char ***array, const char *value, int uniq)
{
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':
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);
#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);
char **config;
char **environ;
- char *script;
char hostname[HOSTNAME_MAX_LEN + 1]; /* We don't store the length */
uint8_t fqdn;
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;
}
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
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 *);
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;
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;
#ifdef PRIVSEP
int
-script_runchroot(struct dhcpcd_ctx *ctx, char *script)
+script_runchroot(struct dhcpcd_ctx *ctx)
{
char *argv[2];
return -1;
}
- argv[0] = script;
+ argv[0] = ctx->script;
argv[1] = NULL;
logdebugx("executing `%s' %s", argv[0], "CHROOT");
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