|
Эмулятор Linux своими руками!
Xakep, номер #047, стр. 047-060-2 Затем в новом бинарнике происходит отсоединение от параметров system() сначала tty, потом глобальной переменной $FLROOT (путь к директории эмулятора), а далее вызов процедуры Getenvs(), в которой происходит считывание UserID, GroupID, Home, Shell и т.д. Вот как это выглядит (пример из /bin/ls): #!/usr/bin/perl ## /bin/ls component for Flinux v1.0 my(@argv)=@ARGV; # Запоминаем параметры $tty=pop(@argv); # Отсоединяем от них tty $FLROOT=pop(@argv); # Затем $FLROOT require "$FLROOT/lib/flinux.so"; # Заюзаем процедурный файл /lib/flinux.so Getenvs(); # Уходим на процедуру получения переменных Откуда берутся эти переменные? В эмуляторе может быть несколько пользователей одновременно. В /bin/login каждому пользователю присваивается личный номер - условно назовем его tty (tty-файл сам по себе создать сложно - нет ядра). Поэтому номера пользователей отличаются друг от друга. Затем - мой личный алгоритм :). В эмуляторе есть директория /var/env. В ней расположены эти же tty-номера, в которых записаны Login, Uid, Gid, Name, Home, и Shell пользователя соответственно. Таким образом, после считывания каждая программа наверняка знает права юзера, под которым она была запущена. Так становится реальным запрет на несанкционированный просмотр директорий, убийство процессов и тому подобные пакости. Что касается процессов, тут тоже не обошлось без извращений. Функции addproc() и rmproc() записывают и удаляют процессы из таблицы (директория /proc содержит номера процессов с содержанием в них user, tty, time и cmd). Функция Perl - kill (signal, pid) убивает процесс по заданному сигналу. Вопрос на засыпку: как узнать текущий процесс? А его содержит переменная $$. После нескольких хитрых манипуляций тебе подчиняются все процессы ;). А после фильтрации прав путем сравнения уидов, можно уверенно гарантировать безопасность запускаемых приложений (у меня это пока не реализовано). К моменту написания этой статьи уже появился телнет-демон =). При его запуске Flinux биндит 23 порт и ждет коннекта, после которого перенаправляет поток /bin/login в консоль клиента и обрабатывает соединение. Добиться этого было непросто, так как функция system(), хоть и выполняет скрипт интерактивно, не способна изменить направления трех главных дескрипторов (STDIN, STDOUT, STDERR) под Win32... Под Linux - здесь проблем нет, но ядро эмулятора все же Windows. Поэтому пришлось обходиться do() и делать взаимоисключение при помощи переменной $remote (1 - подключение через демон, 0 - локально) в бинарниках. Таким образом, фактически все процессы, выполняемые через телнет, являются потомками, и чтобы убить какой-либо из них, необходимо убить весь демон. |