Книга: Linux программирование в примерах
11.3. Проверка для действительного пользователя: access()
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 нет такой проблемы.
Если path
является символической ссылкой, access()
проверяет файл, на который указывает символическая ссылка.
Возвращаемое значение равно 0, если операция для действительных UID и GID разрешена, и -1 в противном случае. Соответственно, если access()
возвращает -1, программа с setuid может запретить доступ к файлу, с которым в противном случае эффективный UID/GID смог бы работать:
if (access("/some/special/file", R_OK|W_OK) < 0) {
fprintf(stderr, "Sorry: /some/special/file: %sn",
strerror(errno));
exit(1);
}
По крайней мере для серии ядра Linux 2.4, когда тест X_OK применяется к файловой системе, смонтированной с опцией noexec
(см. раздел 8.2.1 «Использование опций монтирования»), тест успешно проходится, если права доступа к файлу имеют разрешение на исполнение. Это верно, несмотря на то, что попытка выполнить файл завершилась бы неудачей.
ЗАМЕЧАНИЕ. Хотя использование access()
перед открытием файла является обычной практикой, существует состояние гонки открываемый файл может быть сброшен при подкачке между проверкой функцией access()
и вызовом open()
. Необходимо осмотрительное программирование, такое, как проверка владельца и прав доступа с помощью stat()
и fstat()
до и после вызовов access()
и open()
.
Например, программа pathchk
проверяет действительность имен путей. GNU версия использует access()
для проверки того, что компоненты каталога данного пути действительны. Из Coreutils pathchk.c
:
244 /* Возвращает 1, если PATH является годным к использованию
245 каталогом, 0 если нет, 2 если он не существует. */
246
247 static int
248 dir_ok(const char *path)
249 {
250 struct stat stats;
251
252 if (stat (path, &stats)) /* Nonzero return = failure */
253 return 2;
254
255 if (!S_ISDIR(stats.st_mode))
256 {
257 error(0, 0, _("'%s" is not a directory"), path);
258 return 0;
259 }
260
261 /* Используйте access для проверки прав доступа на поиск,
262 поскольку при проверке битов прав доступа st_mode они могут
263 потеряться новыми механизмами управления доступом. Конечно,
264 доступ теряется, если вы используете setuid. */
265 if (access (path, X_OK) != 0)
266 {
267 if (errno == EACCES)
268 error (0, 0, _("directory '%s' is not searchable"), path);
269 else
270 error(0, errno, "%s", path);
271 return 0;
272 }
273
274 return 1;
275 }
Код прост. Строки 252–253 проверяют, существует ли файл. Если stat()
завершится неудачей, файл не существует. Строки 255–259 удостоверяют, что файл в самом деле является каталогом.
Комментарий в строках 261–264 объясняет использование access()
. Проверки битов st_mode
недостаточно: файл может находиться в файловой системе, которая смонтирована только для чтения, в удаленной файловой системе или в файловой системе, не принадлежащей Linux или Unix, или у файла могут быть атрибуты, предотвращающие доступ. Таким образом, лишь ядро может в действительности сказать, будет ли работать access
. Строки 265–272 осуществляют проверку, выдавая сообщение об ошибке, определяемое значением errno
(строки 267–270).
- 11.1. Проверка прав доступа
- 11.2. Получение ID пользователя и группы
- 11.3. Проверка для действительного пользователя: access()
- 11.4. Проверка для эффективного пользователя: euidaccess() (GLIBC)
- 11.5. Установка дополнительных битов доступа для каталогов
- 11.6. Установка действительных и эффективных ID
- 11.7. Работа со всеми тремя ID: getresuid() и setresuid() (Linux)
- 11.8. Пересечение минного поля безопасности: setuid root
- 11.9. Рекомендуемая литература
- 11.10. Резюме
- Упражнения
- 11.1. Проверка прав доступа
- Листинг 10.1. (simpleid.c) Отображение идентификаторов пользователя и группы
- Сохранение информации о пользователях при миграции
- Практическая работа 53. Запуск Access. Работа с объектами базы данных
- Реальный (RID) и эффективный (EUID) идентификаторы пользователя
- 12. Лекция: Создание приложений с графическим интерфейсом пользователя.
- Создание пользователя и группы на рабочей станции
- 5. Null-значения и проверка условий
- Configure Access Control
- 1.1 Режимы ядра и пользователя Windows
- Запуск Access. Открытие учебной базы данных Борей
- Управление пользователями и разрешениями узла