在“chroot(2)”给定一些文件描述符后如何恢复旧根?

在“chroot(2)”给定一些文件描述符后如何恢复旧根?

chroot(2)在给它一些打开的文件描述符后,如何取回旧的根?

在下面的程序中,我首先打开文件描述符 to /,然后打开chroot(2)to.chdir(2)to /

但是,如果我然后chdir(2)到旧根目录fd,Python 会抱怨它无法打印当前工作目录getcwd(),因为它不存在。

为什么我无法将当前工作目录更改为旧根目录并打印?

这就是为什么我们有“pivot_root()”和“chroot()”,它们都可以用来做你想做的事情。您将新根挂载到其他位置,然后对其进行 chroot(或枢纽根)。然后你执行 'chdir("/")' 将 cwd 也移动到新的根目录中(只有在那时你才“丢失”旧的根目录 - 尽管如果你打开了一些文件描述符,你实际上可以将它找回来到它)。

https://yarchive.net/comp/linux/pivot_root.html

程序:

import os

print(f'cwd: {os.getcwd()}')

fd = os.open('/', os.R_OK, os.X_OK)

os.chroot('.')
os.chdir('/')

print(f'cwd: {os.getcwd()}')

os.chdir(fd)

print(f'cwd: {os.getcwd()}')

输出:

$ sudo python3 chdir_fd.py
cwd: /home/admin/projects/linux-pwn
cwd: /
Traceback (most recent call last):
  File "chdir_fd.py", line 14, in <module>
FileNotFoundError: [Errno 2] No such file or directory

答案1

我可以看到三个问题:

  • 您正在使用chdir(2)文件描述符。正确的系统调用应该是fchdir(2)

    尽管Python可能足够聪明,可以使用它来fchdir()代替。

  • 使用后fchdir(2)你必须chroot(2)再次这样你的当前目录又是里面当前的“已知空间”树。

  • 您无法区分结果getcwd()。在这两种情况下/,即使它不一样,你也会得到/。例如,您可以显示索引节点号(假设它是相同的文件系统,因此比较成立)或其他任何可能不同的内容。

在这里,根据上述更改,我从 debian bullseye/sid chroot 到 LXC Buster 容器的根目录中。我显示两次的内容/etc/debian_version

import os

print(f'cwd: {os.getcwd()}')

fd = os.open('/', os.R_OK, os.X_OK)

os.chroot('.')
os.chdir('/')

print(f'cwd: {os.getcwd()}')

debfd=open("/etc/debian_version","r")
print(debfd.read())
debfd.close()

os.fchdir(fd)
os.chroot('.')

print(f'cwd: {os.getcwd()}')

debfd=open("/etc/debian_version","r")
print(debfd.read())
debfd.close()

结果:

root@glasswalker:/var/lib/lxc/buster-amd64/rootfs# /tmp/chrootback.py 
cwd: /var/lib/lxc/buster-amd64/rootfs
cwd: /
10.8

cwd: /
bullseye/sid

琐事

可以滥用“未知空间”来逃离chroot() 没有保留了文件描述符。 2005 年的这个页面对此进行了描述:

如何摆脱 chroot() 监狱

除了给定代码中的两个问题(其中一个必须添加#include <stdlib.h>并更正第 62 行中的双引号拼写错误fprintf())之外,它在当今的 Debian(当然还有一些 *nixes)上仍然可以正常工作。

根据我的理解,似乎当处于“未知空间”时(即:当西德位于当前之外)然后我们可以盲目地回到实际的

相关内容