我正在尝试检测一个叉炸弹,并且通过该过程我试图计算每个进程的后代数。但是,我只想计算非系统进程的后代计数,因为fork炸弹将是一个非系统进程。但是,我不确定该怎么做。这就是我到目前为止所做的:
struct task_struct *pTask;
for_each_process(pTask)
{
struct task_struct *p;
*p = *pTask;
//trace back to every ancestor
for(p = current; p != &init_task; p->parent)
{
//increment the descendant count of p's parent
}
}
这个循环适用于init
任务正确,因为它是&init_task
?有没有办法转而去第一个系统进程并停止?例如,叉炸弹将成为系统进程的直接子进程。任何帮助将不胜感激,谢谢!
[编辑]
通过系统过程,我的意思是像bash
之类的东西。我应该更清楚地解释一下,但在基本级别,我不想删除任何从启动运行的进程。从启动后运行的用户空间开始的任何进程都是合理的游戏,但其他进程则不然。我不会检查tomcat
,httpd
之类的内容,因为我100%知道这些进程不会运行。
答案 0 :(得分:1)
登录bash
shell由另一个进程exec
编写(该进程取决于它是否是控制台登录shell,ssh登录shell,gnome-terminal shell等)进程{{ 1}} exec
bash
由exec
init
或init
启动的其他进程,而不是内核。
用户可以轻松创建一个自行分析的bash脚本,因此如果您从检查中免除/bin/bash
,则无法检测到用bash编写的fork炸弹。例如,以下脚本放在名为foo
的文件中并在当前目录中执行,将创建一个fork炸弹。
#!/bin/bash
while [ /bin/true ]
do
./foo &
done
如果您想限制特定用户可以投放的流程数,请查看bash(1)或setrlimit(2)中的ulimit
。
或者,您可以为触发查杀进程的后代计数设置一个非常高的阈值。如果返回init
的父母链数百深,那么可能会发生一些可疑的事情。
答案 1 :(得分:1)
您可以使用logind / ConsoleKit2 D-Bus API通过其PID确定进程的会话。 "系统"进程(IIRC)将没有会议。
显然这需要logind(Systemd的一部分)或ConsoleKit2正在运行。
如果没有跟踪用户会话的服务,可能没有可靠的方法来区分"系统"来自用户进程的进程,除了user-id之外(假设你的fork炸弹不能作为系统用户运行)。在许多发行版上,系统用户ID小于1000,常规用户ID>&= 1000,除了" nobody"用户(通常为65534)。