程序可以继承或传递打开的文件描述符,否则不允许读取(或写入)文件。例如:
(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
。