access(2)

НАИМЕНОВАНИЕ
access, faccessat, faccessat2 - проверка прав доступа пользователя к файлу

БИБЛИОТЕКА
Стандартная библиотека языка C (libc, -lc)

ОБЗОР
#include <unistd.h>

int access(const char *path, int mode);

#include <fcntl.h>            /* определения констант AT_* */
#include <unistd.h>

int faccessat(int dirfd, const char *path, int mode, int flags);
                /* But see C library/kernel differences, below */

#include <fcntl.h>            /* определения констант AT_* */
#include <sys/syscall.h>      /* определения констант SYS_* */
#include <unistd.h>

int syscall(SYS_faccessat2,
            int dirfd, const char *path, int mode, int flags);

    Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

faccessat():
    Начиная с glibc 2.10:
        _POSIX_C_SOURCE >= 200809L
    До glibc 2.10:
        _ATFILE_SOURCE

ОПИСАНИЕ
access() checks whether the calling process can access the file path. If path is a symbolic link, it is dereferenced.

Аргумент mode - маска выполняемых проверок доступа; может быть равна значению F_OK, или состоять из результатов одной или нескольких поразрядных операций логическое ИЛИ с операндами R_OK, W_OK и X_OK. F_OK проверяет существование файла. R_OK, W_OK и X_OK запрашивают проверку, соответственно, существования файла и возможности его чтения, записи или выполнения.

Проверка осуществляется с использованием real (действительного), а не эффективного (текущего) идентификатора пользователя (UID) и группы (GID) вызвавших процесс. Эффективные идентификаторы будут использоваться при действительной попытке выполнения той или иной операции с файлом (например, open(2)). Аналогичным образом, для пользователя root, при проверке используется набор прав доступа, а не набор эффективных прав доступа; для не root-пользователей при проверке используется пустой набор прав доступа.

Это позволяет программам с set-user-ID (setuid) и программам с расширенными возможностями легко определять права доступа вызывавшего их пользователя. Другими словами программа access() не отвечает на запрос «может она прочитать/записать/выполнить этот файл?». Она отвечает на несколько иной запрос (в предположении, что это двоичный файл с setuid) : « может ли the user who invoked me (может ли пользователь, запустивший этот файл) прочитать/записать/выполнить этот файл?». Это даёт возможность программам с set-user-ID не дать злонамеренным пользователям прочитать файлы, которые они не имеют права прочитать.

Если вызвавший процесс имеет соответствующие привилегии (например, его реальный UID равен 0), то проверка X_OK пройдёт успешно для обычного файла, если у него установлено право на выполнение для любых владельце, групп или остальных.

  faccessat()
faccessat() действует точно так же, как access(), за исключением случаев, описанных здесь.

If path is relative, then it is interpreted relative to the directory referred to by the file descriptor dirfd (rather than relative to the current working directory of the calling process, as is done by access() for a relative pathname).

If path is relative and dirfd is the special value AT_FDCWD, then path is interpreted relative to the current working directory of the calling process (like access()).

If path is absolute, then dirfd is ignored.

Значение flags получается с помощью операции логическое ИЛИ с нулём или со следующими значениями:

AT_EACCESS
    Выполнять проверку, доступа используя эффективный идентификатор пользователя и группы. По умолчанию в faccessat() используются реальные идентификаторы (как в access()).

AT_EMPTY_PATH (начиная с Linux 5.8)
    If path is an empty string, operate on the file referred to by dirfd (which may have been obtained using the open(2) O_PATH flag). In this case, dirfd can refer to any type of file, not just a directory. If dirfd is AT_FDCWD, the call operates on the current working directory. This flag is Linux-specific; define _GNU_SOURCE to obtain its definition.

AT_SYMLINK_NOFOLLOW
    If path is a symbolic link, do not dereference it: instead return information about the link itself.

Смотрите в openat(2) объяснение необходимости faccessat().

  faccessat2()
Приведенное выше описание функции faccessat() соответствует POSIX.1 и реализации, предоставленной glibc. Однако реализация glibc была несовершенной эмуляцией (см. раздел "ОШИБКИ"), которая скрывала тот факт, что исходный системный вызов Linux faccessat() не имеет аргумента flags. Чтобы обеспечить правильную реализацию, в Linux 5.8 был добавлен системный вызов faccessat2(), который поддерживает аргумент flags и позволяет корректно реализовать функцию-оболочку faccessat().

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
В случае успеха (все запрошенные разрешения предоставлены, или mode это - F_OK и файл существует), то возвращается ноль. При ошибке (по крайней мере, из-за одного бита, в доступе mode было отказано или mode это - F_OK и файл не существует, или произошла какая-либо другая ошибка) возвращается значение -1 и устанавливается errno для указания на ошибку.

ОШИБКИ

EACCES
    The requested access would be denied to the file, or search permission is denied for one of the directories in the path prefix of path. (See also path_resolution(7).)

EBADF
    (faccessat()) path is relative but dirfd is neither AT_FDCWD (faccessat()) nor a valid file descriptor.

EFAULT
    Аргумент path указывает за пределы доступного адресного пространства.

EINVAL
    Аргумент mode был задан неверно.

EINVAL
    (faccessat()) Указано неверное значение в flags.

EIO Произошла ошибка ввода-вывода.

ELOOP
    Во время определения path встретилось слишком много символьных ссылок.

ENAMETOOLONG
    path слишком длинен.

ENOENT
    A component of path does not exist or is a dangling symbolic link.

ENOMEM
    Недостаточное количество памяти ядра.

ENOTDIR
    A component used as a directory in path is not, in fact, a directory.

ENOTDIR
    (faccessat()) path is relative and dirfd is a file descriptor referring to a file other than a directory.

EPERM
    Было запрошено разрешение на запись в файл, для которого установлен флаг неизменяемости. Смотрите также FS_IOC_SETFLAGS(const).

EROFS
    Запрошено право на запись в файл, расположенный в файловой системе, доступной только для чтения.

ETXTBSY
    Запрошены права на запись для исполняемого файла, который сейчас выполняется.

ВЕРСИИ
Если вызывающий процесс имеет соответствующие права доступа (например, суперпользователя), то POSIX.1-2001 позволяет реализации указывать на успешное выполнение проверки X_OK, даже если ни один из битов разрешения на выполнение файла не установлен. В Linux так не происходит.

  Отличия между библиотекой C и ядром
Системный вызов raw faccessat() принимает только первые три аргумента. Флаги AT_EACCESS и AT_SYMLINK_NOFOLLOW на самом деле реализованы в функции-оболочке glibc для faccessat(). Если указан любой из этих флагов, то функция-оболочка использует fstatat(2) для определения прав доступа, но видит ОШИБКИ.

  Замечания по glibc
On older kernels where faccessat() is unavailable (and when the AT_EACCESS and AT_SYMLINK_NOFOLLOW flags are not specified), the glibc wrapper function falls back to the use of access(). When path is relative, glibc constructs a pathname based on the symbolic link in /proc/self/fd that corresponds to the dirfd argument.

СТАНДАРТЫ

access()
faccessat()
    POSIX.1-2024.

faccessat2()
    Linux.

ИСТОРИЯ

access()
    4.3BSD, SVr4, POSIX.1-1988.

faccessat()
    Linux 2.6.16, glibc 2.4, POSIX.1-2008.

faccessat2()
    Linux 5.8.

ПРИМЕЧАНИЯ
Warning (предупреждение): Использование этих вызовов для проверки, например, разрешено ли пользователю открытие файла перед действительным выполнением open(2), создаёт брешь в безопасности, так как пользователь может использовать короткий промежуток времени между проверкой и открытием файла для управления им. По этой причине лучше избегать использования данного системного вызова (в только что описанном примере, безопасной альтернативой будет временное переключение эффективного пользовательского идентификатора процесса на действительный идентификатор и вызов open(2)).

Вызов access() всегда разыменовывает символьные ссылки. Если вам нужно проверить права символьной ссылки, используйте вызов faccessat() с флагом AT_SYMLINK_NOFOLLOW.

Эти вызовы возвращают ошибку, если отказано в любом из типов доступа mode, даже если разрешены остальные типы.

A file is accessible only if the permissions on each of the directories in the path prefix of path grant search (i.e., execute) access. If any directory is inaccessible, then the access() call fails, regardless of the permissions on the file itself.

Проверяются только биты доступа, а не тип файла или его содержимое. Следовательно, если обнаруживается, что каталог доступен для записи, это, вероятно, означает, что в нем могут быть созданы файлы, а не то, что каталог может быть записан в виде файла. Аналогично, файл DOS может быть указан как исполняемый, но вызов execve(2) все равно завершится ошибкой.

Эти вызовы access() могут некорректно работать на файловых системах NFSv2 со включённым преобразованием UID, потому что это преобразование происходит на сервере и спрятано от клиента, который пытается проверить права (в NFS версии 3 и выше выполняется проверка на сервере). Похожие проблемы могут возникать при монтировании FUSE.

ОШИБКИ
Поскольку системный вызов faccessat() ядра Linux не поддерживает аргумент flags, функция-оболочка glibc faccessat(), представленная в glibc 2.32 и в более ранних версиях, эмулирует требуемую функциональность, используя комбинацию системного вызова faccessat() и fstatat(2). Однако эта эмуляция не учитывает списки управления доступом. Начиная с glibc 2.33, функция-оболочка позволяет избежать этой ошибки, используя системный вызов faccessat 2(), который предоставляется основным ядром.

В Linux 2.4 (и более ранних версиях) есть некоторая странность в обработке тестов X_OK для суперпользователя. Если все категории разрешений на выполнение отключены для файла, не относящегося к каталогу, то единственный тест access(), который возвращает значение -1, выполняется, когда mode указан как просто X_OK; если R_OK или W_OK также указаны в mode, тогда функция access() возвращает 0 для таких файлов. Ранний Linux 2.6 (вплоть до Linux 2.6.3 включительно) также вел себя так же, как и Linux 2.4.

До Linux 2.6.20 эти вызовы игнорировали действие флага MS_NOEXEC, если он использовался для mount(2) базовой файловой системы. Начиная с Linux 2.6.20, флаг MS_NOEXEC поддерживается.

СМОТРИТЕ ТАКЖЕ
chmod(2), chown(2), open(2), setgid(2), setuid(2), stat(2), euidaccess(3), credentials(7), path_resolution(7), symlink(7)

ПЕРЕВОД
Русский перевод этой страницы руководства разработал(и) Dmitry Bolkhovskikh <d20052005@yandex.ru>, Yuri Kozlov <yuray@komyakino.ru> и Aleksandr Felda <isk8da@gmail.com>

Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков (<debian-l10n-russian@lists.debian.org>).