首页 > 解决方案 > 区分 uid 范围的 kill(-1,…) 和有针对性的 kill

问题描述

如果一个进程运行kill(-1,SIGKILL);(或使用不同的信号)并且调用杀死了调用者(MacOS 会这样做 kill(-1,...),尽管 Linux 会让调用者活着)但不是它的父进程(父进程有不同的 uid),那么父进程可以使用提供的设施POSIX,判断kill-caller是因为它在kill(-1,...)调用中杀死了自己还是因为另一个进程杀死了它而死亡?

标签: cposixsystem-callskill

解决方案


首先,如果您发送SIGKILL给进程,他们将永远看不到信号 - 他们只是被内核立即杀死。

否则,根据POSIX 标准的2.4.3 Signal Actions ,如果您的信号处理程序已使用SA_SIGINFO标志注册,您可以提取发送信号的进程的 PID:

如果SA_SIGINFO设置了信号标志,则信号捕获函数应作为 C 语言函数调用输入,如下所示:

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

其中func是指定的信号捕获函数,signo是正在传递的信号的信号编号,并且info是指向siginfo_t定义的结构的指针,该结构<signal.h>至少包含以下成员:

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.

si_signo成员应包含信号编号。这应与signo参数相同。si_code成员应包含识别信号原因的代码。为 定义了以下非信号特定值si_code

SI_USER 信号是由kill()函数发送的。如果信号由 or函数或作为实现扩展提供的任何类似函数发送,则实现可以设置si_code为。 信号是由函数发送的。 该信号是由 设置的计时器到期产生的。 该信号是由异步 I/O 请求的完成生成的。 该信号是由一条消息到达一个空消息队列而产生的。SI_USERraise()abort()SI_QUEUEsigqueue()SI_TIMERtimer_settime()SI_ASYNCIOSI_MESGQ

si_code还定义 了特定于信号的值,如 中所述<signal.h>

这应该提供足够的信息来判断信号是否是通过调用生成的kill()、发送信号的进程以及发送信号的人。或者,如果信号是由内部故障(例如SIGSEGV.


推荐阅读