table of contents
access(2) | System Calls Manual | 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 *pathname, int mode);
#include <fcntl.h> /* Definicja stałych AT_* */ #include <unistd.h>
int faccessat(int dirfd, const char *pathname, 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 *pathname, int mode, int flags);
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 pathname. Jeśli pathname 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 podana w pathname 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 pathname 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 pathname 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 pathname 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 pathname 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 pathname (zob. też path_resolution(7)).
- EBADF
- (faccessat()) pathname jest względne, lecz dirfd nie wynosi ani AT_FDCWD (faccessat()), ani nie jest prawidłowym deskryptorem pliku.
- EFAULT
- pathname 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 pathname napotkano zbyt wiele dowiązań symbolicznych.
- ENAMETOOLONG
- Ścieżka pathname jest zbyt długa.
- ENOENT
- Składnik pathname nie istnieje lub jest wiszącym dowiązaniem symbolicznym.
- ENOMEM
- Brak pamięci jądra.
- ENOTDIR
- Składnik pathname, który powinien być katalogiem w rzeczywistości katalogiem nie jest.
- ENOTDIR
- (faccessat()) pathname 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ż ioctl_iflags(2).
- 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 pathname jest względną ścieżką, glibc konstruuje ścieżkę na bazie dowiązania symbolicznego w /proc/self/fd, które odpowiada argumentowi dirfd.
STANDARDY¶
- access()
- faccessat()
- POSIX.1-2008.
- faccessat2()
- Linux.
HISTORIA¶
- access()
- SVr4, 4.3BSD, POSIX.1-2001.
- faccessat()
- Linux 2.6.16, glibc 2.4.
- 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 pathname 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¶
Autorami polskiego tłumaczenia niniejszej strony podręcznika są: 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 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.
2 maja 2024 r. | Linux man-pages (niewydane) |