access(2)

NAZWA
access, faccessat, faccessat2 - sprawdza prawa użytkownika do pliku

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <unistd.h>

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

#include <fcntl.h>            /* Definicja stałych AT_* */
#include <unistd.h>

int faccessat(int dirfd, const char *path, int mode, int flags);
                /* Różnice między biblioteką C a jądrem opisano poniżej */

#include <fcntl.h>            /* Definicja stałych AT_* */
#include <sys/syscall.h>      /* Definicja stałych SYS_* */
#include <unistd.h>

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

    Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):

faccessat():
    Od glibc 2.10:
        _POSIX_C_SOURCE >= 200809L
    Przed glibc 2.10:
        _ATFILE_SOURCE

OPIS
access() sprawdza, czy wywołujący proces ma dostęp do pliku path. Jeśli path jest dowiązaniem symbolicznym, jest rozwiązywana.

Mode określa jakie sprawdzenia dostępności mają być wykonane i jest albo wartością F_OK albo maską zawierającą sumę logiczną jednego lub więcej z R_OK, W_OK i X_OK. F_OK sprawdza istnienie pliku. R_OK, W_OK i X_OK sprawdzają pod kątem istnienia pliku i, odpowiednio, uprawnień odczytu, zapisu i wykonania.

Sprawdzenie jest wykonywane za pomocą prawdziwych identyfikatorów użytkownika i grupy procesu, zamiast identyfikatorów efektywnych, jak dzieje się przy rzeczywistej próbie wykonania operacji (np. open(2)) na pliku. Podobnie, w przypadku użytkownika root, sprawdzenie używa zestawu przywilejów (ang. capabilities) dozwolonych zamiast zestawu przywilejów efektywnych; w przypadku użytkowników innych niż root, sprawdzenie używa pustego zestawu przywilejów.

Pozwala to programom korzystającym z ustawienia ID użytkownika podczas wykonania (suid) oraz programom obsługującym przywileje (ang. capabilities) na łatwe określenie uprawnień wywołującego użytkownika. Innymi słowy, access() nie odpowiada na pytanie "czy mogę odczytać/zapisać/wykonać ten plik?". Odpowiada na nieco inne "(zakładając, że jestem plikiem wykonywalnym korzystającym z suid) czy użytkownik, który mnie wywołał może odczytać/zapisać/wykonać ten plik?". Daje to programom korzystającym z suid możliwość uniemożliwienia zmuszania ich przez złośliwych użytkowników do odczytywania plików, których ci użytkownicy nie powinni móc odczytywać.

Jeśli wywołujący proces jest uprzywilejowany (tzn. jego identyfikator użytkownika wynosi zero), to sprawdzenie X_OK kończy się sukcesem, jeśli zwykły plik posiada uprawnienie wykonania dla dowolnego właściciela pliku, grupy itp.

  faccessat()
Wywołanie systemowe faccessat() operuje w dokładnie taki sam sposób jak access(), z wyjątkiem różnic opisanych tutaj.

Jeśli ścieżka path jest względna, jest to interpretowane w odniesieniu do katalogu do którego odnosi się deskryptor pliku dirfd (zamiast w odniesieniu do bieżącego katalogu roboczego procesu wywołującego, jak w stosunku do ścieżek względnych robi to access()).

Jeśli path jest względna a dirfd ma wartość specjalną AT_FDCWD, to pathname jest interpretowana w odniesieniu do bieżącego katalogu roboczego procesu wywołującego (jak access()).

Jeśli ścieżka path jest bezwzględna, to dirfd jest ignorowane.

Parametr flags jest tworzony jako suma logiczna (OR) zera lub większej liczby następujących wartości:

AT_EACCESS
    Przeprowadza sprawdzenie za pomocą efektywnych identyfikatorów użytkownika i grupy. Domyślnie faccessat() używa identyfikatorów rzeczywistych (jak access()).

AT_EMPTY_PATH (od Linuksa 5.8)
    Jeśli path jest pustym łańcuchem, działa na pliku do którego odnosi się dirfd (który mógł być pozyskany za pomocą znacznika O_PATH open(2)). W tym przypadku dirfd może odnosić się do dowolnego typu pliku, a nie tylko katalogu. Jeśli dirfd wynosi AT_FDCWD, to wywołanie działa na bieżącym katalogu roboczym. Znacznik ten jest charakterystyczny dla Linuksa; należy zdefiniować _GNU_SOURCE, aby pozyskać jego definicję.

AT_SYMLINK_NOFOLLOW
    Jeśli path jest dowiązaniem symbolicznym, nie rozwiązuje go: w zamian zwraca informacje o samym dowiązaniu.

Więcej informacji o potrzebie wprowadzenia faccessat() można znaleźć w podręczniku openat(2).

  faccessat2()
Powyższy opis faccessat() odnosi się do POSIX.1 i implementacji dostarczonej przez glibc. Implementacja glibc nie była jednak wiernym odwzorowaniem (zob. USTERKI), która prześlizgnęła się nad faktem, że surowe wywołanie linuksowe faccessat() nie posiadało argumentu flags. W celu poprawnej implementacji, Linux 5.8 dodał wywołanie systemowe faccessat2(), które obsługuje argument flags i pozwala na prawidłową implementację funkcji opakowującej faccessat().

WARTOŚĆ ZWRACANA
Gdy wszystko pójdzie dobrze (wszystkie żądane prawa są zapewnione, lub mode wynosi F_OK i plik istnieje), zwracane jest zero. W wypadku błędu (przynajmniej jeden bit z żądanych w mode uprawnień nie jest ustawiony, mode wynosi F_OK i plik nie istnieje lub wystąpiły inne błędy), zwracane jest -1 i ustawiane jest errno wskazując błąd.

BŁĘDY

EACCES
    Brak uprawnień dla żądanego dostępu do pliku, albo brak uprawnień do przeglądania któregoś z katalogów w ścieżce path (zob. też path_resolution(7)).

EBADF
    (faccessat()) path jest względna, lecz dirfd nie wynosi ani AT_FDCWD (faccessat()), ani nie jest prawidłowym deskryptorem pliku.

EFAULT
    path wskazuje poza dostępną dla użytkownika przestrzeń adresową.

EINVAL
    mode zostało nieprawidłowo podane.

EINVAL
    (faccessat()) Podano nieprawidłową opcję w flags.

EIO Wystąpił błąd wejścia/wyjścia.

ELOOP
    Podczas rozwiązywania path napotkano zbyt wiele dowiązań symbolicznych.

ENAMETOOLONG
    path jest zbyt długie.

ENOENT
    Składowa path nie istnieje lub jest wiszącym dowiązaniem symbolicznym.

ENOMEM
    Brak pamięci jądra.

ENOTDIR
    Składowa path, która powinna być katalogiem, w rzeczywistości katalogiem nie jest.

ENOTDIR
    (faccessat()) path jest względna, a dirfd jest deskryptorem pliku odnoszącym się do pliku zamiast do katalogu.

EPERM
    Żądano zapisu do pliku z ustawionym znacznikiem niezmienności. Zob. też FS_IOC_SETFLAGS(2const).

EROFS
    Żądano zapisu do pliku położonego w systemie plików tylko do odczytu.

ETXTBSY
    Wystąpiła próba dostępu z prawem zapisu do pliku aktualnie uruchomionego programu.

WERSJE
Jeśli proces posiada odpowiednie uprawnienia (tj. jest superużytkownikiem), POSIX.1-2001 zezwala na implementację wskazującą pomyślne zakończenie dla sprawdzenia X_OK nawet wtedy, gdy nie jest ustawiony żaden z bitów uruchamialności w prawach dostępu do pliku. Linux tego nie czyni.

  Różnice biblioteki C/jądra
Surowe wywołanie systemowe faccessat() przyjmuje jedynie trzy pierwsze argumenty. Znaczniki AT_EACCESS i AT_SYMLINK_NOFOLLOW są faktycznie zaimplementowane w opakowującej funkcji glibc do faccessat(). Jeśli nie podano żadnego z tych znaczników, funkcja opakowująca używa fstatat(2) do określenia uprawnień dostępu, zob. jednak USTERKI.

  Uwagi dla glibc
Na starszych wersjach jądra Linux, gdzie faccessat() nie jest dostępne (i gdzie znaczniki AT_EACCESS oraz AT_SYMLINK_NOFOLLOW nie są określone), funkcja opakowująca z glibc wraca do używania access(). Gdy path jest względna, glibc konstruuje ścieżkę na bazie dowiązania symbolicznego w /proc/self/fd, które odpowiada argumentowi dirfd.

STANDARDY

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

faccessat2()
    Linux.

HISTORIA

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

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

faccessat2()
    Linux 5.8.

UWAGI
Ostrzeżenie: Użycie tych wywołań w celu sprawdzenia, czy użytkownik ma uprawnienia na przykład do otwarcia pliku, przed otwarciem tego pliku za pomocą open(2) tworzy lukę bezpieczeństwa, ponieważ użytkownik może wykorzystać krótki moment pomiędzy sprawdzeniem pliku a otwarciem go do manipulacji na pliku. Z tego powodu należy unikać używania niniejszego wywołania systemowego (w opisanym właśnie przykładzie, bezpieczniejszą alternatywą byłoby tymczasowe przełączenie efektywnego identyfikatora użytkownika na jego identyfikator rzeczywisty, a następnie wywołanie open(2)).

access() zawsze podąża za dowiązaniami symbolicznymi. Jeśli konieczne jest sprawdzenie uprawnień samego dowiązania symbolicznego, należy użyć faccessat() ze znacznikiem AT_SYMLINK_NOFOLLOW.

Te wywołania zwracają błąd, jeśli jakikolwiek z żądanych w mode rodzajów dostępu zostanie odmówiony, nawet jeśli pozostałe typy dostępu z mode są dozwolone.

Plik jest dostępny tylko wówczas, gdy uprawnienia każdego z katalogów w jego ścieżce path przyznają dostęp do przeszukiwania (tj. wykonania). Jeśli dowolny katalog jest niedostępny, to wywołanie access() zawiedzie, niezależnie od uprawnień samego pliku.

Sprawdzane są jedynie bity dostępu, nie zawartość pliku czy jego typ. Dlatego, jeśli katalog okazuje się "zapisywalny", znaczy to prawdopodobnie, że można w nim tworzyć pliki, a nie, że do katalogu można pisać jak do pliku. Podobnie, plik dosowy może zostać zgłoszony jako "wykonywalny", lecz funkcja execve(2) mimo to zawiedzie.

Wywołania te mogą nie działać prawidłowo na systemach plików NFSv2 z włączonym mapowaniem UID, ponieważ mapowanie to jest dokonywane na serwerze i ukryte przed klientem sprawdzającym prawa dostępu (NFS w wersji 3 i wyższej dokonują sprawdzeń na serwerze). Podobny problem może wystąpić przy montowaniach FUSE.

USTERKI
Ze względu na to, że wywołanie systemowe jądra Linux faccessat() nie obsługuje argumentu flags, funkcja opakowująca faccessat() z glibc udostępniona w glibc 2.32 i wcześniejszych, emuluje wymaganą funkcjonalność za pomocą połączenia wywołania systemowego faccessat() oraz fstatat(2). Jednak emulacja ta nie bierze pod uwagę ACL-i (list kontroli dostępu do plików). Począwszy od glibc 2.33, funkcja opakowująca obchodzi tę usterkę, wykorzystując wywołanie systemowe faccessat2(), tam gdzie jest ono zapewnione przez jądro.

W Linuksie 2.4 (i wcześniejszych) obsługa testów X_OK dla superużytkownika jest nieco dziwna. Jeśli wszystkie kategorie uprawnień wykonania są wyłączone dla pliku niebędącego katalogiem, to jedynym testem access() zwracającym -1 jest sytuacja, gdy podany mode wynosi tylko X_OK; jeśli w mode określono również R_OK lub W_OK, to access() zwróci dla takich plików 0. Wczesny Linux 2.6 (do Linuksa 2.6.3 włącznie) zachowywał się również w ten sam sposób jak Linux 2.4.

Przed Linuksem 2.6.20, wywołania te ignorowały wpływ znacznika MS_NOEXEC, jeśli był on używany do wykonania mount(2) na systemie plików. Od Linuksa 2.6.20, znacznik MS_NOEXEC jest uwzględniany.

ZOBACZ TAKŻE
chmod(2), chown(2), open(2), setgid(2), setuid(2), stat(2), euidaccess(3), credentials(7), path_resolution(7), symlink(7)

TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: Przemek Borys <pborys@dione.ids.pl>, Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl> i Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 (https://www.gnu.org/licenses/gpl-3.0.html) lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.