fork bomb 介绍

下面就是一个最简单的 bash fork 炸弹:

: () { : | : & } ; :

上面几个符号看上去很复杂,其实如果写成下面这个样子就好懂了,: 是函数名,执行一个调用自己的递归并且 pipe 到自己,& 表示后台执行程序,最后的一个 : 是在函数外调用和执行 : () 这个函数的意思:

: () {
    : | : &
}; :


上面几个符号看上去很复杂,其实如果写成下面这个样子就好懂了,: 是函数名,执行一个调用自己的递归并且 pipe 到自己,& 表示后台执行程序,最后的一个 : 是在函数外调用和执行 : () 这个函数的意思:

: () {
    : | : &
}; :

如何避免 fork 炸弹呢?方法很简单,只要限制每个用户可以调用的进程数就可以避免,这个可以通过修改 vi /etc/security/limits.conf 文件来设定:

# vi /etc/security/limits.conf

vpsee           hard    nproc           32
@student        hard    nproc           32
@faculty        hard    nproc           64

上面的配置文件意思是说限制 vpsee 这个用户只能 fork 32 个进程;然后限制 student 这个用户组的每个成员最多能 fork 32 个进程;限制 faculty 这个用户组的每个成员最多能 fork 64 个进程。不过要事先检查系统是否有 pam_limits.so 这个模块以及是否已经加载:

# ls /lib64/security/pam_limits.so
/lib64/security/pam_limits.so

# vi /etc/pam.d/login
session    required     pam_loginuid.so

如果自己是 Linux 普通用户,不是 root 用户不能修改 limits.conf 和重启系统的话,可以用 ulimit 来临时限制自己允许创建的进程数,ulimit 有 Hard 和 Soft 两种方法限制,用 Hard 的话可以减少最大可用的进程数,但是就不能重新增大这个限制了;用 Soft 的话可以自己自由增大和减小限制(ulimit,-H 和 -S 的详细说明可以参看 man ulimit)。不同的 Linux 版本对这个 ulimit -u 的默认值不同,在 CentOS 上默认情况下最大运行进程数是 8256,在 Fedora 上是 1024,所以这个要看不同的发行版本,不过这个无所谓,反正可以改,不过改成32后就不能再改成比32更大的了(比如64),只能再改成比32小的,ulimit 不带 -H 和 -S 参数的时候同时设置 Hard 和 Soft:

$ ulimit -u
8256
$ ulimit -u 32
$ ulimit -u 64
-bash: ulimit: max user processes: cannot modify limit: Operation not permitted

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 8256
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 32
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited


还是晕晕的?再换一下就更好理解了。

a()
{
a|a&
};
a

简化一下,先定义一个函数a,再运行a。a函数里面递归调用自身a,并且利用管道fork一个子bash进程在后台运行a。

于是,运行a的后果是当前的bash陷入a的死循环,不断的fork,而且fork出来的子进程又都做同样的事,这样要不了一会儿,栈空间挂了,进程列表也会挂,系统就要崩溃了。

:(){ :|:& };:这个我刚开始也让我困惑,不知道bash里:可以用做函数名。还有:在bash里是builtin,具体可以info :看到其作用。

有必要了解bash解释命令的顺序

  1. Aliases
  2. Keywords such asfunctionand several others, likeifandfor
  3. Functions
  4. Built-ins likecdandtype
  5. Scripts and executable programs, for which the shell searches in the directories listed in thePATH

environment variable bash中函数优先内置命令,于是:被当作函数解释了。


你可能感兴趣的:(linux,centos,shell,File,user,bash)