Skip to content
Advertisement

Get notified about process termination

I’m trying to use NETLINK with CN_IDX_PROC to monitor my process. This works but requires the monitoring process to be launched with root privileges.

I’ve tried to fix it by setting a capability in the filesystem on my monitoring executable (including CAP_AUDIT_READ, CAP_SYS_ADMIN,CAP_SYS_PTRACE and CAP_IPC_OWNER), but it didn’t work, bind() still fails saying “Operation not permitted” unless using sudo to start.

Is there a way to enable non-roots to use netlink connector sockets the way I want?

If no, is there any other reliable way to get notified when other (non child, running under different user account) process terminates? I don’t want to poll: it’s embedded software, I don’t have much resources, and I want to get notified ASAP. I especially want to get notified if the target process terminates abnormally, e.g. with segmentation fault, so I can’t rely on target process being cooperative.

On Windows I’d just create & lock a named mutex in the target process, and make the monitor process to sleep on it, mutexes are guaranteed to be released as soon as the owner process dies. Is there a similar IPC mechanism in Linux?

Advertisement

Answer

So you want to be notified about the termination of a process, e.g. running some program foo.

BTW, if that process behaves well, you might use atexit(3) inside the source code of foo. Then, if that program exits correctly (by calling exit(3) explicitly, or by returning from main; the crt0 is calling exit(3) in such case just after main returned), the registered routine is running when you want. But that foo process can sadly be terminated by some signal(7) (e.g. a segmentation fault, or some external kill(1) command, etc etc…), then of course _exit(2) is not happening (and neither is exit(3) ….).

So write a simplistic wrapper program (e.g. wrapfoo) which fork(2)-s then execve(2)-s foo in the child, and waitpid(2) in the parent. Then your wrapfoo is always notified of the end of foo (including when foo was terminated by some signal). It behaves as if it was a specialized “shell” to run foo (this is just for the explanation here, wrapfoo is not really a Unix shell).

(of course, you don’t want the process running wrapfoo to be terminated itself)

Coding that wrapfoo program is really simple. You should expect it to be correct. And you might (carefully) use setuid techniques to have them using different users (if you need that). Beware that setuid tricks are difficult and without care can open a security hole.

In some cases you might merge the C source code of wrapfoo with the code of foo but most of the time you don’t want to (separation of concerns principle). Especially if you use dangerous setuid techniques, you want your wrapfoo.c to be as simple as possible (and be able to prove that it works like you want it to).

Read some good book on Linux programming, e.g. download the old Advanced Linux Programming (also here; it is legally freely downloadable) or something newer. setuid techiques and all the subtilities behind fork(2), execve(2), waitpid(2) … are difficult to explain (so I won’t even try here). See also credentials(7).

Maybe you could use a fifo(7), use some advisory locking (e.g. flock(2) or lockf(3)…); the kernel releases them too when a process dies.

Advertisement