linux 命令分析之 chroot 的原理

chroot 的功能

chroot 可以用来切换当前进程的【根目录】,它能够将当前进程能够访问的目录树结构限制
在某个子目录中,同时由于当前进程创建的子进程将会继承父进程的根目录结构,所以子进
程也随之被限定。

chroot 命令的原理

通过 strace 来跟踪一次 chroot 命令执行过程来研究其代码执行过程。

这里我删除了与这个问题没有太大关系的一些输出,重要的系统调用信息如下:

[root@localhost new_test]# strace chroot . sh
execve("/usr/sbin/chroot", ["chroot", ".", "sh"], 0x7fffbf1a9580 /* 28 vars */) = 0
..............................
chroot(".")                             = 0
chdir("/")                              = 0
execve("/usr/local/sbin/sh", ["sh"], 0x7fff5cd3d1a8 /* 28 vars */) = -1 ENOENT (没有那个文件或目录)
execve("/usr/local/bin/sh", ["sh"], 0x7fff5cd3d1a8 /* 28 vars */) = -1 ENOENT (没有那个文件或目录)
execve("/usr/sbin/sh", ["sh"], 0x7fff5cd3d1a8 /* 28 vars */) = -1 ENOENT (没有那个文件或目录)
execve("/usr/bin/sh", ["sh"], 0x7fff5cd3d1a8 /* 28 vars */) = 0
.............................

上述过程可以总结为如下几个步骤:

  1. execve 运行 chroot 程序
  2. chroot 系统调用切换当前命令的根目录
  3. chdir 系统调用切换当前命令的工作目录到新的根目录
  4. 根据路径搜索默认 shell 的位置,使用 execve 进行执行

这里它搜索默认 shell 的路径时有几个备选路径,搜索顺序如下:

  1. /usr/local/sbin/sh
  2. /usr/local/bin/sh
  3. /usr/sbin/sh
  4. /usr/bin/sh

从上面的捕获到的 chroot 命令的系统调用可以看到 chroot 命令的核心其实就是调用
chroot 系统调用,这也就是其内核态的主要行为,这个行为并不是直接完成这项功能
的,它实际是通过一种间接的方式修改 task_struct 中的数据结构来达成的。

为什么 chroot 要 chdir 到 “/” 目录中呢?

细心的读者也许会注意到 chroot 在执行了 chroot 系统调用后,又调用了 chdir 切换
【当前目录】到【新的根目录】的行为,这个行为是必不可少的!

chdir 系统调用将会修改当前进程 task_sturct fs 中的 pwd 字段,这个字段保存了当前工作
目录的 dentry 结构体。

核心代码如下:

	set_fs_pwd(current->fs, &path);

如果 chroot 命令不 chdir 到 “/” 目录,那么我们仍旧可以在 chroot 后的程序中通过访问到
外界的目录
,这样就会出现非常好玩的情景。

不让 chroot 执行 chdir 过程的测试

为了验证这点,我进行了如下几个尝试。

1. 指定 --skip-chdir 参数

chroot 命令中有一个 –skip-chdir 参数,在根目录中运行如下命令来使用它:

[root@localhost /]# /root/chroot --skip-chdir /root/chroot_environment/ sh
/root/chroot: option --skip-chdir only permitted if NEWROOT is old '/'

这里报错信息表明 –skip-chdir 只在新的 root 目录与老的根目录相同时才被允许使用

2. 修改 chroot 命令源码

chroot 命令在 coreutils 包中,执行 sudo apt-get source coreutils 来下载,其源
码在 src/chroot.c 中,对代码进行如下修改让 chroot 不执行 chdir 操作:

#if 0
  if (! skip_chdir && chdir ("/"))
    die (EXIT_CANCELED, errno, _("cannot chdir to root directory"));
#endif

终端中测试不执行 chdir 的 chroot

重新编译后运行,在终端中执行如下命令:

[root@localhost /]# /chroot /root/chroot_environment sh
(unreachable)/ # ls
bin     chroot  etc     lib     media   opt     root    sbin    sys     usr
boot    dev     home    lib64   mnt     proc    run     srv     tmp     var
(unreachable)/ # chroot .
[root@localhost /]# ls
bin  boot  chroot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@localhost /]# exit
exit
(unreachable)/ # cd ./root
sh: cd: can't cd to ./root: No such file or directory
(unreachable)/ # cd /root
~ # cd ..
/ # ls
bin    dev    etc    lib64  proc   root   sys    usr    var
/ #

第一行命令切根后,由于没有 chdir 到新的根目录,cwd 中仍然保存了旧的工作目录的
dentry 信息
,这样我们仍旧能够访问到旧的根目录下的所有文件,第二行的 ls 命令的
输出信息证实了这点。

第三行命令继续执行了 chroot,注意这里的参数为 .. 表示当前目录,这行命令执行后,又
切回了原来的根目录。

第四行命令从第三行命令的 chroot 环境中退出,退出后尝试 cd ./root,发现会报这个目录
不存在的错误。

通过 strace 跟踪这个 sh,发现它传递给 chdir 系统调用的命令并不是 ./root,而是 "
(unreachable)/root",这个目录当然不存在喽,就报了目录不存在的错误。

相关的系统调用内容如下:

chdir("(unreachable)/root")             = -1 ENOENT (没有那个文件或目录)
write(2, "sh: ", 4)                     = 4
write(2, "cd: ", 4)                     = 4
write(2, "can't cd to ./root: No such file"..., 45) = 45

单独编写了一个调用 chdir(“root”) 的代码编译后运行测试,确认能够 chdir,看来应该是 sh
进行了某种处理。

sh 中对当前目录的处理

这里添加的 (unreachable) 是 PS1 变量控制的,查看 manual 确定这个字符串实际上对
应的是当前的工作目录。相关信息如下:

\w     当前工作目录

我当前 shell 的 PS1 设定如下:

(unreachable)/ # echo $PS1
\w \$

看来 sh 执行的时候应该是通过当前目录的变量将我输入的 ./ 展开了,这样就有上面的
问题了。

chdir 到 /root 后切到新的根目录,完成 chroot 的所有过程

第五行命令中 cd /root 成功,这是肯定的,因为当前进程的根目录已经切换了,所以我们能
够进入到这个 /root 目录,而且这个目录也是新的目录。

第六行命令中 cd … 返回根目录,然后运行 ls 命令,可以看到此时根目录下的文件已经变
了,直至这里才完成了 chroot 的所有过程。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux chroot是一种将进程限制在特定目录下的技术,可以用来增强系统的安全性和稳定性。通过chroot,可以将进程的根目录切换到指定的目录下,使得进程无法访问系统的其他部分。这样可以有效地防止进程对系统的破坏,同时也可以保护系统的敏感数据。chroot技术在Linux系统中得到广泛应用,特别是在Web服务器等需要保护数据安全的场合。 ### 回答2: Linux下的chroot是一个非常有用的工具,它可以使用户在系统中创建一个与主系统隔离的环境,这个环境中只有特定的二进制文件、库、配置文件和资源。这个环境会在一个新的根目录下运行,并限制用户只能使用这个目录下的文件和命令。这种工具可以用来为不同的应用程序创建自己的组件,以便可以在相同的Linux系统上安装和运行不同版本和不同偏好的软件,而不会因为某个应用程序使用了错误的库而出现问题。 chroot在许多情况下是非常有用的,例如当你需要在一个系统上运行两个不同的版本的MySQL服务器时。你可以使用chroot来创建MySQL的独立环境,并且让每个环境有它自己的库和系统资源。这样,即使其中一个MySQL服务器发生故障,另一个环境也可以继续运行。chroot还可以帮助你创建一个沙箱环境,当你需要测试软件或者运行一些危险的命令时,你可以把它们放在独立的环境中,防止对主系统造成安全隐患。 总体来说,chroot是一个非常有用的工具,它为Linux用户提供了更大的灵活性和安全性。当你需要为不同的应用程序或者用户创建单独的环境时,它是一个不可或缺的工具。 ### 回答3: Linux chroot是一种在Linux系统中提供的操作,它可以让用户将特定的进程或应用程序运行在一个隔离环境中,该环境包含了一套独立的文件系统、用户身份和进程间通信机制。这种技术可以很好地实现系统安全,同时也有助于应用程序开发、调试和测试等方面的工作。 Linux chroot最初是在UNIX系统中提出的,意思是ChangeRoot,即改变根目录。在Linux系统中,chroot可以使用chroot指令来实现。它主要通过改变进程的根目录为一个新的目录,来将进程所使用的文件系统与整个系统的文件系统隔离开来。 chroot的另一个重要的应用领域就是用户环境隔离。在Linux系统中,每个用户都有自己的home目录,当用户登录到系统时,所有的进程都会在/home/username目录下运行。但有时候我们需要将用户的进程放在一个独立的文件系统中运行,这个时候就需要使用chroot了。使用chroot后,所有的文件和程序都只能在新的目录中使用,相当于将用户隔离在一个独立的环境中,降低了系统被攻击的风险。 由于chroot可以将整个文件系统移动到一个隔离的环境中,它也可以非常方便地用于应用程序的开发、测试和调试。在开发应用程序时,我们可以使用chroot将应用程序的环境与主机的环境隔离开来,这样可以保证程序的稳定性,并且可以在隔离环境中进行测试。 总的来说,Linux chroot是一种非常有用的技术,它可以为系统安全、用户隔离和应用程序开发提供帮助,是Linux系统中不可或缺的一部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值