Soonts
Soonts

Reputation: 21956

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?

Upvotes: 1

Views: 1625

Answers (2)

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.

Upvotes: 1

Soonts
Soonts

Reputation: 21956

Implemented a workaround with named shared memory section with a pthread mutex in that.

Funfact: when the mutex is forcefully released because the owner process terminates, pthread_mutex_lock of the other process returns EOWNERDEAD code, however the mutex it’s no longer usable after that, subsequent pthread_mutex_lock on that mutex return 131 = EOTHER error code. Fortunately I’m only synchronizing 2 processes, so I’m OK just recreating the mutex in the same shared memory section.

Surprising amount of code to replicate a single WaitForSingleObject Win32 API :-(

Upvotes: 0

Related Questions