Head First 0x00 | chroot
Head First 系列计划用于记录一些工具的简单使用方法以及有意思的概念。尽量做到由表及里,层层深入。后面如果未加说明,参考的 Linux 内核源码版本均为 4.10.10。
介绍
实验
以下实验以root
权限在/root
目录下进行。建立如下目录结构:
sandbox
|- hello.c
|- lib/
hello.c
即最简单的打印Hello, world
程序。
gcc -o hello hello.c
ldd hello
得到动态链接信息:
linux-gate.so.1 => (0xb7778000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75be000)
/lib/ld-linux.so.2 (0xb7779000)
为了保证chroot
后程序能正确找到动态链接器和动态链接库:
cp /lib/i386-linux-gnu/libc.so.6 ./sandbox/lib
cp /lib/ld-linux.so.2 ./sandbox/lib
测试如下,因为原来的根目录下无hello
程序,所以第一次运行失败:
原理
就这个工具来讲,应该是使用了 API chroot()
,可参考man 2 chroot
。
我写了个简单的mychroot
,同样有效:
更深层次的原理:猜测是更改了进程图像的task_struct->fs->root
。
验证
它依赖的头文件是<unistd.h>
找到/usr/include/linux/unistd.h
:
找到/usr/include/asm-generic/unistd.h
:
#define __NR_chroot 51
__SYSCALL(__NR_chroot, sys_chroot)
好吧,是一个系统调用,看内核源码。
这是一个一参的系统调用,所以应该是用SYSCALL_DEFINE1
宏定义来定义的。一开始我找不到源码中对sys_chroot
的定义在哪里,后来看了【参考】的文章才知道新的内核中对系统调用的统一调用方式是SYSCALL_DEFINEX
,这里的X
是参数个数。【参考】的文章非常好,有理有据,推荐阅读。
在fs/open.c
中:
在各种检查之后,注意这一句:
可以跟进一下,在fs/fs_struct.c
中:
猜对了。
参考