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
У каждого процесса имеется несколько пользовательских и групповых идентификаторов. Реальные идентификаторы определяют принадлежность процесса. В большинстве реализаций UNIX для определения полномочий процесса при доступе к таким ресурсам, как файлы, применяются действующие идентификаторы. Но в Linux для определения полномочий доступа к файлам используются идентификаторы файловой системы, а действующие идентификаторы предназначены для проверки других полномочий. (Поскольку идентификаторы файловой системы обычно имеют такие же значения, как и соответствующие действующие идентификаторы, Linux при проверке полномочий доступа к файлам ведет себя точно так же, как и другие реализации UNIX.) Права доступа процесса также определяются с помощью дополнительных групповых идентификаторов — набора групп, в которые входит данный процесс. Извлекать и изменять его пользовательские и групповые ID процессу позволяют различные системные вызовы и библиотечные функции.
Когда запускается set-user-ID-программа, действующий пользовательский идентификатор процесса устанавливается на то значение, которое имеется у владельца файла. Этот механизм позволяет пользователю присвоить идентификатор, а следовательно, и полномочия другого пользователя при запуске конкретной программы. Аналогично, программы с полномочиями setgid изменяют действующий групповой ID процесса, в котором выполняется программа. Сохраненный установленный идентификатор пользователя (saved set-user-ID) и сохраненный установленный идентификатор группы (saved set-group-ID) позволяют программам с полномочиями setuid и setgid временно сбрасывать, а затем позже восстанавливать полномочия.
Пользовательский ID, равный нулю, имеет специальное значение. Обычно его имеет только одна учетная запись с именем root. Процессы с действующим идентификатором пользователя, равным нулю, являются привилегированными, то есть освобождаются от многих проверок полномочий, которые обычно выполняются при осуществлении процессом различных системных вызовов (например, при произвольном изменении различных пользовательских и групповых идентификаторов процесса).
9.1. Предположим, что в каждом из следующих случаев исходный набор пользовательских идентификаторов процесса такой: реальный = 1000, действующий = 0, сохраненный = 0, файловой системы = 0. Какими станут пользовательские идентификаторы после следующих вызовов:
1) setuid(2000);
2) setreuid(–1, 2000);
3) seteuid(2000);
4) setfsuid(2000);
5) setresuid(–1, 2000, 3000)?