From: Vincent Bernat Date: Fri, 20 Oct 2017 06:42:01 +0000 (+0200) Subject: priv: correctly handle lldpcli exit X-Git-Tag: 0.9.9~6^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=635724519137dde5adc749f6320f225373fd63d5;p=thirdparty%2Flldpd.git priv: correctly handle lldpcli exit When lldpcli exits, we must acknowledge its death with `waitpid()`. There were two missing cases: - when lldpcli exits before setting the SIG_CHLD signal - when privilege separation was not configured For the first case, we call the function associated to the signal ourselves after the signal is configured. This function is idempotent. For the second case, we setup the SIG_CHLD signal even when privilege separation is disabled. Fix #250 --- diff --git a/src/daemon/priv.c b/src/daemon/priv.c index 92c68d87..2412d80d 100644 --- a/src/daemon/priv.c +++ b/src/daemon/priv.c @@ -488,7 +488,9 @@ sig_pass_to_chld(int sig) 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) { @@ -496,11 +498,14 @@ 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 */ @@ -599,7 +604,6 @@ priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid) #ifdef ENABLE_PRIVSEP gid_t gidset[1]; - int status; /* Spawn off monitor */ if ((monitored = fork()) < 0) fatal("privsep", "unable to fork monitor"); @@ -657,14 +661,17 @@ priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid) .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