chroot
在 Linux 系统上,既是一个系统管理命令 chroot(8)
,也是一个系统调用 chroot(2)
。为了叙述简单,且后面不会讨论
chroot(2)
,所以后面一律采用 chroot
表示 chroot(8)
。chroot
是 change root directory
的缩写,使用 chroot
命令能够以特殊的根目录去运行命令或者是交互式 shell。什么意思呢?在 Linux OS 上,根目录就是
/
,表示操作系统中目录结构的根节点。如果改变了根目录,那么所有的资源就只能从新的根节点开始去寻找。那不多说,我们先来运行一个实例看看。
root@1054e3f0a7ed:/# cd ~ root@1054e3f0a7ed:~# mkdir new_root root@1054e3f0a7ed:~# chroot new_root/ chroot: failed to run command '/bin/sh': No such file or directory
这里明明指定了一个新的
new_root
来作为 chroot
的新根目录,命令却执行报错了。这是因为
chroot
命令还需要指定后续的指令参数 chroot [OPTION] NEWROOT [COMMAND [ARG]...]
当我们不去指定指令时,它会默认地执行
$SHELL
-i
(default: /bin/sh
-i
)
略微思考一下,便可以知道,由于我们的新根目录下什么也没有,那么自然是找不到
/bin/sh
的。所以很自然的,我们会把
/bin/sh
复制到 new_root
下。但这是不够的,因为很多命令工具不是静态编译的,它们还需要对应的动态链接库才能够正常运行。
这个时候可以使用
ldd
命令来获取。这里就以
/bin/sh
为例,来看一下它的执行过程:root@1054e3f0a7ed:~# which sh /usr/bin/sh root@1054e3f0a7ed:~# mkdir new_root/bin root@1054e3f0a7ed:~# cp /usr/bin/sh new_root/bin/ root@1054e3f0a7ed:~# ldd /usr/bin/sh linux-vdso.so.1 (0x00007ffd39faa000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5a380e8000) /lib64/ld-linux-x86-64.so.2 (0x00007f5a382ef000) root@1054e3f0a7ed:~# mkdir new_root/{lib,lib64} root@1054e3f0a7ed:~# cp /lib/x86_64-linux-gnu/libc.so.6 new_root/lib/ root@1054e3f0a7ed:~# cp /lib64/ld-linux-x86-64.so.2 new_root/lib64/ root@1054e3f0a7ed:~# chroot new_root/ #
可以看出来,这次我们成功的切换到了新根目录,并且成功的在新根目录中启动了一个
shell
。有了
shell
后,我们就可以执行 shell
提供的内置命令了:# pwd / # cd .. # cd .. # cd .. # pwd / #
但我们似乎并没有办法跳出新根目录,这就意味着新根目录与之前的环境是隔离的,是不是有点容器的感觉了。
其实,到这里,基本的
chroot
命令就介绍得差不多了,下面我们再浅浅地挖掘一点点。chroot
到底是如何做到修改根目录的呢?其实它是通过修改进程的 root
指针实现的,我们可以通过查看进程的 /proc/<pid>/root
来查看对应进程是否处于 chroot
中。这里先使用
screen
开启一个 chroot
的进程,然后 detach
查看进程情况:root@ede0cf4b8cba:~# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 16:07 pts/0 00:00:00 bash root 209 1 0 16:09 ? 00:00:00 SCREEN root 210 209 0 16:09 pts/1 00:00:00 /bin/sh root 212 210 0 16:09 pts/1 00:00:00 /bin/sh -i root 318 1 0 16:10 pts/0 00:00:00 ps -ef
这里的
212
进程就是我们要找的。root@ede0cf4b8cba:~# ls -l /proc/212/root lrwxrwxrwx 1 root root 0 Dec 1 16:15 /proc/212/root -> /root/new_root
那么,
chroot
为什么没有用来做容器的实现呢?这就要扯出 chroot
的安全问题了,至于具体的那就以后再说了。最后,我们来列举一些常用的
chroot
使用场景。- 利用隔离性,可以有多个版本的开发环境、测试环境,即使这些版本是互斥的。
- 通过限制新根目录中的命令工具来提升安全性。比如一个只有应用程序的新根目录,由于没有
shell
等工具,所以即使被找到漏洞了也无法执行很多操作。
- 当系统损坏无法启动时,可以先用光碟启动,然后挂载原系统分区并
chroot
进入,然后对系统进行修复。
- 利用隔离性,提供只能访问特定目录的环境,比如
FTP
服务器。
- 利用隔离性,可以确保不受宿主机上的干扰,比如作为构建环境。
相关链接: