什么是 chroot
chroot 是作为系统调用引入 1979 年的 Unix V7 系统,目的是为了将当前进程及其子进程的 root 目录重定向到某个指定目录。1982 年,chroot 功能被加入到 BSD 中,后经 20 多年,FreeBSD 团队引入虚拟化技术的概念,在原本的 chroot 机制上,开发了新的 jail 机制。
简单来说:一个正在运行的进程经过 chroot 操作后,其根目录将被显式映射为某个指定目录,它将不能够对该指定目录之外的文件进行访问动作。这是一种非常简单的资源隔离化操作,类似于现在 Linux 的 Mount Namespace 功能。当年 Docker 刚开源的时候,有个人就利用 Linux 下 chroot 命令,用 100 多行的 Bash 代码实现了一个。
chroot 的使用
在现今的 Linux 上,chroot 既是一个 CLI 工具(chroot(8)
),又是一个系统调用(chroot(2)
)。
-
使用
chroot(8)
命令我们可以利用 Linux 下的
chroot(8)
命令来创建出一种类似于进入某个隔离容器内部的效果。chroot(8)
的用法很简单,格式如下所示:chroot [OPTION] NEWROOT [COMMAND [ARGS]...]复制代码
COMMAND 指的是切换 root 目录后需要执行的命令,如果没有指定,默认是
${SHELL} -i
,大部分情况是/bin/bash
。执行chroot(8)
需要使用 root 权限。简单地,我们可以这样使用:
$ sudo chroot /path/to/new/root /bin/bash复制代码
下面就让我们来建造我们的监狱(jail)(备注:基于 Ubuntu 16.04)。
-
创建对应的新的根目录
$ J=$HOME/jail$ mkdir -p $J$ mkdir -p $J/{bin,lib/x86_64-linux-gnu,lib64,etc,var}复制代码
-
将几个必要的命令工具 copy 到
bin/
下$ sudo cp -vf /bin/{bash,ls} $J/bin复制代码
-
将步骤 2 中可执行命令依赖的动态库 copy 到
jail/
下$ list=`ldd /bin/ls | egrep -o '/lib.*\.[0-9]'`$ for i in $list; do sudo cp -vf $i $J/$i; done$ list=`ldd /bin/bash | egrep -o '/lib.*\.[0-9]'`$ for i in $list; do sudo cp $i -vf $J/$i; done复制代码
-
执行 chroot 命令
$ sudo chroot $J /bin/bashbash-4.3# lsbin etc lib lib64 varbash-4.3# cd /bash-4.3# lsbin etc lib lib64 varbash-4.3# cd ..bash-4.3# lsbin etc lib lib64 var复制代码
无论我们如何改变目录,其根目录都被隔离在
$J
中,执行exit
命令可退出这一环境;
-
-
使用
chroot(2)
系统调用chroot(2)
的原型是:#include
int chroot(const char *path);复制代码 chroot()
将调用进程及其子进程的根目录指定为 path。执行该调用需要使用 root 权限。如以下代码所示:
#include
#include #include #include char *const patv[] = "/home/test/jail"; # 如上文实验所述目录char *const argv[] = { "/bin/bash", NULL};intmain(void) { if (chroot(path) != 0) { perror("chroot error"); exit(1); } chdir("/"); // 忽略返回值 execvp("/bin/bash", argv); // 忽略返回值 return 0;}复制代码 编译和运行代码:
$ gcc test_chroot.c -o test_chroot$ ./test_chroot # 非 root 用户执行命令chroot error: Operation not permitted$ sudo ./test_chrootbash-4.3#复制代码
-
如何获知某个进程是否处于 chroot 监禁
可通过查看进程的
/proc/<pid>/root
来查看对应进程是否处于 chroot 监禁中,如上文,其 chroot 下 bash 的执行进程为 15768,则有:$ sudo ls -ld /proc/15768/rootlrwxrwxrwx 1 root root 0 Apr 17 22:47 /proc/15768/root -> /home/test/jail复制代码
可见其根目录已经被修改为
/home/test/jail
。
chroot 的安全问题
chroot 机制从一开始就并非安全,存在很多安全漏洞,有不少「越狱」(jailbreak)的手段。