}
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;
}
{
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;
__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
{
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));
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");
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 */
}
break;
default:
- ctx.options |= DHCPCD_FORKED; /* A lie */
setproctitle("[launcher]");
+ ctx.options |= DHCPCD_FORKED; /* A lie */
ctx.fork_fd = fork_fd[0];
close(fork_fd[1]);
#ifdef PRIVSEP_RIGHTS
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;
}
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
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__);
}
int
-ps_mastersandbox(struct dhcpcd_ctx *ctx)
+ps_mastersandbox(struct dhcpcd_ctx *ctx, const char *_pledge)
{
const char *sandbox = NULL;
-
- if (ps_dropprivs(ctx) == -1) {
+ bool forked;
+ int dropped;
+
+ 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;
}
}
#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);
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,