# chroot - изоляция процесса в каталог _Процессы и ресурсы · LinuxLab Knowledge Base_ **TL;DR:** `chroot()` - системный вызов меняющий apparent root каталог процесса (и его потомков). Лёгкая изоляция доступа к ФС. **НЕ заменяет [[namespaces]]/контейнеры** - root внутри chroot часто может выйти. ## Что делает chroot Системный вызов `chroot(path)` (с прав root) меняет «apparent /» текущего процесса на `path`. Все последующие пути с `/` резолвятся относительно него. Процесс и **все его потомки** не видят то что выше. ``` Реальная ФС: Внутри chroot /srv/jail: / / ├── etc/ ├── etc/ ├── usr/ ├── usr/ ├── srv/ └── bin/ │ └── jail/ ←── chroot │ ├── etc/ │ ├── usr/ │ └── bin/ └── home/ ``` Используется для: - **Изоляции демонов** (исторически BIND, vsftpd, sshd ChrootDirectory). - **Сборки пакетов в чистом окружении** (debootstrap, mock, pbuilder). - **Системного восстановления** - boot с live-USB → `chroot /mnt/sysroot`, чтобы починить grub/fstab «изнутри» сломанной системы. ## Что chroot НЕ делает (важные ограничения) Linux-документация и история показали: chroot - это `/` rebind, а не security-граница. Он **не изолирует**: - Сетевой стек (виден тот же сетевой namespace, тот же netfilter) - PID-пространство (`ps -ef` снаружи видит процессы chroot'а) - IPC, signals, ptrace (можно прицепиться к процессу хоста с такими же правами) - Kernel exploits и `/dev` устройства - **Сам chroot** - root внутри jail имеет известный escape: ```c int fd = open("/", O_RDONLY); // fd на ВНЕШНИЙ корень chroot("/tmp/anything"); // сменить chroot fchdir(fd); // перейти в старый / chroot("."); // зафиксировать // теперь видим всю ФС ``` Поэтому для real изоляции нужны [namespaces](/kb/namespaces.md) (mount/pid/net/user) + [capabilities](/kb/capabilities.md) + [seccomp](/kb/seccomp.md) + cgroups. То что в сумме даёт Docker/Podman. Когда chroot всё ещё уместен: - Внутри **уже** изолированного контейнера - для дополнительного слоя. - Для не-root процессов (после chroot уронить privileges через `setuid`). - Для бытового - пересобрать пакет в чистом окружении. ## Как создать рабочий chroot вручную Минимальный chroot для запуска `bash` + `ls`: ```bash ROOT=/tmp/jail mkdir -p $ROOT/{bin,lib,lib64} # 1) бинари cp /bin/bash /bin/ls $ROOT/bin/ # 2) их библиотеки - через ldd ldd /bin/bash # linux-vdso.so.1 # libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 # libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 # /lib64/ld-linux-x86-64.so.2 for bin in /bin/bash /bin/ls; do ldd $bin | awk '/=>/{print $3}; /^\s*\//{print $1}' | while read lib; do mkdir -p $ROOT$(dirname $lib) cp $lib $ROOT$lib done done # 3) запустить sudo chroot $ROOT /bin/bash ``` Такой минимальный jail не имеет `/etc/passwd`, `/proc`, `/dev` - `ls -l` покажет UID числами, многие команды упадут. ## /proc, /dev, /sys внутри chroot Большинство демонов требуют доступ к `/dev/null`, `/proc/self`, иногда `/sys`. Их **нельзя просто скопировать** - это виртуальные ФС ядра. Решение - [bind-mount](/kb/bind-mount.md) из хоста: ```bash sudo mount --bind /proc $ROOT/proc sudo mount --bind /sys $ROOT/sys sudo mount --bind /dev $ROOT/dev sudo mount --bind /dev/pts $ROOT/dev/pts sudo mount --bind /run $ROOT/run sudo chroot $ROOT /bin/bash ``` Это стандартный паттерн для системного rescue. ## Использование на практике ### sshd ChrootDirectory (sftp-only пользователи) В `/etc/ssh/sshd_config`: ``` Match Group sftpusers ChrootDirectory /srv/sftp/%u ForceCommand internal-sftp AllowTcpForwarding no ``` Требования к каталогу: владелец `root:root`, права `0755` (нельзя дать юзеру write на сам chroot-root, иначе sshd откажется). Внутри уже можно создать поддиректории с правами юзера. ### debootstrap - установка Debian в каталог ```bash sudo apt install debootstrap sudo debootstrap stable /srv/sid http://deb.debian.org/debian sudo mount --bind /proc /srv/sid/proc sudo chroot /srv/sid /bin/bash apt update # внутри chroot ``` Используется чтобы собрать пакет в эталонном окружении или подготовить rootfs для контейнера. ### Восстановление сломанной системы Загрузка с live-USB: ```bash # после монтирования root-ФС больной системы sudo mount /dev/sda2 /mnt sudo mount /dev/sda1 /mnt/boot # если /boot отдельно for fs in proc sys dev dev/pts run; do sudo mount --bind /$fs /mnt/$fs; done sudo chroot /mnt # теперь живём «внутри» сломанной системы: grub-install /dev/sda update-initramfs -u passwd # сбросить root-пароль exit ``` ## chroot vs pivot_root - `chroot` - меняет видимый `/`, старый корень всё ещё «существует» где-то. - `pivot_root` - буквально меняет местами старый и новый корни, старый можно потом размонтировать. Используется при init контейнера/initramfs. Для системы внутри контейнера (containerd, runc) - всегда pivot_root. Для одноразового запуска - chroot. ## Дебаг - почему не запускается ```bash sudo chroot /srv/jail /bin/bash # → bash: error while loading shared libraries: libtinfo.so.6: cannot open ``` Не хватает библиотек. Найти что нужно: ```bash ldd /srv/jail/bin/bash | awk '/not found/' # после chroot - не работает # вместо этого - снаружи chroot /srv/jail ldd /bin/bash 2>&1 # упадёт если нет ldd ``` Альтернатива - `strace -e openat` чтобы увидеть какие файлы пытаются открыться: ```bash sudo strace -f -e openat chroot /srv/jail /bin/bash 2>&1 | grep ENOENT ``` ## Команды ```bash sudo chroot /mnt /bin/bash ``` Войти в систему смонтированную в /mnt - стандарт для rescue с live-USB ```bash ldd /bin/bash ``` Посмотреть список .so которые нужно положить в chroot вместе с бинарём ```bash for fs in proc sys dev; do sudo mount --bind /$fs /mnt/$fs; done ``` Подготовить виртуальные ФС внутри chroot - без них демоны не запустятся ```bash sudo debootstrap stable /srv/sid http://deb.debian.org/debian ``` Установить чистый Debian в каталог - для chroot или сборки rootfs ```bash sudo strace -f -e openat chroot /srv/jail /bin/myapp 2>&1 | grep ENOENT ``` Найти какие файлы приложение пытается открыть и не находит - типичный дебаг chroot ## См. также - [Linux namespaces](/kb/namespaces.md) - [Linux capabilities - биты привилегий](/kb/capabilities.md) - [seccomp - фильтр системных вызовов](/kb/seccomp.md) - [bind mount - монтирование каталога в другое место](/kb/bind-mount.md) - [SSH - secure shell](/kb/ssh.md) - [Filesystem Hierarchy Standard (FHS)](/kb/fhs.md)