%20%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%81%8B%3F.png)
プログラムは、通常は読み取り (または書き込み) が許可されないファイルのオープン ファイル記述子を継承したり、渡されたりすることができます。例:
(sudo -u nobody echo "hello world") > ~/test-file
(sudo -u nobody cat) < ~/test-file
質問: ユーザーがアクセスを許可されていない現在のディレクトリ (またはルート ディレクトリ) を継承した場合、そのディレクトリにアクセスできますか?
答え1
ファイル記述子との比較は非常に誤解を招きます。プロセスの現在のディレクトリとルート ディレクトリは、ファイル記述子でも「オープン ファイル記述子」(a struct file
) へのポインターでもなく、単にディレクトリ エントリ (s) へのポインターですstruct dentry
。
カーネルは、現在のディレクトリまたはルート ディレクトリによって指されるディレクトリ 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
$
openat(fd, "", AT_EMPTY_PATH|O_RDWR)
このような不透明な fd は、特権プロセスであっても通常の fd として使用することはできません。また、幸いなことに、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
現在のディレクトリ (またはルート ディレクトリ) への書き込みアクセスについても同様です。そうでない場合は、セキュリティ バグの原因になると思われます :-)。
O_PATH
Linux で開かれたファイル記述子にも同様の動作が適用されます。
POSIX(は定義していないO_PATH
)は、openat(fd, path, ...)
および同様の関数が開いているディレクトリへのアクセス許可を再確認することを示唆していますfd
。ない限り fd
で開かれましたO_SEARCH
。 LinuxはサポートしていませんO_SEARCH
。