Помещаем в chroot-песочницу командный интерпретатор
Мы посмотрели, как можно chroot-изировать приложение средствами системного вызова из кода самого приложения.
Теперь давайте возьмем уже готовое приложение — для удобства работы это будет командный интерпретатор /bin/sh.
Почему? Процесс командного интерпретатора в состоянии сам о себе рассказать — через интерфейс командной строки, — в каком окружении он работает, что ему доступно, а что нет. Тем самым мы легко понаблюдаем за возможностями процесса в изолированном средствами chroot() окружении.
При этом нам нет необходимости писать свое приложение, так как, во-первых, мы запускаем процесс командного интерпретатора, исполняемый файл которого уже есть в системе, а во-вторых, существующее приложение мы можем запускать в изолированном окружении специальной командой chroot. Смысл этой команды заключается как раз в использовании одноименного системного вызова для запуска приложения, переданного ей в качестве параметра.
$ man 1 chroot
Итак, создаем песочницу /tmp/chroot, копируем туда исполняемый файл командного интерпретатора /bin/sh и пробуем его там запустить. Для работы chroot() требуется привилегия CAP_SYS_CHROOT, поэтому запускаем утилиту chroot через sudo:
$ mkdir -p /tmp/chroot/bin
$ cp /bin/sh /tmp/chroot/bin/
$ sudo chroot /tmp/chroot /bin/sh
chroot: failed to run command ‘/bin/sh’: No such file or directory
Несмотря на то что по сообщению об ошибке кажется, будто не найден файл самого командного интерпретатора, в действительности ошибка возникает из-за того, что запускаемый в chroot-окружении исполняемый файл не может найти необходимых ему динамически загружаемых библиотек.
Воспользуемся утилитой ldd
$ man 1 ldd
чтобы понять, какие динамические библиотеки требуются для работы /bin/sh:
$ ldd /bin/sh
linux-vdso.so.1 (0x00007fff3eb9f000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f190aef1000)
libc.so.6 => /lib64/libc.so.6 (0x00007f190ad18000)
/lib64/ld-linux-x86-64.so.2 (0x00007f190afdc000
Итак, что мы здесь видим:
- Первая библиотека — linux-vdso.so.1 — является неким виртуальным объектом, размещаемым в памяти процесса, через который организуется взаимодействие с ядром операционной системы — собственно, обращение к системным вызовам. С ней ничего делать не надо, так как ее виртуальное присутствие в исполняемом файле обеспечивается компоновщиком. А вот остальные библиотеки в выводе утилиты ldd должны быть явно доступны при работе процесса.
- Для размещения остальных библиотек создаем в каталоге chroot’изации подкаталог lib64 (имя подкаталога может отличаться в зависимости от используемой процессорной архитектуры и конкретного дистрибутива). И далее копируем туда необходимые библиотеки.
$ mkdir -p /tmp/chroot/lib64
$ cp /lib64/{libdl.so.2,libc.so.6,ld-linux-x86-64.so.2} /tmp/chroot/lib64/
Теперь можем запустить в созданном chroot’е командный интерпретатор:
$ sudo chroot /tmp/chroot /bin/sh
sh-4.4#
Постараемся понять, куда попали (попали в chroot ) и что мы отсюда можем увидеть:
sh-4.4# pwd
/
sh-4.4# ls
sh: ls: command not found
sh-4.4# cd bin
sh-4.4# pwd
/bin
sh-4.4# cd ..
sh-4.4# echo *
bin lib64
sh-4.4# cd /
sh-4.4# pwd
/
sh-4.4# echo *
bin lib64
sh-4.4# cat /etc/passwd
sh: cat: command not found
sh-4.4# exit
$
Приведенный вывод показывает, что:
- Мы в каталоге chroot-изации и имеем видимость только той части иерархии каталогов, которая находится ниже этого каталога (/tmp/chroot).
- Нам доступны внутренние команды командного интерпретатора /bin/sh, типа echo, cd, pwd, exit, так как они реализованы в самом исполняемом файле командного интерпретатора и не требуют наличия в каталоге chroot’изации дополнительных исполняемых файлов.
Внешние команды, типа ls и cat, реализованные в отдельных исполняемых файлах, нам недоступны, так как мы их и требуемые ими библиотеки не положили в каталог chroot-изации.
Дополнение chroot-окружения
Добавим в созданное изолированное окружение некоторые команды и используемые ими библиотеки. Начнем с cat:
$ which cat
/usr/bin/cat
$ ldd `which cat`
linux-vdso.so.1 (0x00007ffe87599000)
libc.so.6 => /lib64/libc.so.6 (0x00007fa7ac385000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa7ac59e000)
Как видим, дополнительные библиотеки в chroot добавлять не потребуется, все необходимое там уже есть, достаточно добавить только сам исполняемый файл утилиты cat:
$ cp /usr/bin/cat /tmp/chroot/bin/
Теперь ls:
$ which ls
/bin/ls
$ ldd `which ls`
linux-vdso.so.1 (0x00007fff31113000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f8c95d22000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f8c95cf6000)
libcap.so.2 => /lib64/libcap.so.2 (0x00007f8c95cee000)
libc.so.6 => /lib64/libc.so.6 (0x00007f8c95b15000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8c95daf000)
libpcre.so.3 => /lib64/libpcre.so.3 (0x00007f8c95ad0000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f8c95aca000)
Кроме самого исполняемого файла, потребуется добавить недостающие библиотеки:
$ cp /bin/ls /tmp/chroot/bin/
$ cp /lib64/{libtinfo.so.5,libselinux.so.1,libcap.so.2,libpcre.so.3} /tmp/chroot/lib64/
Ну и проверяем работу в изолированном окружении:
$ sudo chroot /tmp/chroot /bin/sh
sh-4.4# ls
bin lib64
sh-4.4# cat /etc/passwd
cat: /etc/passwd: No such file or directory
Таким образом, мы обеспечили наличие необходимых инструментов в chroot-окружении, но остались при этом в рамках тех же, установленных системным вызовом chroot, ограничениях.