
程式可以繼承或傳遞開啟的檔案描述符,否則不允許讀取(或寫入)檔案。例如:
(sudo -u nobody echo "hello world") > ~/test-file
(sudo -u nobody cat) < ~/test-file
問題:如果您繼承了您的使用者不允許存取的當前目錄(或根目錄),您是否可以存取它?
答案1
與檔案描述符的比較具有很強的誤導性:進程的當前目錄和根目錄不是檔案描述符或任何類型的指向「開啟檔案描述」(a struct file
)的指針,而只是指向目錄條目(struct dentry
s)的指針。
核心不保留引用目前目錄或根目錄所指向的目錄 inode 的開啟檔案描述,子進程可以透過任何類型的句柄繼承該目錄 inode。
為了以任何方式使用它們,必須透過路徑開啟當前目錄和根目錄,就像任何其他檔案一樣,並且所有標準檢查都適用。
打開檔案O_PATH
將僅傳回一個不透明的句柄,並且它將成功任何無法正常開啟進行讀取或寫入的文件,前提是該文件的路徑可存取:
$ perl -e 'sysopen my $fh, "/root", 0, 0 or die "$!"'
Permission denied at -e line 1.
$ perl -e 'sysopen my $fh, "/root", 010000000, 0 or die "$!"' # 010000000 is O_PATH
$
即使是特權進程,這樣的不透明 fd 也不能用作普通 fd,幸運的是,沒有辦法openat(fd, "", AT_EMPTY_PATH|O_RDWR)
將其轉換dup()
為常規文件描述符;-)
答案2
不。
# sudo -u nobody ls .
ls: cannot access '.': Permission denied
# sudo -u nobody ls -d .
ls: cannot access '.': Permission denied
# chmod o-rwx /chroot
# chroot --userspec=nobody:nobody /chroot
chroot: failed to run command ‘/bin/bash’: Permission denied
對目前目錄(或根目錄)的寫入存取也是如此。如果不是,我懷疑這將是安全錯誤的來源:-)。
類似的行為適用於在 Linux 上開啟的檔案描述符O_PATH
。
POSIX(未定義O_PATH
)意味著openat(fd, path, ...)
類似的函數將重新檢查存取開啟目錄的權限fd
,除非 fd
被打開O_SEARCH
。 Linux不支援O_SEARCH
。