我怎么知道我在 chroot 中运行?

Gil*_*il' 52 chroot

我有一个 unix 安装,它应该可以用作 chroot 和独立系统。如果它作为 chroot 运行,我不想运行任何服务(cron、inetd 等),因为它们会与主机系统发生冲突或变得多余。

如何编写根据是否在 chroot 中运行而行为不同的 shell 脚本?我的迫切需要是一个现代 Linux 系统,它/proc安装在 chroot 中,并且脚本以 root 身份运行,但也欢迎更多可移植的答案。(如果 /proc 未安装,请参阅如何判断我正在 chroot 中运行?对于没有/proc.的 Linux 的情况。)

更一般地说,适用于其他收容方法的建议会很有趣。实际问题是,这个系统是否应该运行任何服务?(答案在 chroot 中是否定的,在成熟的虚拟机中是;我不知道诸如 jails 或容器之类的中间情况。)

Gil*_*il' 55

我在这里所做的是测试init进程的根(PID 1)是否与当前进程的根相同。虽然/proc/1/root总是一个链接/(除非init它自己被 chroot 了,但这不是我关心的情况),跟随它会导致“主”根目录。此技术用于 Debian 中的一些维护脚本,例如在 chroot 中安装后跳过启动 udev。

if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
  echo "We are chrooted!"
else
  echo "Business as usual"
fi
Run Code Online (Sandbox Code Playgroud)

(顺便说一下,chroot如果 chrooted 进程具有 root 访问权限,那么这又是为什么对安全无用的另一个例子。非 root 进程无法读取/proc/1/root,但/proc/1234/root如果有一个 PID 1234 的正在运行的进程以相同的方式运行,它们可以跟随用户。)

如果您没有 root 权限,您可以查看/proc/1/mountinfo/proc/$$/mountinfofilesystems/proc.txt在 Linux 内核文档中简要介绍)。这个文件是世界可读的,并且包含了大量关于文件系统进程视图中每个挂载点的信息。该文件中的路径受到影响读取器进程的 chroot 的限制(如果有)。如果进程读取/proc/1/mountinfo使用chroot到文件系统,是从全球根不同(假设PID 1根是全球根),则不适合入门/的出现/proc/1/mountinfo。如果进程读取/proc/1/mountinfo被 chroot 到全局根文件系统上的目录,则 中会/出现一个条目/proc/1/mountinfo,但具有不同的挂载 ID。顺便说一下,根字段($4) 表示 chroot 在其主文件系统中的位置。

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]
Run Code Online (Sandbox Code Playgroud)

这是一个纯 Linux 解决方案。它可以推广到具有足够相似性的其他 Unix 变体/proc/proc/1/root我认为Solaris 有一个类似的,但不是mountinfo)。

  • @AdamKatz 恰恰相反:pid 1 具有特殊作用(它必须收割僵尸,并且对 SIGKILL 免疫)。init 程序是该角色的实现。我的答案在 OpenBSD 中不起作用的原因与此无关:这是因为 OpenBSD 没有像 Solaris/Linux 的 `/proc` 那样的东西。无论如何,我的回答并不是要解决任何问题,而是要解决 Linux。 (5认同)
  • @Vouze 不,安装 `/proc` 并不是一个安全缺陷,因为 chroot 本身并不是一个安全机制。仅当 chroot 中运行的进程使用与 chroot 外部运行的进程不同的用户 ID 运行时,您才能从 chroot 获得安全性。否则,chroot 无法保护您,例如,防止某个进程杀死或跟踪在 chroot 之外运行的另一个进程。在这种情况下,`/proc/$pid/root` 不允许绕过 chroot。 (2认同)

l0b*_*0b0 24

正如Portable way to find inode numberDetecting a chroot jail from inside 所述,您可以检查 inode 编号是否/2

$ ls -di /
2 /
Run Code Online (Sandbox Code Playgroud)

不同于 2 的 inode 编号表示明显的根不是文件系统的实际根。这不会检测碰巧植根于挂载点或具有随机根 inode 编号的操作系统上的 chroot 。

  • 这适用于 ext[234],但并非适用于所有文件系统。它还只测试您的根是文件系统的根,它可能不会作为真正的根挂载。换句话说,如果你在 /jail 和 `chroot /jail` 中挂载另一个分区,那么它看起来就像这个测试的真正根。 (6认同)

tho*_*nic 10

虽然显然不如此处列出的许多其他选项可移植,但如果您使用的是基于 Debian 的系统,请尝试ischroot.

请参阅:https : //manpages.debian.org/jessie/debianutils/ischroot.1.en.html

要直接在控制台中获取状态,请使用 ischroot:

ischroot;echo $?

退出代码:

0 if currently running in a chroot
1 if currently not running in a chroot
2 if the detection is not possible (On GNU/Linux this happens if the script is not run as root).
Run Code Online (Sandbox Code Playgroud)

  • 由于`ischroot`是OSS(在GPL2下),你可以从官方(目前[这里](https://packages.debian.org/buster/debianutils))和`./configure &amp;&amp; make ischroot`下载源代码到编译它。在 Arch Linux 下测试。 (2认同)