Допустим, приложение должно читать файлы только из
/srv/uploads. Пользователь передаёт имя файла, а программа открывает его.На первый взгляд достаточно проверить путь. Но если внутри каталога есть символические ссылки, всё становится сложнее.
▪️В чём проблема
Например, пользователь передаёт:
documents/report.pdf
Приложение проверяет, что путь находится внутри
/srv/uploads, а затем вызывает open().Но между проверкой и открытием файла кто-то может заменить один из каталогов символической ссылкой на
/etc.Получается классическая TOCTOU-проблема: проверили один объект, а открыли уже другой.
▪️Что меняет openat2()
В Linux есть системный вызов
openat2(), который позволяет задать ограничения прямо во время разрешения пути.Например:
struct open_how how = {
.flags = O_RDONLY,
.resolve = RESOLVE_BENEATH |
RESOLVE_NO_SYMLINKS
};Здесь два важных ограничения:
RESOLVE_BENEATH - запрещает разрешение пути за пределами указанного каталога.RESOLVE_NO_SYMLINKS - запрещает проходить через символические ссылки в любом компоненте пути.▪️Как открыть файл
Сначала приложение получает дескриптор каталога:
int dirfd = open("/srv/uploads",
O_PATH | O_DIRECTORY);Затем открывает файл относительно него:
int fd = syscall(SYS_openat2,
dirfd,
"documents/report.pdf",
&how,
sizeof(how));
Теперь ядро проверяет ограничения непосредственно при разрешении пути.
Если один из компонентов окажется символической ссылкой, операция завершится ошибкой.
▪️А если символические ссылки нужны?
Полностью запрещать их необязательно.
Можно использовать:
.resolve = RESOLVE_IN_ROOT
В этом режиме указанный каталог становится временным корнем для разрешения пути. Даже абсолютные пути и переходы через
.. интерпретируются относительно него.Это полезно, когда приложению нужно работать с деревом файлов, не позволяя обращаться к объектам за его пределами.
▪️Почему это важно
Обычная проверка строки пути не гарантирует безопасность: файловая система может измениться между проверкой и открытием.
openat2() позволяет перенести ограничения на уровень ядра и избежать многих ошибок при работе с недоверенными путями. При этом это не полноценная песочница: ограничения действуют на конкретное открытие файла, а не на все действия процесса.BashTex 📱 #bash #linux