:(){ :|:& };:                         # 著名的 fork×××,系统执行海量的进程,直到系统僵死

fork×××

fork×××(fork bomb)在计算机领域中是一种利用系统调用fork(或其他等效的方式)进行的拒绝服务***。与病毒与蠕虫不同的是,fork×××没有传染性,而且fork×××会使对同时执行进程/程序数设限的系统无法执行新程序,对于不设限的系统则使之停止响应。以fork×××为代表的自我复制程序有时亦被称为wabbit。

fork×××的概念:进程递归式派生(fork,亦即自我复制),以使系统拒绝服务甚至崩溃

原理与影响


fork×××以极快的速度创建大量进程(进程数呈以2为底数的指数增长趋势),并以此消耗系统分配予进程的可用空间使进程表饱和,而系统在进程表饱和后就无法运行新程序,除非进程表中的某一进程终止;但由于fork×××程序所创建的所有实例都会不断探测空缺的进程槽并尝试取用以创建新进程,因而即使在某进程终止后也基本不可能运行新进程。fork×××生成的子程序在消耗进程表空间的同时也会占用CPU和内存,从而导致系统与现有进程运行速度放缓,响应时间也会随之大幅增加,以致于无法正常完成任务,从而使系统的正常运作受到严重影响。


除了恶意触发fork×××破坏的情况外,软件开发中有时也会不慎在程序中嵌入fork×××,如在用于监听网络套接字并行使客户端-服务器结构系统中服务器端职责的应用程序中可能需要无限地进行循环(loop)与派生(fork)操作(类似下节示例程序所示),而在这种情况下源代码内的细微错误就可能在测试中"引爆"fork×××。


折叠编辑本段示例


以下程序段就是由Jaromil所作的在类UNIX系统的shell环境下触发fork×××的shell脚本代码,总共只用了13个字符(包括空格):


:(){ :|:& };:


注解如下:


:() # 定义函数,函数名为":",即每当输入":"时就会自动调用{}内代码


{ # ":"函数开始标识


: # 用递归方式调用":"函数本身


| # 并用管道(pipe)将其输出引至...


: # 另一次递归调用的":"函数


# 综上,":|:"表示的即是每次调用函数":"的时候就会生成两份拷贝


& # 调用间脱钩,以使最初的":"函数被杀死后为其所调用的两个":"函数还能继续执行


} # ":"函数结束标识


; # ":"函数定义结束后将要进行的操作...


: # 调用":"函数,"引爆"fork×××


其中函数名":"只是简化的一例,实际实现时可以随意设定,一个较易理解(将函数名替换为"forkbomb")的版本如下:


forkbomb(){ forkbomb|forkbomb &} ; forkbomb


Windows下则可以批处理命令如下实现:


%0|%0


POSIX标准下的C与C++的实现:


#include <unistd.h>int main(){while(1) fork();return0;}


Perl语言的实现:


fork while fork


折叠编辑本段"熄火"


在系统中成功"引爆"fork×××后,我们可重启来使系统恢复正常运行;而若要以手动的方法使fork×××"熄火",那前提就是必须杀死fork×××产生的所有进程。为此我们可以考虑使用程序来杀死fork×××产生的进程,但由于这一般需要创建新进程,且由于fork×××一直在探测与占用进程槽与内存空间,因而这一方法几乎不可能实现,而且用kill命令杀死进程后,释放出的进程槽又会被余下的fork×××线程所产生的新进程占用,


在Windows下,用户可以退出当前用户会话的方式使系统恢复正常,但此法奏效的前提是fork×××是在该用户的特定会话内触发的。


折叠编辑本段预防


由于Fork Bomb通过不断的开新进程来瘫痪系统,一个防止其严重影响系统的方法就是限定一个用户能够创建的进程数的上限,在Linux系统上,可以通过ulimit这个指令达到相应的效果,例如: ulimit -Hu 30 这个指令可以限制每一个用户最多只能创建30个进程。而FreeBSD系统的话系统管理者可以在/etc/login.conf底下的设置档进行相关的设置