I write C application that calls fork()
to create child processes. The application runs as root. In the parent process, I use wait()
for waiting terminated child processes. In child processes, I use prctl()
with PR_SET_PDEATHSIG
option to detect the death of the parent. It works fine. To reduce the risk of security issues, child processes call setuid()
to change UID. The problem is: child processes can not detect the death of the parent one any more.
I have searched around to find the answer and found some useful links, but it does not help:
prctl
related) : although this link contains a clear answer, there is no solution.How to do that correctly?
I just stumbled upon the same issue, the kernel resets the PDEATH
signal on credential change:
https://github.com/torvalds/linux/blob/master/kernel/cred.c#L450
This can be verified with the following code and strace -f
:
#include <sys/prctl.h>
#include <unistd.h>
#include <signal.h>
int main(int argc, char *argv[])
{
if (fork() == 0) {
// This works as expected
setgid(1000);
setuid(1000);
prctl(PR_SET_PDEATHSIG, SIGTERM);
// This doesn't work since pdeath_signal will be reset
// setgid(1000);
// setuid(1000);
pause();
}
sleep(1);
kill(getpid(), SIGTERM);
return (0);
}
Just a hint for anyone still having the same issue. If the circumstances of process death aren't important (exit code and/or signal) there is work around. One can detect a process death by secondary indicators. One can rely on the *nix feature that guarantees that on exit each process closes all of its descriptors. Knowing this one can create a simple pipe, where each end is shared by each party.
Then, a simple select on one end of the pipe will detect an event of the other end being closed (process exit). It's very common in this case to already have some communication line between parent and child (stdin/stdout/strderr or a custom pipe/unix-socket). In which case this is all that is needed here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With