Опубликован: 15.06.2004 | Уровень: специалист | Доступ: платный
Лекция 7:

Процессы

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >

Переустановить действующий идентификатор пользователя вызывающего процесса позволяют функции setuid() и seteuid() (см. листинг 7.11). Операция разрешена, если реальный или сохраненный ПДП-идентификатор пользователя совпадает со значением аргумента uid. Помимо этого, обладающие соответствующими привилегиями процессы с помощью функции setuid() могут установить по значению uid все три идентификатора пользователя процесса – реальный, действующий и сохраненный.

#include <unistd.h>
int setuid (uid_t uid);

#include <unistd.h>
int seteuid (uid_t uid);
Листинг 7.11. Описание функций setuid() и seteuid().

Для непривилегированных процессов по соображениям мобильности рекомендуется использование функции seteuid().

Аналогичные функции для переустановки идентификаторов группы процесса показаны в листинге 7.12.

#include <unistd.h>
int setgid (gid_t gid);

#include <unistd.h>
int setegid (gid_t gid);
Листинг 7.12. Описание функций setgid() и setegid().

Отметим, что функция для изменения списка дополнительных групп setgroups() относится к числу привилегированных и, следовательно, остается за рамками стандарта POSIX.

Проиллюстрируем использование описанных функций с помощью программы, показанной в листинге 7.13.

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>

int main (void) {
	uid_t uid;
	int nsupgroups;
	gid_t *supgroupslist;
	int i;
	/* Отменим буферизацию стандартного вывода */
	setbuf (stdout, NULL);
	printf ("Идентификаторы пользователя текущего
		процесса:\n" " реальный: %d, действующий:
		%d\n", uid = getuid (), geteuid ());
	printf ("Идентификаторы группы текущего
		процесса:\n" " реальный: %d, действующий:
		%d\n", getgid (), getegid ());
	printf ("Количество дополнительных групп
		текущего процесса: %d\n",
		nsupgroups = getgroups (0, supgroupslist));
	if (nsupgroups > 0) {
		if ((supgroupslist = (gid_t *) malloc
			(nsupgroups * sizeof (gid_t))) == NULL) {
			perror ("MALLOC");
		} else if (getgroups (nsupgroups,
			supgroupslist) == (-1)) {
			perror ("GETGROUPS");
		} else {
		/* Выдадим идентификаторы дополнительных */
		/* групп процесса */
			printf ("Идентификаторы дополнительных групп
				текущего процесса:\n");
			for (i = 0; i < nsupgroups; i++) {
				printf (" %d", supgroupslist [i]);
			}
		printf ("\n");
		}
	}
	/* Попробуем переустановить идентификатор */
	/* пользователя процесса */
	if (setuid ((uid_t) 1) != 0) {
		perror ("setuid (1)");
	}
	printf ("Идентификаторы пользователя текущего
		процесса после первой смены:\n"
		" реальный: %d, действующий: %d\n",
		getuid (), geteuid ());
	/* Попробуем вернуть прежний идентификатор */
	/* пользователя процесса */
	if (setuid (uid) != 0) {
		perror ("setuid (uid)");
	}
	printf ("Идентификаторы пользователя текущего
		процесса после второй смены:\n"
		" реальный: %d, действующий: %d\n",
		getuid (), geteuid ());
	/* Попробуем сменить действующий идентификатор */
	/* с помощью функции seteuid() */
	if (seteuid ((uid_t) 1) != 0) {
		perror ("seteuid (1)");
	}
	printf ("Идентификаторы пользователя текущего
		процесса после третьей смены:\n"
		" реальный: %d, действующий: %d\n",
		getuid (), geteuid ());
	return (0);
}
Листинг 7.13. Пример использования функций опроса и изменения идентификаторов пользователя процесса.

Если эту программу запустить от имени обычного пользователя, результат может выглядеть так, как показано в листинге 7.14.

Идентификаторы пользователя текущего процесса:
	реальный: 108, действующий: 108
Идентификаторы группы текущего процесса:
	реальный: 3, действующий: 3
Количество дополнительных групп текущего процесса: 1
Идентификаторы дополнительных групп текущего процесса: 3
setuid (1): Operation not permitted
Идентификаторы пользователя текущего процесса после первой смены:
	реальный: 108, действующий: 108
Идентификаторы пользователя текущего процесса после второй смены:
	реальный: 108, действующий: 108
seteuid (1): Operation not permitted
Идентификаторы пользователя текущего процесса после третьей смены:
	реальный: 108, действующий: 108
Листинг 7.14. Возможный результат работы программы, показанной в листинге 7.13 и запущенной от имени обычного пользователя.

После запуска той же программы от имени суперпользователя может получиться результат, показанный в листинге 7.15.

Идентификаторы пользователя текущего процесса:
	реальный: 0, действующий: 0
Идентификаторы группы текущего процесса:
	реальный: 0, действующий: 0
Количество дополнительных групп текущего процесса: 7
Идентификаторы дополнительных групп текущего процесса:
	0 1 2 3 4 6 10
Идентификаторы пользователя текущего процесса после первой смены:
	реальный: 1, действующий: 1
setuid (uid): Operation not permitted
Идентификаторы пользователя текущего процесса после второй смены:
	реальный: 1, действующий: 1
Идентификаторы пользователя текущего процесса после третьей смены:
	реальный: 1, действующий: 1
Листинг 7.15. Возможный результат работы программы, показанной в листинге 7.13 и запущенной от имени суперпользователя.

Утерять статус суперпользователя легко, а вернуть трудно...

Наконец, сделаем владельцем выполнимого файла рассматриваемой программы пользователя с идентификатором 1, то же проделаем с владеющей группой, взведем в режиме этого файла биты ПДИП и ПДИГ(на ОС Linux можно воспользоваться командой chmod ug+s ) и вновь запустим его от имени обычного пользователя (см. листинг 7.16).

Идентификаторы пользователя текущего процесса:
	реальный: 108, действующий: 1
Идентификаторы группы текущего процесса:
	реальный: 3, действующий: 1
Количество дополнительных групп текущего процесса: 1
Идентификаторы дополнительных групп текущего процесса:
	3
Идентификаторы пользователя текущего процесса после первой смены:
	реальный: 108, действующий: 1
Идентификаторы пользователя текущего процесса после второй смены:
	реальный: 108, действующий: 108
Идентификаторы пользователя текущего процесса после третьей смены:
	реальный: 108, действующий: 1
Листинг 7.16. Возможный результат работы программы, показанной в листинге 7.13 и запущенной от имени обычного пользователя после взведения в режиме выполнимого файла бита ПДИП.

Видно, что сохраненный ПДП-идентификатор помогает непривилегированному процессу переустанавливать действующий идентификатор пользователя.

Отметим, что если функция getgroups() применяется в программе несколько раз, то память под массив supgroupslist лучше отвести по максимуму, воспользовавшись выражением вида nsupgroups = sysconf (_SC_NGROUPS_MAX) + 1;.

Для опроса и/или изменения маски режима создания файлов вызывающего процесса предназначены служебная программа umask:

umask [-S] [маска]

и одноименная функция (см. листинг 7.17).

#include <sys/stat.h>>
mode_t umask (mode_t cmask);
Листинг 7.17. Описание функции umask().

Согласно стандарту, в маске могут фигурировать только биты режима доступа к файлам; трактовка прочих бит зависит от реализации.

Для служебной программы umask маска может задаваться и выводиться в символьной и восьмеричной формах. Маска в символьной форме является "позитивной" в том смысле, что заданные в ней биты режима доступа будут сохранены при создании файла. Восьмеричная форма – "негативная", заданные в ней биты будут "вычитаться" (очищаться) из режима доступа, заданного при создании. Синтаксис маски в umask аналогичен утилите chmod.

Опция -S предписывает выдавать маску в символьной форме.

Функция umask() устанавливает новую ("негативную") маску и возвращает старую.

Пример. Последовательность команд, показанная в листинге 7.18, выдаст результат, воспроизведенный в листинге 7.19.

umask 0
umask -S
umask -- -x
umask
Листинг 7.18. Пример использования служебной программы umask.
u=rwx,g=rwx,o=rwx
0111
7.19. Листинг 7.19. Возможный результат использования служебной программы umask.

Обратим внимание на употребление признака конца опций --. Он позволяет задавать аргументы, начинающиеся с минуса. Отметим также, что результаты, выдаваемые umask, могут в дальнейшем использоваться как аргументы данной утилиты (и в символьной, и в восьмеричных формах).

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >
Антон Коновалов
Антон Коновалов

В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13
Планируется ли актуализация материалов данного очень полезного курса?

Ирина Воскресенская
Ирина Воскресенская
Россия, Москва, НИЯУ МИФИ
Максим Баранов
Максим Баранов
Россия