給定一些文件描述符後,如何在“chroot(2)”之後恢復舊根?
chroot(2)
在給它一些打開的文件描述符後,我怎樣才能找回舊的根?在下面的程序中,我首先打開一個文件描述符 to
/
,然後打開chroot(2)
to.
和chdir(2)
to/
。但是,如果我再到
chdir(2)
舊根目錄fd
,Python 會抱怨它無法列印目前工作目錄getcwd()
,因為它不存在。為什麼我不能將目前工作目錄更改為舊根目錄並列印?
這就是為什麼我們有“pivot_root()”和“chroot()”,它們都可以用來做你想做的事情。您將新根安裝在其他地方,然後將其chroot(或pivot-root)。然後你執行 ‘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
我可以看到三個問題:
- 您正在使用
chdir(2)
文件描述符。正確的系統呼叫應該是fchdir(2)
.儘管 python 可能足夠聰明,可以
fchdir()
代替使用。
- 使用後,
fchdir(2)
您必須chroot(2)
再次使用,以便目前目錄再次位於目前根樹的“已知空間”內。- 您無法將結果與
getcwd()
./
在這兩種情況下,即使它不一樣,您也會得到/
。例如,您可以顯示 inode 編號(假設它是相同的文件系統,以便進行比較)或其他任何可能不同的內容。在這裡,通過上面的更改,從 debian Bullseye/sid,我在 LXC buster 容器的根目錄中 chroot。我顯示
/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()
在沒有保留文件描述符的情況下,可以濫用“未知空間”來轉義 a 。從 2005 年開始,本頁對此進行了描述:除了給定程式碼中的兩個問題(一個必須在第 62 行添加
#include <stdlib.h>
和更正雙引號拼寫錯誤fprintf()
),它在今天的 Debian 上仍然可以正常工作(當然還有一些 *nixes)。據我了解,當處於“未知空間”時(即:當cwd位於目前root之外時導致 OP 錯誤的情況),人們可以盲目地回到實際的root。