Каждый процесс может получить все из этих значений. Обычный (не принадлежащий суперпользователю) процесс может переключать свои действительные и эффективные ID пользователя и группы. Процесс root
(с эффективным UID, равным 0) может также устанавливать значения таким образом, как ему нужно (хотя это может оказаться односторонней операцией)
11.1.2. Биты Setuid и Setgid
Биты chmod
:
$ chmod u+s myprogram /* Добавить бит setuid */
$ chmod g+s myprogram /* Добавить бит setgid */
$ ls -l myprogram
-rwsr-sr-x 1 arnold devel 4573 Oct 9 18:17 myprogram
Наличие символа s в месте, где обычно находится символ x, указывает на присутствие битов setuid/setgid.
Как упоминалось в разделе 8.2.1 «Использование опций монтирования», опция nosuid
команды mount для файловой системы предотвращает обращение ядра к битам setuid и setgid. Это мера безопасности; например, пользователь с домашней системой GNU/Linux мог бы вручную изготовить гибкий диск с копией исполняемого файла оболочки с setuid, устанавливающей в root
. Но если система GNU/Linux в офисе или лаборатории монтирует файловые системы с гибкими дисками с опцией nosuid
, запуск этой оболочки не предоставит доступа с правами root
[117].
Каноническим (и возможно, злоупотребляемым) примером программы с setuid является игровая программа. Представьте, что вы написали по-настоящему крутую игру и хотите позволить пользователям системы играть в нее. Игра содержит файл счета, в котором перечислены высшие достижения.
Если вы не являетесь системным администратором, вы не можете создать отдельную группу только для тех пользователей, которым разрешено играть в игру и тем самым записывать в файл счета. Но если вы сделаете файл доступным для записи любому, чтобы каждый смог поиграть в игру, тогда каждый сможет также сжульничать и поместить наверх любое имя.
Однако, заставив программу устанавливать setuid на вас, пользователи, запускающие игру, получат ваш UID в качестве своего эффективного UID. Игровая программа сможет при этом открывать и обновлять файл счета по мере необходимости, но произвольные пользователи не смогут прийти и отредактировать его. (Вы подвергаете себя также большинству опасностей при программировании setuid; например, если в игровой программе есть дыра, которую можно использовать для запуска оболочки, действующей от вашего имени,
Та же логика применяется к программам setgid, хотя на практике программы с setgid используются гораздо реже, чем с setuid (Это также плохо; многие вещи, которые делаются программами с setuid root
, легко могут быть сделаны программами с setgid или программами, которые вместо этого устанавливают setuid на обычного пользователя[118]).
11.2. Получение ID пользователя и группы
Получение от системы сведений о UID и GID просто. Функции следующие:
#include
uid_t getuid(void); /* Действительный и эффективный UID */
uid_t geteuid(void);
gid_t getgid(void); /* Действительный и эффективный GID */
gid_t getegid(void);
int getgroups(int size, gid_t list[]); /* Список дополнительных групп*/
Функции:
uid_t getuid(void)
Возвращает действительный UID.
uid_t geteuid(void)
Возвращает эффективный UID.
gid_t getgid(void)
Возвращает действительный GID.
gid_t getegid(void)
Возвращает эффективный GID.
int getgroups(int size, gid_t list[])
Заполняет до size
элементов массива list
из набора дополнительных групп процесса. Возвращаемое значение является числом заполненных элементов или -1 при ошибке. Включается ли в набор также эффективный GID, зависит от реализации. На системах, совместимых с POSIX, можно передать в size нулевое значение; в этом случае getgroups()
возвращает число групп в наборе групп процесса. Затем можно использовать это значение для динамического выделения массива достаточного размера. На не-POSIX системах константа NGROUPS_MAX
определяет максимально допустимый размер для массива list
. Эту константу можно найти в современных системах в
, а в старых системах в
. Вскоре мы представим пример.