Когда setuid()
используется процессом, чей эффективный uid установлен в 0, все uid процесса изменяются на euid
. К сожалению, это делает невозможным использование setreuid()
в setuid-программах, которым нужно временное использование другого uid, поскольку после вызова setreuid()
процесс не может восстановить свои полномочия root.
Хотя способность переключать uid упрощает написание кода, с помощью которого нельзя нарушить безопасность системы, все же это не панацея. Существует очень много популярных методов обманного проникновения в выполняющийся код [18]. До тех пор пока либо сохраненный, либо действительный uid процесса равен 0, такие атаки легко могут устанавливать эффективный uid процесса в 0. Это не дает возможности переключению uid эффективно предотвращать серьезную уязвимость системных программ. Однако если процесс может передать любой доступ к полномочиям root, устанавливая эффективный, сохраненный и действительный идентификаторы в ненулевые значения, это ограничивает эффективность любых атак против него.
10.2.3. Идентификатор uid файловой системы
В очень специальных случаях программе может понадобиться сохранять свои права root для всего, кроме доступа к файловой системе, при котором она использует пользовательский uid. Изначально использовавшийся в Linux NFS-сервер пространства пользователя может служить иллюстрацией проблемы, которая возникает, когда процесс предполагает применение пользовательского uid. Хотя NFS-сервер в прошлом применял setreuid()
для переключения uid при доступе к файловой системе, такое поведение позволяло пользователю, чей uid совпадает с uid NFS-сервера, уничтожать NFS-сервер. В конечном итоге, пользователь получал владение процессом NFS-сервера. Чтобы предотвратить проблемы подобного рода, Linux использует uid файловой системы (fsuid) для контроля доступа к файловой системе.
Всякий раз когда изменяется эффективный uid процесса, его fsuid устанавливается равным новому эффективному идентификатору пользователя, что делает fsuid прозрачным для большинства приложений. Те приложения, которые нуждаются в дополнительных возможностях, предоставляемых отличающимся значением fsuid, должны применять вызов setfsuid()
для явной установки fsuid.
int setfsuid(uid_t uid);
Значение fsuid может быть установлено равным текущим эффективному, сохраненному или действительному идентификаторам пользователя. В дополнение следует сказать, что setfsuid()
выполняется успешно, если fsuid остается неизменным или эффективный uid процесса равен 0.
10.2.4. Резюме по идентификаторам пользователей и групп
Подведем итоги обо всех системных вызовах, которые модифицируют права доступа выполняющегося процесса. Большинство перечисленных здесь функций, имеющих отношение к идентификаторам пользователей, уже детально рассматривались в настоящей главе, но те, что относятся к группам — еще нет. Поскольку эти функции отражают соответствующие функции, модифицирующие идентификаторы пользователя, их поведение должно быть понятно.
Все эти функции возвращают -1
в случае ошибки и 0
— в случае успеха, если только не указано иначе. Большинство их прототипов находятся в
. Те, что расположены где-то еще, отмечены ниже.