CHROOT(2)

ИМЯ
chroot - изменить корневой каталог

ОБЗОР
#include <unistd.h>

int chroot(const char *path);

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

chroot():
    Начиная с glibc 2.2.2:
        _XOPEN_SOURCE && ! (_POSIX_C_SOURCE >= 200112L)
            || /* начиная с glibc 2.20: */ _DEFAULT_SOURCE
            || /* версии glibc <= 2.19: */ _BSD_SOURCE
    До glibc 2.2.2: не было

ОПИСАНИЕ
chroot() изменяет корневой каталог вызывающего процесса на тот, что задан аргументом path. Этот каталог будет использоваться для имён файлов, начинающихся с /. Корневой каталог наследуется всеми потомками вызывающего процесса.

Только привилегированный процесс (Linux: с мандатом CAP_SYS_CHROOT в своём пользовательском пространстве имён) может вызвать chroot().

Этот вызов изменяет только составляющую процесса разрешения имён и больше ничего. В частности, он не предназначен для действий повышения безопасности, создания полностью изолированной среды процесса (sandbox) или ограничения системных вызовов файловой системы. В прошлом, chroot() использовался службами для ограничения их самих передачи полученных от недоверенных пользователей путей системным вызовам наподобие open(2). Однако, если каталог перемещается за пределы каталога chroot, атакующий может использовать это в своих интересах и также выйти за пределы каталога chroot. Простейший способ сделать это — выполнить chdir(2) в каталог, который будет перемещён, подождать, когда он переместится, а затем открыть путь, например ../../../etc/passwd.

Если chdir(2) не разрешён, то есть немного более хитрый вариант, работающий при определённых условиях. Если служба позволяет задать «chroot в каталог», то обычно это означает, что если вы хотите предотвратить доступ к файлам удалённых пользователей вне каталога chroot, то вы должны гарантировать, что каталоги никогда не перемещаются за его пределы.

Данный вызов не изменяет текущий рабочий каталог, поэтому после вызова '.' может оказаться вне дерева, являющегося корнем '/'. В частности, суперпользователь может выйти за пределы "тюрьмы chroot" выполнив:

    mkdir foo; chroot foo; cd ..

Данный вызов не закрывает открытые файловые дескрипторы и поэтому через такие дескрипторы можно получить доступ к файлам за пределами дерева chroot.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.

ОШИБКИ
В зависимости от файловой системы могут также возвращаться другие ошибки. Общий набор ошибок перечислен ниже:

EACCES
    Поиск запрещён из-за одного из частей префикса пути (См. также path_resolution(7).)

EFAULT
    Аргумент path указывает за пределы доступного адресного пространства.

EIO Произошла ошибка ввода-вывода.

ELOOP
    Во время определения path встретилось слишком много символьных ссылок.

ENAMETOOLONG
    path слишком длинен.

ENOENT
    Файл не существует.

ENOMEM
    Недостаточное количество памяти ядра.

ENOTDIR
    Компонент path не является каталогом.

EPERM
    У вызвавшего процесса недостаточно прав.

СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, 4.4BSD, SUSv2 (отмечена как УСТАРЕВШАЯ). Эта функция не входит в POSIX.1-2001.

ЗАМЕЧАНИЯ
Дочерний процесс, созданный посредством fork(2), наследует корневой каталог родительского процесса. При вызове execve(2) корневой каталог остаётся неизменным.

Для определения корневого каталога процесса можно использовать магическую символическую ссылку /proc/[pid]/root; подробности в proc(5).

В FreeBSD есть более ограничивающий системный вызов jail().

СМОТРИТЕ ТАКЖЕ
chroot(1), chdir(2), pivot_root(2), path_resolution(7), switch_root(8)