errno = oerrno;
}
-/* if parent gets a SIGCHLD, it will exit */
+/* If priv parent gets a SIGCHLD, it will exit if this is the monitored
+ * process. Other processes (including lldpcli)) are just reaped without
+ * consequences. */
static void
sig_chld(int sig)
{
int rc = waitpid(monitored, &status, WNOHANG);
if (rc == 0) {
while ((rc = waitpid(-1, &status, WNOHANG)) > 0) {
- if (rc == monitored) priv_exit_rc_status(rc, status);
+ if (monitored != -1 && rc == monitored)
+ priv_exit_rc_status(rc, status);
}
return;
}
- priv_exit_rc_status(rc, status);
+ if (monitored != -1)
+ /* Monitored process not here anymore */
+ priv_exit_rc_status(rc, status);
}
/* Initialization */
#ifdef ENABLE_PRIVSEP
gid_t gidset[1];
- int status;
/* Spawn off monitor */
if ((monitored = fork()) < 0)
fatal("privsep", "unable to fork monitor");
.sa_flags = SA_RESTART
};
sigaction(SIGCHLD, &child, NULL);
-
- if (waitpid(monitored, &status, WNOHANG) != 0)
- /* Child is already dead */
- _exit(1);
+ sig_chld(0); /* Reap already dead children */
priv_loop(pair[1], 0);
exit(0);
}
#else
+ const struct sigaction child = {
+ .sa_handler = sig_chld,
+ .sa_flags = SA_RESTART
+ };
+ sigaction(SIGCHLD, &child, NULL);
+ sig_chld(0); /* Reap already dead children */
log_warnx("priv", "no privilege separation available");
priv_ping();
#endif