Linux программирование в примерах
int setregid(gid_t rgid, gid_t egid)Делает для действительных и эффективных ID групп то же, что
делает для действительных и эффективных ID пользователя. Используется то же разграничение между обычными пользователями иsetreuid().rootСохраненный set-user ID в модели BSD не существует, поэтому лежащей в основе
иsetreuid()идеей было упростить переключение между действительным и эффективным ID:setregid()setreuid(geteuid(), getuid()); /* обмен действительным и эффективным */Однако, с принятием POSIX модели сохранения set-user ID и функций
иseteuid()функции BSD не следует использовать в новом коде. Даже документация BSD 4.4 помечает эти функции как устаревшие, рекомендуя вместо нихsetegid()/seteuid()иsetuid()/setegid().setgid()11.6.3. Использование битов setuid и setgid
Есть важные случаи, в которых действующая как
программа должна безвозвратно изменить все три значения действительного, эффективного и сохраненного set-user ID на ID обычного пользователя. Наиболее очевидным случаем является программаroot, которую вы используете (либо непосредственно, либо удаленно) каждый раз при регистрации в системе GNU/Linux или Unix. Имеется иерархия программ, как очерчено на рис. 11.1.loginРис. 11.1. От
черезinitчерезgettyк shellloginКод для
слишком сложен, чтобы показать здесь, поскольку он имеет дело с рядом задач, не имеющих отношения к текущему обсуждению. Но мы можем очертить шаги, которые происходят во время регистрации, следующим образом:login1.
является самым первым процессом. Его PID равен 1. Все другие процессы являются его потомками. Ядро вручную создает процесс 1 во время загрузки и запускает в немinit. Он действует с действительным и эффективным UID, равными нулю, т.е. какinit.root2.
читаетinit, который, помимо прочих вещей, сообщает/etc/inittabо том, на каких устройствах он должен запустить процессinit. Для каждого такого устройства (такого, как консоль, последовательные терминалы или виртуальные консоли в системе GNU/Linux)gettyпорождает новый процесс. Этот новый процесс использует затемinitдля запускаexec()(от «get tty» («получить tty», т.е. терминал)). На многих системах GNU/Linux эта команда называетсяgetty. Программа открывает устройство, сбрасывает его состояние и выводит приглашение 'mingetty'.login:3. По получении регистрационного имени
выполняетgetty. Программаloginищет имя пользователя в файле паролей, запрашивает пароль и проверяет его. Если пароль подходит, процессloginпродолжается.login4.
изменяет домашний каталог пользователя, устанавливает начальное окружение, а затем устанавливает начальный набор открытых файлов. Он закрывает дескрипторы файлов, открывает терминал и используетloginдля копирования дескрипторов файла терминала в 0, 1 и 2. Вот откуда происходят дескрипторы уже открытых файлов стандартного ввода, стандартного вывода и стандартной ошибки.dup()5. Затем
используетloginдля установки дополнительного набора групп,setgroups()для установки значений действительного, эффективного и сохраненного set-group ID в соответствующее значение группы пользователя, и наконец,setgid()для установки всех трех значений действительного, эффективного и сохраненного set-user ID в соответствующие значения для регистрирующегося пользователя. Обратите внимание, что вызовsetuid()должен быть последним для того, чтобы другие два вызова завершились успешно.setuid()6. Наконец,
вызывает зарегистрированную оболочку пользователя. Оболочки в стиле Борна после этого читают файлыloginи/etc/profile, если они существуют. Затем оболочка выводит приглашение.$HOME/.profileОбратите внимание, как один процесс меняет свою сущность от системного процесса до процесса пользователя. Каждый потомок
начинается как копияinit. Используяinit, тот же самый процесс выполняет различные задания. Вызвавexec()для перехода отsetuid()к обычному пользователю, процесс в конечном счете поступает непосредственно для работы пользователя. Когда вы выходите из оболочки (посредством CTRL-D илиroot), процесс попросту завершается. Затемexitвозобновляет цикл, порождая новыйinit, который выводит новое приглашение 'getty'.login:ЗАМЕЧАНИЕ. Открытые файлы остаются открытыми и доступными для использования, даже после изменения процессом своих UID или GID. Таким образом, программы с setuid должны заранее открыть все нужные файлы, изменить их ID на ID действительного пользователя и продолжить оставшуюся часть работы без дополнительных привилегий
В табл. 11.1 приведена сводка шести стандартных функций для манипулирования значениями UID и GID.
Таблица 11.1. Сводка API для установки действительных и эффективных ID [120]
Функция Устанавливает Постоянно Обычный пользователь Root seteuid()E Нет Из R, E, S Любое setegid()E Нет Из R, E, S Любое setuid()Root: R,E,S Другие: E Root: да Другие: нет Из R, E Любое setgid()Root: R,E,S Другие: E Root: да Другие: нет Из R, E Любое setreuid()E, может установить R Нет Из R, E Любое setregid()E, может установить R Нет Из R, E Любое
