我拥有一个进程,其文档声称我可以发送SIGABRT
到该进程以获得一些调试信息。但是,当我尝试发送时SIGABRT
,我返回“不允许操作”。
我还尝试向我拥有的其他进程发送相同的信号,以确保没有某些底层块阻止我SIGABRT
完全发送,但它们以适当的方式响应。这只是一个程序,但它是该程序的每个实例。该进程的系统调用跟踪显示它从未收到该信号。
我尝试/bin/kill
显式运行,以排除 shell 内置的任何奇怪现象kill
,并且,除了一些细微的输出差异之外,行为没有任何变化。
root 可以发送SIGABRT
到进程并且它按我的预期工作。
我玩这个游戏已经有一段时间了,但我从未见过用户无法向他拥有的进程发送信号的实例,也没有见过用户可以发送一个信号但不是另一个。
操作系统是 FreeBSD 9.0,该进程是一个 ruby 进程,是在 Apache 下运行的 Phusion Passenger Ruby-on-Rails 应用程序的一部分。
我目前完全不知所措。有谁知道发生了什么事吗?
更新:根据手册页,事实证明security.bsd.conservative_signals
sysctl 设置为 1,这会阻止许多信号传递到 setuid 进程。将其设置为 0 即可解决该问题。
虽然在进程链的某个地方有一个 setuid 调用——该进程是 Apache httpd 的子进程,并且 Apache 更改其 uid 以放弃 root 权限——但该进程本身不是 setuid,它的 EUID、RUID 和 SVUID 都是与发送信号的用户相同。我能找到的唯一可以表明发生任何 setuid 的进程检查是“flags”字段P_SUGID
中的标志。 ps
(“自上次执行以来已设置 id 权限”)似乎不应该是这样,但它是在 Apache 模块中处理的,我不知道它的确切方法。
需要说明的是,它是一个 ruby 进程,作为 Ruby on Rails 应用程序的一部分运行,由 mod_passenger(又名 mod_rails)处理。
答案1
要使进程有权向 pid 指定的进程发送信号,用户必须是超级用户,或者接收进程的真实或保存的用户 ID 必须与发送进程的真实或有效用户 ID 相匹配。一个例外是信号 SIGCONT,它可能始终被发送到与发送方具有相同会话 ID 的任何进程。此外,如果 security.bsd.conservative_signals sysctl 设置为 1,则用户不是超级用户,并且接收者为 set-uid,则只能发送作业控制和终端控制信号(特别是,只能发送 SIGKILL、SIGINT、SIGTERM、SIGALRM、SIGSTOP、SIGTTIN、SIGTTOU、SIGTSTP、SIGHUP、SIGUSR1、SIGUSR2)。
您在什么意义上拥有该流程?与真实 uid、有效 uid、正在运行的二进制文件、该二进制文件的所有者和 setid 位等相关的进程状态到底是什么?