From: Roy Marples Date: Thu, 9 Jan 2020 15:39:18 +0000 (+0000) Subject: privsep: Delay control startup after starting privsep X-Git-Tag: v9.0.0~126 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9c939ec49f43770566791c122e85a45e279ceeb;p=thirdparty%2Fdhcpcd.git privsep: Delay control startup after starting privsep This means we don't need to close it for other processes. Add ps_init so that we can change directory permissions before starting privsep itself. --- diff --git a/src/control.c b/src/control.c index f1489878..c81d2cb3 100644 --- a/src/control.c +++ b/src/control.c @@ -269,25 +269,22 @@ control_stop(struct dhcpcd_ctx *ctx) int retval = 0; struct fd_list *l; - if (ctx->options & DHCPCD_FORKED) - goto freeit; - - if (ctx->control_fd == -1) - return 0; - - control_close(ctx); - if (unlink(ctx->control_sock) == -1) - retval = -1; + if (ctx->control_fd != -1) { + eloop_event_delete(ctx->eloop, ctx->control_fd); + close(ctx->control_fd); + ctx->control_fd = -1; + if (unlink(ctx->control_sock) == -1 && errno != ENOENT) + retval = -1; + } if (ctx->control_unpriv_fd != -1) { eloop_event_delete(ctx->eloop, ctx->control_unpriv_fd); close(ctx->control_unpriv_fd); ctx->control_unpriv_fd = -1; - if (unlink(UNPRIVSOCKET) == -1) + if (unlink(UNPRIVSOCKET) == -1 && errno != ENOENT) retval = -1; } -freeit: while ((l = TAILQ_FIRST(&ctx->control_fds))) { TAILQ_REMOVE(&ctx->control_fds, l, next); eloop_event_delete(ctx->eloop, l->fd); @@ -448,14 +445,3 @@ queue: eloop_event_add_w(fd->ctx->eloop, fd->fd, control_writeone, fd); return 0; } - -void -control_close(struct dhcpcd_ctx *ctx) -{ - - if (ctx->control_fd != -1) { - eloop_event_delete(ctx->eloop, ctx->control_fd); - close(ctx->control_fd); - ctx->control_fd = -1; - } -} diff --git a/src/control.h b/src/control.h index 4d8c5225..72f601bf 100644 --- a/src/control.h +++ b/src/control.h @@ -71,6 +71,5 @@ int control_stop(struct dhcpcd_ctx *); int control_open(const char *); ssize_t control_send(struct dhcpcd_ctx *, int, char * const *); int control_queue(struct fd_list *, void *, size_t, bool); -void control_close(struct dhcpcd_ctx *ctx); #endif diff --git a/src/dhcpcd.c b/src/dhcpcd.c index d2b205ab..13376b92 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -1917,7 +1917,6 @@ printpidfile: if (ctx.control_fd != -1) { loginfox("sending commands to master dhcpcd process"); len = control_send(&ctx, argc, argv); - control_close(&ctx); if (len > 0) { logdebugx("send OK"); goto exit_success; @@ -1989,6 +1988,13 @@ printpidfile: logdebugx(PACKAGE "-" VERSION " starting"); +#ifdef PRIVSEP + if (ps_init(&ctx) == -1 && errno != 0) { + logerr("ps_init"); + goto exit_failure; + } +#endif + #ifdef USE_SIGNALS if (pipe(sigpipe) == -1) { logerr("pipe"); @@ -2038,18 +2044,6 @@ printpidfile: } #endif - if (control_start(&ctx, - ctx.options & DHCPCD_MASTER ? NULL : argv[optind]) == -1) - { - logerr("%s: control_start", __func__); - goto exit_failure; - } - - setproctitle("%s%s%s", - ctx.options & DHCPCD_MASTER ? "[master]" : argv[optind], - ctx.options & DHCPCD_IPV4 ? " [ip4]" : "", - ctx.options & DHCPCD_IPV6 ? " [ip6]" : ""); - #ifdef BSD /* Disable the kernel RTADV sysctl as early as possible. */ if (ctx.options & DHCPCD_IPV6 && ctx.options & DHCPCD_IPV6RS) @@ -2057,7 +2051,7 @@ printpidfile: #endif #ifdef PRIVSEP - if (ps_start(&ctx) == -1 && errno != 0) { + if (ctx.options & DHCPCD_PRIVSEP && ps_start(&ctx) == -1) { logerr("ps_start"); goto exit_failure; } @@ -2065,6 +2059,18 @@ printpidfile: goto run_loop; #endif + if (control_start(&ctx, + ctx.options & DHCPCD_MASTER ? NULL : argv[optind]) == -1) + { + logerr("%s: control_start", __func__); + goto exit_failure; + } + + setproctitle("%s%s%s", + ctx.options & DHCPCD_MASTER ? "[master]" : argv[optind], + ctx.options & DHCPCD_IPV4 ? " [ip4]" : "", + ctx.options & DHCPCD_IPV6 ? " [ip6]" : ""); + if (if_opensockets(&ctx) == -1) { logerr("%s: if_opensockets", __func__); goto exit_failure; diff --git a/src/privsep.c b/src/privsep.c index 9696e5c8..fb0a85b6 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -68,6 +68,35 @@ #include #endif +int +ps_init(struct dhcpcd_ctx *ctx) +{ + struct passwd *pw; + gid_t gid = (gid_t)-1; + + errno = 0; + if ((pw = getpwnam(PRIVSEP_USER)) == NULL) { + ctx->options &= ~DHCPCD_PRIVSEP; + if (errno == 0) { + logerrx("no such user %s", PRIVSEP_USER); + /* Just incase logerrx caused an error... */ + errno = 0; + } else + logerr("getpwnam"); + return -1; + } + + + /* Change ownership of stuff we need to drop at exit. */ + if (chown(ctx->pidfile, pw->pw_uid, gid) == -1) + logerr("chown `%s'", ctx->pidfile); + if (chown(DBDIR, pw->pw_uid, gid) == -1) + logerr("chown `%s'", DBDIR); + if (chown(RUNDIR, pw->pw_uid, gid) == -1) + logerr("chown `%s'", RUNDIR); + return 0; +} + pid_t ps_dostart(struct dhcpcd_ctx *ctx, pid_t *priv_pid, int *priv_fd, @@ -80,51 +109,21 @@ ps_dostart(struct dhcpcd_ctx *ctx, int fd[2]; pid_t pid; - /* Even if we're not dropping privs, we need to ensure that the unpriv - * user exists so the processes that do need it startup just fine. */ - errno = 0; - if ((pw = getpwnam(PRIVSEP_USER)) == NULL) { - ctx->options &= ~DHCPCD_PRIVSEP; - if (errno == 0) { - if (ctx == recv_ctx) { /* Only log the once. */ + if (flags & PSF_DROPPRIVS) { + errno = 0; + if ((pw = getpwnam(PRIVSEP_USER)) == NULL) { + if (errno == 0) logerrx("no such user %s", PRIVSEP_USER); - /* Just incase logerrx caused an error... */ - errno = 0; - } - } else - logerr("getpwnam"); - return -1; - } - - if (!(flags & PSF_DROPPRIVS)) { + else + logerr("getpwnam"); + return -1; + } + } else pw = NULL; - goto create_sp; - } - if (priv_pid == NULL) { - gid_t gid = (gid_t)-1; - - /* Main process - change ownership of stuff we need to - * drop at exit. */ - if (pw != NULL) { - if (chown(ctx->pidfile, pw->pw_uid, gid) == -1) - logerr("chown `%s'", ctx->pidfile); - if (chown(DBDIR, pw->pw_uid, gid) == -1) - logerr("chown `%s'", DBDIR); - if (chown(RUNDIR, pw->pw_uid, gid) == -1) - logerr("chown `%s'", RUNDIR); - if (ctx->options & DHCPCD_MASTER) { - if (chown(ctx->control_sock, - pw->pw_uid, gid) == -1) - logerr("chown `%s'", ctx->control_sock); - if (chown(UNPRIVSOCKET, pw->pw_uid, gid) == -1) - logerr("chown `%s'", UNPRIVSOCKET); - } - } + if (priv_fd == NULL) goto dropprivs; - } -create_sp: stype = SOCK_CLOEXEC | SOCK_NONBLOCK; if (socketpair(AF_UNIX, SOCK_DGRAM | stype, 0, fd) == -1) { logerr("socketpair"); @@ -159,7 +158,6 @@ create_sp: close(ctx->fork_fd); ctx->fork_fd = -1; } - control_close(ctx); pidfile_clean(); eloop_clear(ctx->eloop); diff --git a/src/privsep.h b/src/privsep.h index 4c306f3d..2f63038a 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -130,6 +130,7 @@ TAILQ_HEAD(ps_process_head, ps_process); #include "privsep-bpf.h" #endif +int ps_init(struct dhcpcd_ctx *); int ps_start(struct dhcpcd_ctx *); int ps_stop(struct dhcpcd_ctx *);