我如何知道我正在 chroot 中运行?

我如何知道我正在 chroot 中运行?

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

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

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

答案1

我在这里所做的是测试进程的根init(PID 1)是否与当前进程的根相同。虽然/proc/1/root始终是一个链接/(除非init它本身被 chroot,但这不是我关心的情况),但跟随它会导致“master”根目录。此技术用于 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

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

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

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]

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

答案2

正如中提到的查找 inode 号的便携式方法从内部检测 chroot 监狱,可以检查inode号是否/2

$ ls -di /
2 /

索引节点号不同于 2 表示表观根不是文件系统的实际根。这不会检测碰巧以挂载点或具有随机根索引节点号的操作系统

答案3

虽然显然不如此处列出的许多其他选项那么便携,但如果您使用的是基于 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).

答案4

这只是一个偶然的观察。但是,如果您可以使用 FUSE 访问任何内容,那么您可以挂载某些内容,然后使用mount显示挂载路径,该路径将以 chroot 路径为前缀显示。

例如,在 Github Actions Mac 运行器上,您可以执行以下操作:

pip install --user ratarmount
folder=$(mktemp -d)
mountedFolder=$(mktemp -d)
# simple bind mount a folder
ratarmount "$folder" "$mountedFolder"

现在mount将打印如下内容:

TarMount on /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/tmp.P5g4TomF (macfuse, nodev, nosuid, synchronous, mounted by runner)

即使mountedFolder变量中的完整路径是:/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/tmp.P5g4TomF。因此,我们似乎已经根深蒂固了/private

因为这个 hackymountpoint命令替代品使用mount并且grep对我不起作用。

相关内容