SETUID(2)

ИМЯ
setuid - устанавливает идентификатор пользователя

ОБЗОР
#include <sys/types.h>
#include <unistd.h>

int setuid(uid_t uid);

ОПИСАНИЕ
setuid() устанавливает эффективный идентификатор владельца вызывающего процесса. Если эффективный идентификатор вызывающего является суперпользователем (root), то также устанавливаются действительный и сохранённый идентификаторы.

В Linux setuid() реализован как и в стандарте POSIX с возможностью _POSIX_SAVED_IDS. Это позволяет setuid-программам (не setuid-root) сбрасывать все привилегии, делать непривилегированную работу, а затем безопасным путём возвращать себе исходный эффективный идентификатор пользователя.

Если пользователь root или программа установлена как setuid root, при работе требуется особая осторожность. Функция setuid() проверяет эффективный идентификатор вызвавшего пользователя и, если это суперпользователь, то все устанавливаемые значения идентификаторов равны uid. После этого программа уже никаким образом не сможет вернуть права пользователя root.

Таким образом, программа, принадлежащая root и с установленным битом setuid, собирающаяся временно сбросить права root и поработать с правами непривилегированного пользователя, а затем восстановить права root, не сможет использовать setuid(). Требуемого результата можно достичь с помощью вызова seteuid(2).

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение. Замечание: есть случаи, когда setuid() может завершиться с ошибкой даже когда UID вызывающего равен 0; это серьёзная ошибка безопасности — не проверять возвращаемое значение setuid().

ОШИБКИ

EAGAIN
    Вызов изменил бы настоящего реальный UID вызывающего (т. е. uid не совпадает с реальным UID вызывающего), но возникла временная ошибка при выделении памяти под необходимые структуры ядра.

EAGAIN
    Значение uid не совпадает с реальным UID вызывающего и этот вызов создал был превышение количества процессов, принадлежащих пользователю с реальным ID ruid сверх ограничителя ресурсы RLIMIT_NPROC вызывающего. Начиная с Linux 3.1 эта ошибка больше не возникает (но корректное приложение должно проверять эту ошибку); смотрите описание EAGAIN в execve(2).

EINVAL
    Идентификатор пользователя, заданный в uid, некорректен в этом пользовательском пространстве имён.

EPERM
    Пользователь не является суперпользователем (Linux: нет мандата CAP_SETUID), а uid не совпадает с действительным или сохранённым идентификатором пользователя вызывающего процесса.

СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, POSIX.1-2001. Этот системный вызов не полностью совместим с 4.4BSD, который устанавливает действительный, эффективный и сохранённый идентификаторы пользователя.

ЗАМЕЧАНИЯ
Linux поддерживает идентификатор пользователя файловой системы, обычно совпадающий с эффективным идентификатором. Системный вызов setuid() также устанавливает идентификатор пользователя файловой системы вызывающего процесса. См. setfsuid(2).

Если uid отличается от старого эффективного идентификатора, то процессу нельзя будет создавать core-файлы. Первоначальная версия системного вызова setuid() в Linux поддерживала только 16-битные идентификаторы пользователя. Позднее в Linux 2.4 был добавлен вызов setuid32(), поддерживающий 32-битные идентификаторы. В glibc обёрточная функция setuid() работает одинаково вне зависимости от версий ядра.

СМОТРИТЕ ТАКЖЕ
getuid(2), seteuid(2), setfsuid(2), setreuid(2), capabilities(7), credentials(7), user_namespaces(7)