Search code examples
cposixsystem-callskill

Differentiating a uid-wide kill(-1,…) from a targetted kill


If a process runs kill(-1,SIGKILL); (or with a different signal) and the call kills the caller (MacOS's kill(-1,...) does that, though Linux's leaves the caller alive) but not its parent (the parent has a different uid), can the parent, using facilities provided by POSIX, tell if the kill-caller died because it killed itself with the kill(-1,...) call or because another process killed it?


Solution

  • First, if you send SIGKILL to the process(es), they'll never see the signal - they're just summarily killed by the kernel.

    Otherwise, per 2.4.3 Signal Actions of the POSIX standard, you can extract the PID of the process that sent the signal if your signal handler is registered with the SA_SIGINFO flag:

    If the SA_SIGINFO flag for the signal is set, the signal-catching function shall be entered as a C-language function call as follows:

    void func(int signo, siginfo_t *info, void *context);
    

    where func is the specified signal-catching function, signo is the signal number of the signal being delivered, and info is a pointer to a siginfo_t structure defined in <signal.h> containing at least the following members:

    Member Type    Member Name   Description
    int            si_signo      Signal number.
    int            si_code       Cause of the signal.
    pid_t          si_pid        Sending process ID.
    uid_t          si_uid        Real user ID of sending process.
    void *         si_addr       Address of faulting instruction.
    int            si_status     Exit value or signal.
    union sigval   si_value      Signal value.
    

    The si_signo member shall contain the signal number. This shall be the same as the signo parameter. The si_code member shall contain a code identifying the cause of the signal. The following non-signal-specific values are defined for si_code:

    SI_USER The signal was sent by the kill() function. The implementation may set si_code to SI_USER if the signal was sent by the raise() or abort() functions or any similar functions provided as implementation extensions. SI_QUEUE The signal was sent by the sigqueue() function. SI_TIMER The signal was generated by the expiration of a timer set by timer_settime(). SI_ASYNCIO The signal was generated by the completion of an asynchronous I/O request. SI_MESGQ The signal was generated by the arrival of a message on an empty message queue.

    Signal-specific values for si_code are also defined, as described in <signal.h>.

    That should provide enough information to tell if the signal was generated by a call to kill(), what process sent the signal, who sent the signal. Or if the signal was generated by an internal fault such as with a SIGSEGV.