Mercurial > hg > dhcpcd
changeset 5466:8bf1ce29152c draft
privsep: sandbox the launcher process
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Sun, 20 Sep 2020 19:09:08 +0100 |
| parents | afa6f810f693 |
| children | 49e119831377 |
| files | src/dhcpcd.c src/dhcpcd.h src/privsep.c src/privsep.h |
| diffstat | 4 files changed, 40 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- 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
--- 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;
--- 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);
--- 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,
