linux 命令分析之 chroot 的原理
目錄
chroot 的功能
chroot 可以用來切換當前程式的【根目錄】,它能夠將當前程式能夠訪問的目錄樹結構限制
在某個子目錄中,同時由於當前程式建立的子程式將會繼承父程式的根目錄結構,所以子進
程也隨之被限定。
chroot 命令的原理
通過 strace 來跟蹤一次 chroot 命令執行過程來研究其程式碼執行過程。
這裡我刪除了與這個問題沒有太大關係的一些輸出,重要的系統呼叫資訊如下:
[root@localhost new_test]# strace chroot . sh
execve("/usr/sbin/chroot", ["chroot", ".", "sh"], 0x7fffbf1a9580 /* 28 vars */) = 0
..............................
chroot(".") = 0
chdir("/") = 0
execve("/usr/local/sbin/sh", ["sh"], 0x7fff5cd3d1a8 /* 28 vars */) = -1 ENOENT (沒有那個檔案或目錄)
execve("/usr/local/bin/sh", ["sh"], 0x7fff5cd3d1a8 /* 28 vars */) = -1 ENOENT (沒有那個檔案或目錄)
execve("/usr/sbin/sh", ["sh"], 0x7fff5cd3d1a8 /* 28 vars */) = -1 ENOENT (沒有那個檔案或目錄)
execve("/usr/bin/sh", ["sh"], 0x7fff5cd3d1a8 /* 28 vars */) = 0
.............................
上述過程可以總結為如下幾個步驟:
- execve 執行 chroot 程式
- chroot 系統呼叫切換當前命令的根目錄
- chdir 系統呼叫切換當前命令的工作目錄到新的根目錄
- 根據路徑搜尋預設 shell 的位置,使用 execve 進行執行
這裡它搜尋預設 shell 的路徑時有幾個備選路徑,搜尋順序如下:
- /usr/local/sbin/sh
- /usr/local/bin/sh
- /usr/sbin/sh
- /usr/bin/sh
從上面的捕獲到的 chroot 命令的系統呼叫可以看到 chroot 命令的核心其實就是呼叫
chroot 系統呼叫,這也就是其核心態的主要行為,這個行為並不是直接完成這項功能
的,它實際是通過一種間接的方式修改 task_struct 中的資料結構來達成的。
為什麼 chroot 要 chdir 到 “/” 目錄中呢?
細心的讀者也許會注意到 chroot 在執行了 chroot 系統呼叫後,又呼叫了 chdir 切換
【當前目錄】到【新的根目錄】的行為,這個行為是必不可少的!
chdir 系統呼叫將會修改當前程式 task_sturct fs 中的 pwd 欄位,這個欄位儲存了當前工作
目錄的 dentry 結構體。
核心程式碼如下:
set_fs_pwd(current->fs, &path);
如果 chroot 命令不 chdir 到 “/” 目錄,那麼我們仍舊可以在 chroot 後的程式中通過訪問到
外界的目錄,這樣就會出現非常好玩的情景。
不讓 chroot 執行 chdir 過程的測試
為了驗證這點,我進行了如下幾個嘗試。
1. 指定 --skip-chdir 引數
chroot 命令中有一個 –skip-chdir 引數,在根目錄中執行如下命令來使用它:
[root@localhost /]# /root/chroot --skip-chdir /root/chroot_environment/ sh
/root/chroot: option --skip-chdir only permitted if NEWROOT is old '/'
這裡報錯資訊表明 –skip-chdir 只在新的 root 目錄與老的根目錄相同時才被允許使用。
2. 修改 chroot 命令原始碼
chroot 命令在 coreutils 包中,執行 sudo apt-get source coreutils 來下載,其源
碼在 src/chroot.c 中,對程式碼進行如下修改讓 chroot 不執行 chdir 操作:
#if 0
if (! skip_chdir && chdir ("/"))
die (EXIT_CANCELED, errno, _("cannot chdir to root directory"));
#endif
終端中測試不執行 chdir 的 chroot
重新編譯後執行,在終端中執行如下命令:
[root@localhost /]# /chroot /root/chroot_environment sh
(unreachable)/ # ls
bin chroot etc lib media opt root sbin sys usr
boot dev home lib64 mnt proc run srv tmp var
(unreachable)/ # chroot .
[root@localhost /]# ls
bin boot chroot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@localhost /]# exit
exit
(unreachable)/ # cd ./root
sh: cd: can't cd to ./root: No such file or directory
(unreachable)/ # cd /root
~ # cd ..
/ # ls
bin dev etc lib64 proc root sys usr var
/ #
第一行命令切根後,由於沒有 chdir 到新的根目錄,cwd 中仍然儲存了舊的工作目錄的
dentry 資訊,這樣我們仍舊能夠訪問到舊的根目錄下的所有檔案,第二行的 ls 命令的
輸出資訊證實了這點。
第三行命令繼續執行了 chroot,注意這裡的引數為 .,. 表示當前目錄,這行命令執行後,又
切回了原來的根目錄。
第四行命令從第三行命令的 chroot 環境中退出,退出後嘗試 cd ./root,發現會報這個目錄
不存在的錯誤。
通過 strace 跟蹤這個 sh,發現它傳遞給 chdir 系統呼叫的命令並不是 ./root,而是 "
(unreachable)/root",這個目錄當然不存在嘍,就報了目錄不存在的錯誤。
相關的系統呼叫內容如下:
chdir("(unreachable)/root") = -1 ENOENT (沒有那個檔案或目錄)
write(2, "sh: ", 4) = 4
write(2, "cd: ", 4) = 4
write(2, "can't cd to ./root: No such file"..., 45) = 45
單獨編寫了一個呼叫 chdir(“root”) 的程式碼編譯後執行測試,確認能夠 chdir,看來應該是 sh
進行了某種處理。
sh 中對當前目錄的處理
這裡新增的 (unreachable) 是 PS1 變數控制的,檢視 manual 確定這個字串實際上對
應的是當前的工作目錄。相關資訊如下:
\w 當前工作目錄
我當前 shell 的 PS1 設定如下:
(unreachable)/ # echo $PS1
\w \$
看來 sh 執行的時候應該是通過當前目錄的變數將我輸入的 ./ 展開了,這樣就有上面的
問題了。
chdir 到 /root 後切到新的根目錄,完成 chroot 的所有過程
第五行命令中 cd /root 成功,這是肯定的,因為當前程式的根目錄已經切換了,所以我們能
夠進入到這個 /root 目錄,而且這個目錄也是新的目錄。
第六行命令中 cd … 返回根目錄,然後執行 ls 命令,可以看到此時根目錄下的檔案已經變
了,直至這裡才完成了 chroot 的所有過程。
相關文章
- chroot恢復Arch LinuxLinux
- linux命令 之 du 命令Linux
- Linux命令之lldptool命令Linux
- Chroot 簡介
- chroot詳解
- 在Linux中,Jail和Chroot有何區別?LinuxAI
- Spark原始碼分析之cahce原理分析Spark原始碼
- Linux命令之rz命令與sz命令Linux
- 效能工具之linux常見日誌統計分析命令Linux
- Linux命令之fdiskLinux
- linux命令之grepLinux
- Linux之export命令LinuxExport
- linux之 sed命令Linux
- linux命令之touchLinux
- Linux之free命令Linux
- linux命令之seqLinux
- linux之cat命令Linux
- linux之pmap命令!Linux
- linux之stat命令Linux
- linux之vim命令Linux
- Linux之sar命令Linux
- Linux下history命令簡單原理Linux
- Linux 容器技術史話:從 chroot 到未來Linux
- 透過chroot構建Linux作業系統(轉)Linux作業系統
- Linux系統命令之systemctl命令。Linux
- Linux 有用的命令之 - lsof(轉)Linux
- Linux-網橋原理分析********************Linux
- Linux命令技巧之30個必會的命令技巧Linux
- Kafka原理分析之基礎篇Kafka
- Linux命令之rpm安裝命令Linux
- 【運維必看】Linux命令之lsblk命令運維Linux
- linux常用系統分析命令Linux
- Linux命令----分析網路卡流量Linux
- 【Linux之truncate 命令用法】Linux
- Linux之netstat命令Linux
- Linux之基礎命令Linux
- 編譯原理之語法分析-自下而上分析(三)編譯原理語法分析
- 編譯原理之語法分析-自下而上分析(四)編譯原理語法分析