%2C%20%D0%B5%D1%81%D0%BB%D0%B8%20%D1%83%20%D0%B2%D0%B0%D1%88%D0%B5%D0%B3%D0%BE%20%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F%20%D0%BD%D0%B5%D1%82%20%D0%BF%D1%80%D0%B0%D0%B2%20%D0%BD%D0%B0%20%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%20%D0%BA%20%D1%8D%D1%82%D0%BE%D0%BC%D1%83%20%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D1%83%3F.png)
Программа может унаследовать или получить открытый файловый дескриптор для файла, который в противном случае не был бы разрешен для чтения (или записи). Например:
(sudo -u nobody echo "hello world") > ~/test-file
(sudo -u nobody cat) < ~/test-file
Вопрос: Если вы наследуете текущий каталог (или корневой каталог), к которому ваш пользователь в противном случае не имел бы доступа, разрешено ли вам получить к нему доступ?
решение1
Сравнение с файловыми дескрипторами вводит в заблуждение: текущий и корневой каталоги процесса не являются файловыми дескрипторами или какими-либо указателями на «открытое описание файла» (a struct file
), а всего лишь указателями на записи каталога ( struct dentry
s).
Ядро не хранит описание открытого файла, ссылающееся на индекс каталога, на который указывает текущий или корневой каталог, который может быть унаследован дочерними процессами через любой тип дескриптора.
Чтобы их можно было использовать каким-либо образом, текущий и корневой каталоги должны быть открыты по пути, как и любой другой файл, и должны применяться все стандартные проверки.
Открытие файла с помощью 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)
чтобы преобразовать dup()
его в обычный файловый дескриптор ;-)
Кстати, библиотека muslопределяет O_SEARCH
как O_PATH
с тех пор2012.
решение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
.