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


46

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

如何编写行为不同的Shell脚本,具体取决于它是否在chroot中运行?我的迫切需求是/proc安装在chroot中的现代Linux系统,该脚本以root身份运行,但也欢迎提供更多可移植的答案。(对于不带/ Linux的情况,请参阅如果未挂载/ proc,如何知道我正在chroot中运行?/proc

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

Answers:


45

我在这里所做的是测试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

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

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

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

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


1
这在OpenBSD中不起作用,因为它具有随机的PID ; 根进程基本上从不PID1。现在您知道为什么了!
亚当·卡兹

@AdamKatz“ ...有几个明显的例外,例如init(8)。” 那是什么呢?
muru

@muru:噢,嘘。你把我击倒了 我不确定为什么init(8)绝对需要#1插槽,除非有某种硬编码的性质要求它(我仍然不确定为什么)。当然,BSD不仅拥有chroot,而且拥有更多的高级监狱,所以我什至不确定这有多大问题。
亚当·卡兹

4
@AdamKatz相反:pid 1具有特殊作用(它必须收获僵尸,并且不受SIGKILL的影响)。初始化程序就是该角色的实现。我的答案在OpenBSD中不起作用的原因与此无关:这是因为OpenBSD没有类似Solaris / Linux的东西/proc。无论如何,我的答案不是要解决任何问题,而是要解决Linux。
吉尔斯(Gilles)“所以

@Gilles我认为OpenBSD将以某种方式被击败。不过,令我感到惊讶的是,所有这些特殊角色项都无法应用于任意PID(无后果),这就是我前面用斜体表示“为什么”的意思。
亚当·卡兹

22

便携式方法中找到索引节点编号从内部检测chroot监狱所述,您可以检查的索引节点编号是否/2

$ ls -di /
2 /

不同于2的inode编号表示表观根不是文件系统的实际根。这将不会检测恰好植根于安装点或具有随机根inode编号的操作系统上的chroot 。


这种启发式方法在哪些文件系统上起作用?
吉尔(Gilles)“所以,别再邪恶了”,

在ext3和hfs上测试。
2011年

因此,我在鬼混,我认为我发现了一种不需要根权限的更可靠的方法(仅适用于Linux)。我仍然愿意接受反例或更便携式的方法。
吉尔(Gilles)“所以,别再邪恶了”,

6
ext [234]确实如此,但并非所有文件系统都如此。它还仅测试您的根是否是文件系统的根,而该文件系统可能不会作为真正的根挂载。换句话说,如果您在/ jail和中安装了另一个分区chroot /jail,那么它将看起来像是此测试的真实根目录。
psusi 2011年

1
@AdamKatz显然不是。经过openbsd 6.0稳定测试,实际根路径的inode数仍为2,而chroot是一个随机数。
Dmitri DB

5

尽管显然不如这里列出的其他许多选项那样可移植,但是如果您使用的是基于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).
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.