- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Linux программирование в примерах - Арнольд Роббинс
Шрифт:
Интервал:
Закладка:
Каждый процесс может получить все из этих значений. Обычный (не принадлежащий суперпользователю) процесс может переключать свои действительные и эффективные ID пользователя и группы. Процесс root (с эффективным UID, равным 0) может также устанавливать значения таким образом, как ему нужно (хотя это может оказаться односторонней операцией)
11.1.2. Биты Setuid и Setgid
Биты setuid и setgid[116] в правах доступа к файлу заставляют процесс принять эффективный UID или GID, который отличается от действительного. Эти биты накладываются на файл вручную с помощью команды 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 <unistd.h> /* POSIX */
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. Эту константу можно найти в современных системах в <limits.h>, а в старых системах в <sys/param.h>. Вскоре мы представим пример.
Возможно, вы заметили, что для получения сохраненных значений set-user ID или set-group ID нет вызовов. Это просто первоначальные значения эффективных UID и GID. Таким образом, для получения шести значений в начале программы вы можете использовать код наподобие этого:
uid_t ruid, euid, saved_uid;
gid_t rgid, egid, saved_gid;
int main(int argc, char **argv) {
ruid = getuid();
euid = saved_uid = geteuid();
rgid = getgid();
egid = saved_gid = getegid();
/* ...оставшаяся программа... */
}
Вот пример получения набора групп. В качестве расширения gawk предоставляет доступ на уровне awk к значениям действительных и эффективных UID и GID и дополнительному набору групп. Для этого он должен получить набор групп. Следующая функция из main.c в дистрибутиве gawk 3.1.3:
1080 /* init_groupset --- инициализация набора групп */
1081
1082 static void
1083 init_groupset()
1084 {
1085 #if defined(HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
1086 #ifdef GETGROUPS_NOT_STANDARD
1087 /* Для систем, которые не отвечают стандарту, используйте старый способ */
1088 ngroups = NGROUPS_MAX;
1089 #else
1090 /*
1091 * Если оба аргумента при вызове равны 0, возвращаемое
1092 * значение является общим числом групп.
1093 */
1094 ngroups = getgroups(0, NULL);
1095 #endif
1096 if (ngroups == -1)
1097 fatal(_("could not find groups: %s"), strerror(errno));
1098 else if (ngroups == 0)
1099 return;
1100
1101 /* заполнить группы */
1102 emalloc(groupset, GETGROUPS_T*, ngroups * sizeof(GETGROUPS_T), "init_groupset");
1103
1104 ngroups = getgroups(ngroups, groupset);
1105 if (ngroups == -1)
1106 fatal(_("could not find groups: %s"), strerror(errno));
1107 #endif
1108 }
Переменные ngroups и groupset глобальные; их объявления не показаны. Макрос GETGROUPS_T (строка 1102) является типом для использования со вторым аргументом: на системе POSIX это gid_t, в противном случае int.
Строки 1085 и 1107 заключают в скобки все тело функции; на древних системах, в которых вообще нет наборов групп, тело функции пустое.
Строки 1086–1088 обрабатывают не-POSIX системы; до компиляции программы механизмом конфигурации определяется GETGROUPS_NOT_STANDARD. В этом случае код использует NGROUPS_MAX, как описано выше. (Даже а 2004 г. такие системы все еще существуют и используются; хотя, слава богу, число их уменьшается.)
Строки 1089–1094 для систем POSIX, причем нулевой параметр size используется для получения числа групп.
Строки 1096–1099 осуществляют проверку ошибок. Если возвращаемое значение 0, дополнительных групп нет, поэтому init_groupset() просто сразу возвращается.
Наконец, строка 1102 для выделения массива достаточного размера использует malloc() (посредством проверяющего ошибки макроса-оболочки, см. раздел 3.2.1.8 «Пример: чтение строк произвольной длины»). Затем строка 1104 заполняет этот массив.
11.3. Проверка для действительного пользователя: access()
В большинстве случаев значения эффективного и действительного UID и GID являются одними и теми же. Таким образом, не имеет значения, что проверка прав доступа к файлу осуществляется по эффективному ID, а не по действительному.
Однако, при написании приложения с setuid или setgid вы можете иногда захотеть проверить, является ли операция, разрешенная для эффективных UID и GID, также разрешенной для действительных UID и GID. В этом заключается задача функции access():
#include <unistd.h> /* POSIX */
int access(const char *path, int amode);
Аргумент path является путем к файлу для проверки действительных UID и GID. amode содержит объединение побитовым ИЛИ одного или нескольких из следующих значений:
R_OK Действительный UID/GID разрешает чтение файла.
W_OK Действительный UID/GID разрешает запись в файл.
X_OK Действительный UID/GID разрешает исполнение файла или, в случае каталога, поиск в каталоге.
F_OK Проверка существования файла.
Проверяется каждый компонент в имени пути, а на некоторых реализациях при проверке для root access() может действовать, как если бы был установлен X_OK, даже если в правах доступа к файлу не установлены биты, разрешающие исполнение. (Странно, но верно: в этом случае предупрежденный вооружен.) В Linux нет такой проблемы.

