Выбрать главу

9.7.5. Пример: вывод на экран идентификаторов процесса

Программа, показанная в листинге 9.1, использует системные вызовы и библиотечные функции, рассмотренные на предыдущих страницах, для извлечения всех пользовательских и групповых идентификаторов процесса и вывода их на экран.

Листинг 9.1. Отображение на экране всех пользовательских и групповых идентификаторов процесса

proccred/idshow.c

#define _GNU_SOURCE

#include <unistd.h>

#include <sys/fsuid.h>

#include <limits.h>

#include "ugid_functions.h" /* userNameFromId() и groupNameFromId() */

#include "tlpi_hdr.h"

#define SG_SIZE (NGROUPS_MAX + 1)

int

main(int argc, char *argv[])

{

uid_t ruid, euid, suid, fsuid;

gid_t rgid, egid, sgid, fsgid;

gid_t suppGroups[SG_SIZE];

int numGroups, j;

char *p;

if (getresuid(&ruid, &euid, &suid) == -1)

errExit("getresuid");

if (getresgid(&rgid, &egid, &sgid) == -1)

errExit("getresgid");

/* Попытки изменения идентификаторов файловой системы для непривилегированных

процессов всегда игнорируются, но даже при этом следующие вызовы

возвращают текущие идентификаторы файловой системы */

fsuid = setfsuid(0);

fsgid = setfsgid(0);

printf("UID: ");

p = userNameFromId(ruid);

printf("real=%s (%ld); ", (p == NULL)?"???": p, (long) ruid);

p = userNameFromId(euid);

printf("eff=%s (%ld); ", (p == NULL)?"???": p, (long) euid);

p = userNameFromId(suid);

printf("saved=%s (%ld); ", (p == NULL)?"???": p, (long) suid);

p = userNameFromId(fsuid);

printf("fs=%s (%ld); ", (p == NULL)?"???": p, (long) fsuid);

printf("\n");

printf("GID: ");

p = groupNameFromId(rgid);

printf("real=%s (%ld); ", (p == NULL)?"???": p, (long) rgid);

p = groupNameFromId(egid);

printf("eff=%s (%ld); ", (p == NULL)?"???": p, (long) egid);

p = groupNameFromId(sgid);

printf("saved=%s (%ld); ", (p == NULL)?"???": p, (long) sgid);

p = groupNameFromId(fsgid);

printf("fs=%s (%ld); ", (p == NULL)?"???": p, (long) fsgid);

printf("\n");

numGroups = getgroups(SG_SIZE, suppGroups);

if (numGroups == -1)

errExit("getgroups");

printf("Supplementary groups (%d): ", numGroups);

for (j = 0; j < numGroups; j++) {

p = groupNameFromId(suppGroups[j]);

printf("%s (%ld) ", (p == NULL)?"???": p, (long) suppGroups[j]);

}

printf("\n");

exit(EXIT_SUCCESS);

}

proccred/idshow.c

9.8. Резюме

У каждого процесса имеется несколько пользовательских и групповых идентификаторов. Реальные идентификаторы определяют принадлежность процесса. В большинстве реализаций UNIX для определения полномочий процесса при доступе к таким ресурсам, как файлы, применяются действующие идентификаторы. Но в Linux для определения полномочий доступа к файлам используются идентификаторы файловой системы, а действующие идентификаторы предназначены для проверки других полномочий. (Поскольку идентификаторы файловой системы обычно имеют такие же значения, как и соответствующие действующие идентификаторы, Linux при проверке полномочий доступа к файлам ведет себя точно так же, как и другие реализации UNIX.) Права доступа процесса также определяются с помощью дополнительных групповых идентификаторов — набора групп, в которые входит данный процесс. Извлекать и изменять его пользовательские и групповые ID процессу позволяют различные системные вызовы и библиотечные функции.

Когда запускается set-user-ID-программа, действующий пользовательский идентификатор процесса устанавливается на то значение, которое имеется у владельца файла. Этот механизм позволяет пользователю присвоить идентификатор, а следовательно, и полномочия другого пользователя при запуске конкретной программы. Аналогично, программы с полномочиями setgid изменяют действующий групповой ID процесса, в котором выполняется программа. Сохраненный установленный идентификатор пользователя (saved set-user-ID) и сохраненный установленный идентификатор группы (saved set-group-ID) позволяют программам с полномочиями setuid и setgid временно сбрасывать, а затем позже восстанавливать полномочия.

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

9.9. Упражнения

9.1. Предположим, что в каждом из следующих случаев исходный набор пользовательских идентификаторов процесса такой: реальный = 1000, действующий = 0, сохраненный = 0, файловой системы = 0. Какими станут пользовательские идентификаторы после следующих вызовов:

1) setuid(2000);

2) setreuid(–1, 2000);

3) seteuid(2000);

4) setfsuid(2000);

5) setresuid(–1, 2000, 3000)?