# HG changeset patch # User Roy Marples # Date 1600625348 -3600 # Node ID 8bf1ce29152cc049f534d0707c86e98519ca8662 # Parent afa6f810f6932e874a7e687e8843398f4c0b855b privsep: sandbox the launcher process diff -r afa6f810f693 -r 8bf1ce29152c src/dhcpcd.c --- a/src/dhcpcd.c Sun Sep 20 17:43:31 2020 +0100 +++ b/src/dhcpcd.c Sun Sep 20 19:09:08 2020 +0100 @@ -1417,16 +1417,7 @@ } if (sig != SIGCHLD && ctx->options & DHCPCD_FORKED) { - if (sig == SIGHUP) - return; - - pid_t pid = pidfile_read(ctx->pidfile); - if (pid == -1) { - if (errno != ENOENT) - logerr("%s: pidfile_read",__func__); - } else if (pid == 0) - logerr("%s: pid cannot be zero", __func__); - else if (kill(pid, sig) == -1) + if (sig != SIGHUP && kill(ctx->fork_pid, sig) == -1) logerr("%s: kill", __func__); return; } @@ -1769,9 +1760,16 @@ { struct dhcpcd_ctx *ctx = arg; int exit_code; + bool do_exit; ssize_t len; - len = read(ctx->fork_fd, &exit_code, sizeof(exit_code)); + if (ctx->fork_pid == 0) { + do_exit = false; + len = read(ctx->fork_fd, &ctx->fork_pid, sizeof(ctx->fork_pid)); + } else { + do_exit = true; + len = read(ctx->fork_fd, &exit_code, sizeof(exit_code)); + } if (len == -1) { logerr(__func__); exit_code = EXIT_FAILURE; @@ -1780,7 +1778,8 @@ __func__, len, sizeof(exit_code)); exit_code = EXIT_FAILURE; } - eloop_exit(ctx->eloop, exit_code); + if (do_exit) + eloop_exit(ctx->eloop, exit_code); } static void @@ -2156,7 +2155,7 @@ { ctx.options |= DHCPCD_FORKED; /* pretend child process */ #ifdef PRIVSEP - if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1) + if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx, NULL) == -1) goto exit_failure; #endif ifp = calloc(1, sizeof(*ifp)); @@ -2208,12 +2207,9 @@ ctx.options & DHCPCD_DUMPLEASE); if (ctx.control_fd != -1) { #ifdef PRIVSEP - ctx.options &= ~DHCPCD_FORKED; - if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1) { - ctx.options |= DHCPCD_FORKED; + if (IN_PRIVSEP(&ctx) && + ps_mastersandbox(&ctx, NULL) == -1) goto exit_failure; - } - ctx.options |= DHCPCD_FORKED; #endif if (!(ctx.options & DHCPCD_DUMPLEASE)) loginfox("sending commands to dhcpcd process"); @@ -2316,6 +2312,9 @@ logerr("fork"); goto exit_failure; case 0: + /* Inform the launcher of our pid as it's chrooted */ + pid = getpid(); + write(ctx.fork_fd, &pid, sizeof(pid)); break; default: ctx.options |= DHCPCD_FORKED; /* A lie */ @@ -2324,8 +2323,8 @@ } break; default: + setproctitle("[launcher]"); ctx.options |= DHCPCD_FORKED; /* A lie */ - setproctitle("[launcher]"); ctx.fork_fd = fork_fd[0]; close(fork_fd[1]); #ifdef PRIVSEP_RIGHTS @@ -2351,6 +2350,11 @@ eloop_event_add(ctx.eloop, ctx.stderr_fd, dhcpcd_stderr_cb, &ctx); } +#ifdef PRIVSEP + if (IN_PRIVSEP(&ctx) && + ps_mastersandbox(&ctx, "stdio proc") == -1) + goto exit_failure; +#endif goto run_loop; } @@ -2428,7 +2432,7 @@ eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx); #ifdef PRIVSEP - if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1) + if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx, "stdio route") == -1) goto exit_failure; #endif diff -r afa6f810f693 -r 8bf1ce29152c src/dhcpcd.h --- a/src/dhcpcd.h Sun Sep 20 17:43:31 2020 +0100 +++ b/src/dhcpcd.h Sun Sep 20 19:09:08 2020 +0100 @@ -122,6 +122,7 @@ bool stderr_valid; int stderr_fd; /* FD for logging to stderr */ int fork_fd; /* FD for the fork init signal pipe */ + pid_t fork_pid; const char *cffile; unsigned long long options; char *logfile; diff -r afa6f810f693 -r 8bf1ce29152c src/privsep.c --- a/src/privsep.c Sun Sep 20 17:43:31 2020 +0100 +++ b/src/privsep.c Sun Sep 20 19:09:08 2020 +0100 @@ -118,7 +118,8 @@ if (!(ctx->options & DHCPCD_FORKED)) logdebugx("chrooting to `%s' as %s", pw->pw_dir, pw->pw_name); - if (chroot(pw->pw_dir) == -1) + if (chroot(pw->pw_dir) == -1 && + (errno != EPERM || ctx->options & DHCPCD_FORKED)) logerr("%s: chroot `%s'", __func__, pw->pw_dir); if (chdir("/") == -1) logerr("%s: chdir `/'", __func__); @@ -517,11 +518,18 @@ } int -ps_mastersandbox(struct dhcpcd_ctx *ctx) +ps_mastersandbox(struct dhcpcd_ctx *ctx, const char *_pledge) { const char *sandbox = NULL; + bool forked; + int dropped; - if (ps_dropprivs(ctx) == -1) { + forked = ctx->options & DHCPCD_FORKED; + ctx->options &= ~DHCPCD_FORKED; + dropped = ps_dropprivs(ctx); + if (forked) + ctx->options |= DHCPCD_FORKED; + if (dropped == -1) { logerr("%s: ps_dropprivs", __func__); return -1; } @@ -537,7 +545,9 @@ } #endif - if (ps_entersandbox("stdio route", &sandbox) == -1) { + if (_pledge == NULL) + _pledge = "stdio"; + if (ps_entersandbox(_pledge, &sandbox) == -1) { if (errno == ENOSYS) { if (sandbox != NULL) logwarnx("sandbox unavailable: %s", sandbox); diff -r afa6f810f693 -r 8bf1ce29152c src/privsep.h --- a/src/privsep.h Sun Sep 20 17:43:31 2020 +0100 +++ b/src/privsep.h Sun Sep 20 19:09:08 2020 +0100 @@ -175,7 +175,7 @@ int ps_start(struct dhcpcd_ctx *); int ps_stop(struct dhcpcd_ctx *); int ps_entersandbox(const char *, const char **); -int ps_mastersandbox(struct dhcpcd_ctx *); +int ps_mastersandbox(struct dhcpcd_ctx *, const char *); int ps_unrollmsg(struct msghdr *, struct ps_msghdr *, const void *, size_t); ssize_t ps_sendpsmmsg(struct dhcpcd_ctx *, int,