Provided by: manpages-pl_4.27.0-1_all 

NAZWA
capabilities - przegląd przywilejów linuksowych
OPIS
Ze względu na sprawdzanie uprawnień, tradycyjna uniksowa implementacja rozróżnia dwie kategorie procesów:
procesy uprzywilejowane (których efektywny identyfikator użytkownika wynosi 0, zwane superużytkownikiem
lub rootem, rzadziej administratorem), oraz procesy nieuprzywilejowane (z niezerowym efektywnym ID
użytkownika). Procesy uprzywilejowane mogą pominąć wszelką kontrolę uprawnień jądra, natomiast procesy
nieuprzywilejowane są przedmiotem pełnej kontroli uprawnień w oparciu o referencje procesu (zwykle:
efektywne identyfikatory użytkownika oraz grupy, oraz uzupełniającą listę grup).
Począwszy od Linuksa 2.2, Linux dzieli uprawnienia tradycyjnie właściwe superużytkownikowi na odrębne
jednostki, zwane przywilejami (ang. capabilities), które można niezależnie włączać i wyłączać. Przywileje
są atrybutem przypisanym wątkowi.
Lista przywilejów
Poniżej przedstawiono listę ukazującą przywileje zaimplementowane w Linuksie oraz operacje lub
zachowania, na które pozwala każdy z przywilejów:
CAP_AUDIT_CONTROL (od Linuksa 2.6.11)
Włączanie i wyłączanie audytu jądra; zmiana reguł filtrowania audytu; pobieranie statusu audytu i
reguł filtrowania.
CAP_AUDIT_READ (od Linuksa 3.16)
Zezwala na odczyt dziennika audytu za pomocą gniazda multicastowego netlink.
CAP_AUDIT_WRITE (od Linuksa 2.6.11)
Zapisywanie rekordu do dziennika audytu jądra
CAP_BLOCK_SUSPEND (od Linuksa 3.5)
Włączanie funkcji zdolnych powstrzymać wstrzymanie systemu (EPOLLWAKEUP epoll(7),
/proc/sys/wake_lock).
CAP_BPF (od Linuksa 5.8)
Wykorzystywanie uprzywilejowanych operacji BPF (filtrowania pakietów Berkeley - przyp. tłum.),
zob. bpf(2) i bpf-helpers(7).
Ten przywilej dodano w Linuksie 5.8, aby wydzielić funkcjonalność BPF z przeładowanego przywileju
CAP_SYS_ADMIN.
CAP_CHECKPOINT_RESTORE (od Linuksa 5.9)
• Aktualizowanie /proc/sys/kernel/ns_last_pid (zob. pid_namespaces(7));
• wykorzystywanie funkcji set_tid clone3(2);
• odczytywanie zawartości dowiązań symbolicznych /proc/pid/map_files w przypadku innych procesów.
Ten przywilej dodano w Linuksie 5.9, aby wydzielić funkcjonalność punktów kontrolnych/przywracania
z przeładowanego przywileju CAP_SYS_ADMIN.
CAP_CHOWN
Czynienie dowolnych zmian w stosunku do identyfikatorów użytkownika i grupy (zob. chown(2)).
CAP_DAC_OVERRIDE
Pomijanie sprawdzeń uprawnień odczytu, zapisu i wykonania. (DAC jest skrótem od ang.
„discretionary access control” - tj. uznaniowa kontrola dostępu.)
CAP_DAC_READ_SEARCH
• Pomijanie sprawdzenia uprawnień odczytu pliku oraz sprawdzenia uprawnień odczytu i wykonania (a
właściwie przeszukania - przyp. tłum.) katalogu;
• wywoływanie open_by_handle_at(2);
• używanie znacznika AT_EMPTY_PATH linkat(2) do utworzenia linku do pliku opisanego deskryptorem
pliku.
CAP_FOWNER
• Pomijanie sprawdzenia uprawnień w przypadku operacji wymagających zwykle, aby identyfikator
użytkownika procesu pasował do identyfikatora użytkownika pliku (np. chmod(2), utime(2)), z
wyłączeniem operacji objętych przywilejami CAP_DAC_OVERRIDE i CAP_DAC_READ_SEARCH;
• ustawianie znaczników i-węzłów (zob. FS_IOC_SETFLAGS(2const)) dla dowolnych plików;
• ustawianie list kontroli dostępu do plików (ang. Access Control Lists - ACL) dla dowolnych
plików;
• ignorowanie bitu lepkości katalogu przy usuwaniu pliku;
• modyfikowanie atrybutów rozszerzonych użytkownika w przypadku katalogu z bitem lepkości,
będącego własnością dowolnego użytkownika;
• określanie O_NOATIME do dowolnych plików w open(2) i fcntl(2).
CAP_FSETID
• Brak czyszczenia bitów: ustawiania ID użytkownika lub ID grupy podczas wykonania (suid/sgid), w
momencie modyfikowania pliku;
• ustawianie bitu ustawiania ID grupy podczas wykonania (sgid) w przypadku plików, dla których
identyfikator grupy nie pasuje do systemu plików lub do jakiegokolwiek z dodatkowych
identyfikatorów grupy procesu wywołującego.
CAP_IPC_LOCK
• Blokowanie pamięci (mlock(2), mlockall(2), mmap(2), shmctl(2));
• Przydzielanie pamięci za pomocą dużych (ang. huge) stron (memfd_create(2), mmap(2), shmctl(2)).
CAP_IPC_OWNER
Pomijanie sprawdzania uprawnień w przypadku operacji na obiektach IPC Systemu V
CAP_KILL
Pominięcie sprawdzenia uprawnień przy wysyłaniu sygnałów (zob. kill(2)). Obejmuje to operację
KDSIGACCEPT ioctl(2).
CAP_LEASE (od Linuksa 2.4)
Dokonywanie dzierżaw na dowolnych plikach (zob. fcntl(2)).
CAP_LINUX_IMMUTABLE
Ustawianie znaczników i-węzłów FS_APPEND_FL i FS_IMMUTABLE_FL (zob. FS_IOC_SETFLAGS(2const)).
CAP_MAC_ADMIN (od Linuksa 2.6.25)
Zezwala na zmianę statusu lub konfiguracji MAC. Zaimplementowane do modułu Smack Linux Security
Module (LSM).
CAP_MAC_OVERRIDE (od Linuksa 2.6.25)
Przesłanianie obowiązkowej kontroli dostępu (ang. Mandatory Access Control - MAC).
Zaimplementowane do modułu Smack LSM.
CAP_MKNOD (od Linuksa 2.4)
Tworzenie plików specjalnych za pomocą mknod(2).
CAP_NET_ADMIN
Przeprowadzanie wielu operacji związanych z siecią:
• konfigurowanie interfejsu;
• administrowanie zaporą sieciową IP, maskaradowaniem oraz rozliczeniami;
• modyfikowanie tabel trasowania
• przypisywanie do dowolnego adresu w celu uzyskania przezroczystego proxy
• ustawianie typu usługi (ang. type-of-service - TOS);
• czyszczenie statystyk sterownika
• ustawianie trybu nasłuchiwania;
• włączanie multicastingu;
• używanie setsockopt(2) do ustawiania następujących opcji gniazd: SO_DEBUG, SO_MARK, SO_PRIORITY
(na priorytet spoza zakresu od 0 do 6), SO_RCVBUFFORCE i SO_SNDBUFFORCE.
CAP_NET_BIND_SERVICE
Kojarzenie gniazda z portami z uprzywilejowanej domeny internetowej (porty o numerach poniżej
1024).
CAP_NET_BROADCAST
(Nieużywane) Tworzenie gniazd rozgłoszeniowych oraz nasłuchiwanie multicastu.
CAP_NET_RAW
• Używanie gniazd RAW i PACKET
• przypisywanie do dowolnego adresu w celu uzyskania przezroczystego proxy.
CAP_PERFMON (od Linuksa 5.8)
Używanie wielu mechanizmów monitorowania wydajności, w tym:
• wywoływanie perf_event_open(2);
• wykonywanie wielu operacji BPF (filtrowania pakietów Berkeley - przyp. tłum.), które wpływają
na wydajność.
Ten przywilej dodano w Linuksie 5.8, aby wydzielić funkcjonalność monitorowania z przeładowanego
przywileju CAP_SYS_ADMIN. Więcej szczegółów w pliku źródeł jądra
Documentation/admin-guide/perf-security.rst.
CAP_SETGID
• Czynienie dowolnych zmian wobec identyfikatora grupy procesu oraz listy uzupełniających
identyfikatorów grup;
• fałszowanie identyfikatora grupy przy przekazywaniu referencji gniazd za pomocą gniazd domeny
uniksowej;
• zapisywanie przypisania identyfikatora grupy w przestrzeni nazw użytkownika (zob.
user_namespaces(7)).
CAP_SETFCAP (od Linuksa 2.6.24)
Ustawianie dowolnych przywilejów na pliku.
Od Linuksa 5.12 przywilej ten jest konieczny do przypisania identyfikatora użytkownika 0 w nowej
przestrzeni nazw; więcej szczegółów w podręczniku user_namespaces(7).
CAP_SETPCAP
Jeśli obsługiwane są przywileje pliku (tj. od Linuksa 2.6.24): dodawanie dowolnych przywilejów ze
zbioru ograniczonego wywołującego wątku do jego zbioru dziedzicznego; porzucanie przywilejów ze
zbioru ograniczonego (za pomocą PR_CAPBSET_DROP prctl(2)); dokonywanie zmian w znacznikach
securebits.
Jeśli przywileje pliku nie są obsługiwane (tj. przed Linuksem 2.6.24): przyznawanie lub usuwanie
dowolnych przywilejów w zbiorze przywilejów dozwolonych wywołującego lub z dowolnych innych
procesów (ta własność CAP_SETPCAP jest niedostępna gdy jądro skonfigurowano w celu obsługi
przywilejów pliku, ponieważ CAP_SETPCAP ma dla takich jąder zupełnie odmienną semantykę).
CAP_SETUID
• Czynienie dowolnych zmian wobec identyfikatorów użytkownika procesów (setuid(2), setreuid(2),
setresuid(2), setfsuid(2));
• fałszowanie identyfikatora użytkownika przy przekazywaniu referencji gniazd za pomocą gniazd
domeny uniksowej;
• zapisywanie przypisania identyfikatora użytkownika w przestrzeni nazw użytkownika (zob.
user_namespaces(7)).
CAP_SYS_ADMIN
Uwaga: niniejszy przywilej jest przeładowany, zob. Uwagi do deweloperów jądra poniżej.
• Wykonywanie wielu operacji z zakresu administracji systemem, w tym: quotactl(2), mount(2),
umount(2), pivot_root(2), swapon(2), swapoff(2), sethostname(2) i setdomainname(2);
• wykonywanie uprzywilejowanych operacji syslog(2) (od Linuksa 2.6.37 do zezwolenia na takie
operacje powinno się używać CAP_SYSLOG);
• wykonywanie polecenia vm86(2) VM86_REQUEST_IRQ;
• dostęp do takiej samej funkcjonalności punktów kontrolnych/przywracania jak ta zarządzana
przywilejem CAP_CHECKPOINT_RESTORE (jednak ten ostatni jest preferowany do uzyskiwania dostępu
do tej funkcjonalności, ponieważ jest bardziej ograniczony).
• przeprowadzanie takich samych operacji BPF (filtrowania pakietów Berkeley - przyp. tłum.) jak
te zarządzane przywilejem CAP_BPF (jednak ten ostatni jest preferowany do uzyskiwania dostępu
do tej funkcjonalności, ponieważ jest bardziej ograniczony).
• korzystanie z takich samych mechanizmów monitorowania wydajności, jak te zarządzane przywilejem
CAP_PERFMON (jednak ten ostatni jest preferowany do uzyskiwania dostępu do tej funkcjonalności,
ponieważ jest bardziej ograniczony).
• przeprowadzanie operacji IPC_SET i IPC_RMID na dowolnych obiektach IPC Systemu V;
• przesłanianie limitu zasobów RLIMIT_NPROC;
• przeprowadzanie operacji na atrybutach rozszerzonych: zaufanych i bezpieczeństwa (zob.
xattr(7));
• używanie lookup_dcookie(2);
• używanie ioprio_set(2) do przypisania klas harmonogramu wejścia/wyjścia IOPRIO_CLASS_RT i
(przed Linuksem 2.6.25) IOPRIO_CLASS_IDLE;
• fałszowanie identyfikatora procesu przy przekazywaniu referencji gniazd za pomocą gniazd domeny
uniksowej;
• wykraczanie poza określony w /proc/sys/fs/file-max systemowy limit otwartych plików, w
wywołaniach systemowych otwierających pliki (np. accept(2), execve(2), open(2), pipe(2));
• używanie znaczników CLONE_* tworzących nowe przestrzenie nazw za pomocą clone(2) i unshare(2)
(lecz, od Linuksa 3.8, tworzenie przestrzeni nazw użytkownika nie wymaga jakiegokolwiek
przywileju);
• dostęp do uprzywilejowanych informacji o zdarzeniach perf;
• wywoływanie setns(2) (wymaga CAP_SYS_ADMIN w docelowej przestrzeni nazw);
• wywoływanie fanotify_init(2);
• przeprowadzanie uprzywilejowanych operacji KEYCTL_CHOWN i KEYCTL_SETPERM keyctl(2);
• przeprowadzanie operacji MADV_HWPOISON madvise(2);
• wykorzystywanie TIOCSTI ioctl(2) do umieszczania znaków w kolejce wejściowej terminala innego,
niż terminal kontrolujący wywołującego;
• wykorzystywanie przestarzałego wywołania systemowego nfsservctl(2);
• wykorzystywanie przestarzałego wywołania systemowego bdflush(2);
• wykonywanie różnych operacji uprzywilejowanych ioctl(2) na urządzeniu blokowym;
• wykonywanie różnych operacji uprzywilejowanych ioctl(2) na systemie plików;
• wykonywanie operacji uprzywilejowanych ioctl(2) na urządzeniu /dev/random (zob. random(4));
• instalowanie filtru seccomp(2) bez uprzedniej konieczności ustawienia atrybutu wątku
no_new_privs;
• modyfikowanie reguł zezwalających/zabraniających w grupach kontroli urządzenia;
• wykorzystywanie operacji PTRACE_SECCOMP_GET_FILTER ptrace(2) do zrzucania filtrów seccomp
śledzącego;
• wykorzystywanie operacji PTRACE_SETOPTIONS ptrace(2) do zawieszania zabezpieczeń seccomp
śledzącego (np. znacznik PTRACE_O_SUSPEND_SECCOMP);
• dokonywanie operacji administracyjnych na wielu sterownikach urządzeń;
• modyfikacja wartości priorytetów nice autogrupy, za pomocą zapisu do /proc/pid/autogroup (zob.
sched(7)).
CAP_SYS_BOOT
Używanie reboot(2) i kexec_load(2).
CAP_SYS_CHROOT
• Używanie chroot(2);
• zmienianie przestrzeni nazw montowań za pomocą setns(2)
CAP_SYS_MODULE
• Ładowanie i usuwanie modułów jądra (zob. init_module(2) i delete_module(2));
• przed Linuksem 2.6.25: porzucanie przywilejów z systemowego, ograniczonego zbioru przywilejów.
CAP_SYS_NICE
• Zmniejszanie wartości nice procesu (nice(2), setpriority(2)) oraz zmienianie wartości nice
dowolnych procesów;
• ustawianie zasad planowania czasu rzeczywistego procesu wywołującego oraz ustawianie zasad
planowania i priorytetów dowolnych procesów (sched_setscheduler(2), sched_setparam(2),
sched_setattr(2));
• ustawianie koligacji procesorów (ang. affinity) dla dowolnych procesów (sched_setaffinity(2));
• ustawianie klasy i priorytetu planowania wejścia/wyjścia dowolnych procesów (ioprio_set(2));
• stosowanie migrate_pages(2) do dowolnych procesów oraz możliwość migrowania procesów do
dowolnych węzłów;
• stosowanie move_pages(2) do dowolnych procesów;
• używanie znaczniku MPOL_MF_MOVE_ALL z mbind(2) i move_pages(2).
CAP_SYS_PACCT
Używanie acct(2).
CAP_SYS_PTRACE
• Śledzenie dowolnych procesów za pomocą ptrace(2);
• stosowanie get_robust_list(2) do dowolnych procesów;
• transferowanie danych do i z pamięci, w przypadku dowolnych procesów, za pomocą
process_vm_readv(2) i process_vm_writev(2);
• dokonywanie inspekcji procesów za pomocą kcmp(2).
CAP_SYS_RAWIO
• Dokonywanie operacji wejścia/wyjścia na portach (iopl(2) i ioperm(2));
• uzyskiwanie dostępu do /proc/kcore;
• wykonywanie operacji FIBMAP ioctl(2);
• otwieranie urządzeń w celu dostępu do rejestrów charakterystycznych dla danego modelu x86 (ang.
model-specific register - MSR, zob. msr(4));
• aktualizowanie /proc/sys/vm/mmap_min_addr;
• tworzenie przypisań pamięci do adresów poniżej wartości określonej przez
/proc/sys/vm/mmap_min_addr;
• przypisywanie plików w /proc/bus/pci;
• otwieranie /dev/mem i /dev/kmem;
• wykonywanie rożnych poleceń w stosunku do urządzeń SCSI;
• wykonywanie określonych operacji na urządzeniach hpsa(4) i cciss(4);
• wykonywanie wielu charakterystycznych dla urządzenia operacji na innych urządzeniach.
CAP_SYS_RESOURCE
• Używanie zarezerwowanej przestrzeni w systemach plików ext2;
• tworzenie wywołań ioctl(2) kontrolujących działanie dziennika ext3;
• przesłanianie limitów przydziałów dyskowych;
• zwiększanie limitów zasobów (zob. setrlimit(2));
• przesłanianie limitu zasobów RLIMIT_NPROC;
• przesłanianie maksymalnej liczby konsol, przy przydzielaniu konsol;
• przesłanianie maksymalnej liczby mapowań klawiszy;
• zezwalanie na więcej niż 64hz przerwań z zegara czasu rzeczywistego;
• podnoszenie limitu msg_qbytes kolejki komunikatów Systemu V ponad limit określony w
/proc/sys/kernel/msgmnb (zob. msgop(2) i msgctl(2));
• możliwość pominięcia limitu zasobów RLIMIT_NOFILE, dotyczącego deskryptorów plików „w locie”,
przy przekazywaniu deskryptorów pliku do innego procesu za pomocą gniazd domeny uniksowej (zob.
unix(7));
• przesłanianie limitu /proc/sys/fs/pipe-size-max przy ustawianiu pojemności potoku za pomocą
polecenia F_SETPIPE_SZ fcntl(2);
• korzystanie z F_SETPIPE_SZ do zwiększania pojemności potoku ponad limit określony w
/proc/sys/fs/pipe-max-size;
• przesłanianie limitów /proc/sys/fs/mqueue/queues_max, /proc/sys/fs/mqueue/msg_max, i
/proc/sys/fs/mqueue/msgsize_max przy tworzeniu kolejek komunikatów POSIX (zob. mq_overview(7));
• korzystanie z operacji PR_SET_MM prctl(2);
• ustawianie /proc/pid/oom_score_adj na wartość niższą niż ostatnio ustawioną przez proces z
przywilejem CAP_SYS_RESOURCE.
CAP_SYS_TIME
Ustawianie zegara systemowego (settimeofday(2), stime(2), adjtimex(2)); ustawianie zegara czasu
rzeczywistego (sprzętowego).
CAP_SYS_TTY_CONFIG
Używanie vhangup(2); korzystanie z wielu uprzywilejowanych operacji ioctl(2) na terminalach
wirtualnych.
CAP_SYSLOG (od Linuksa 2.6.37)
• Wykonywanie uprzywilejowanych operacji syslog(2). Opis operacji wymagających uprzywilejowania
zawiera podręcznik systemowy syslog(2).
• Przeglądanie adresów ujawnionych w /proc i innych interfejsach, gdy
/proc/sys/kernel/kptr_restrict ma wartość 1 (zob. opis kptr_restrict w proc(5)).
CAP_WAKE_ALARM (od Linuksa 3.0)
Wyzwalanie czegoś, co wybudzi system (ustawienie budzików CLOCK_REALTIME_ALARM i
CLOCK_BOOTTIME_ALARM).
Przeszła i obecna implementacja
Pełna implementacja przywilejów wymaga aby:
• W przypadku wszystkich operacji uprzywilejowanych jądro sprawdzało, czy wątek ma odpowiedni przywilej
w swoim zbiorze efektywnym.
• Jądro zapewniało wywołania systemowe pozwalające na zmianę i pobranie przywilejów wątku.
• System plików obsługiwał dołączanie przywilejów do pliku wykonywalnego, aby proces mógł zyskiwać te
przywileje przy wykonywaniu pliku.
Przed Linuksem 2.6.24 jedynie dwa pierwsze warunki były spełnione, Linux od wersji 2.6.24 wypełnia
wszystkie trzy wymagania.
Uwagi do deweloperów jądra
Przy dodawaniu nowej funkcji, która powinna być zarządzania przywilejami, należy rozważyć poniższe
punkty.
• Celem przywilejów jest podzielenie uprawnień superużytkownika na fragmenty, dzięki czemu program,
którego jeden lub kilka przywilejów zostało przejętych, ma mniejsze możliwości uczynienia szkód w
systemie, niż ten sam program działający z uprawnieniami roota.
• Deweloper ma wybór: utworzyć nowy przywilej dla swojej nowej funkcji lub przypisanie funkcji do
jednego z istniejących. Aby zestaw przywilejów miał rozsądny rozmiar, zaleca się to drugie podejście,
chyba że istnieją przekonujące powody do tworzenia nowego przywileju (istnieje również limit
techniczny: zestaw przywilejów jest obecnie ograniczony do 64 bitów).
• Aby dowiedzieć się, który przywilej będzie najlepiej pasował do opracowywanej nowej funkcji, należy
sprawdzić powyższą listę przywilejów w kolejności, aby znaleźć „koszyk”, w którym nowa funkcja
najlepiej się odnajdzie. Jednym ze sposobów jest sprawdzenie, czy inne funkcje wymagające jakiegoś
przywileju będą zawsze używane z nową funkcją. Jeśli nowa funkcja jest bezużyteczna bez tych innych
funkcji, należy użyć tego samego przywileju jak one.
• Nie należy wybierać CAP_SYS_ADMIN, jeśli tylko uda się tego uniknąć! Wiele istniejących sprawdzeń
przywilejów jest z nim związanych (zob. częściową listę powyżej). Można go już przekonująco nazwać
„nowym rootem”, jako że, z jednej strony obejmuje cały szereg uprawnień, a z drugiej ze względu na
szerokie spektrum wymagany jest również przez wiele uprzywilejowanych programów. Nie należy pogłębiać
tego problemu. Jedynymi funkcjami, które należy wiązać z CAP_SYS_ADMIN są te ściśle pasujące do
istniejących funkcji tego koszyka.
• Jeśli okaże się, że istnieje jednak konieczność utworzenia nowego przywileju dla opracowywanej
funkcji, nie należy tworzyć go lub nazywać jako przywileju „jednorazowego”. Z tego względu na
przykład, dodanie bardzo specjalistycznego przywileju CAP_SYS_PACCT było najprawdopodobniej błędne.
Zamiast tego należy zidentyfikować i nazwać swój nowy przywilej jako szerszy koszyk, do którego
pasować mogą w przyszłości inne związane funkcje.
Zbiory przywilejów wątku
Każdy wątek ma następujący zbiór przywilejów zawierający zero lub więcej z przywilejów opisanych wyżej:
Dozwolony (ang. permitted)
Jest to ograniczający nadzbiór przywilejów efektywnych, jakie może przyjąć wątek. Jest to również
ograniczający nadzbiór przywilejów, jakie można dodać do zbioru dziedzicznego, w przypadku
przywilejów które można dodać do zbioru dziedzicznego przez wątek nieposiadający przywileju
CAP_SETPCAP w swoim zbiorze efektywnym.
Jeśli wątek porzuci przywilej ze swojego zbioru dozwolonego, nigdy nie może pozyskać tego
przywileju ponownie (chyba że execve(2) wykona program z set-user-ID-root lub program, którego
powiązane przywileje pliku dają taki przywilej).
Dziedziczny (ang. inheritable)
Jest to zbiór przywilejów zachowywany na przestrzeni całego execve(2). Przywileje dziedziczne
pozostają dziedziczone przy wykonywaniu dowolnego programu oraz są dodawane do zbioru dozwolonego
przy wykonywaniu programu, który ma ustawione odpowiadające bity w zbiorze dziedzicznym pliku.
Ze względu na to, że przywileje dziedziczne nie są zwykle zachowywane na przestrzeni execve(2)
przy działaniu jako użytkownik nieuprzywilejowany (nie root), programy które chciałyby wykonać
swoje programy pomocnicze z podniesionymi przywilejami, powinny rozważyć korzystanie z przywilejów
tła, opisanych poniżej.
Efektywny (ang. effective)
Jest to zbiór przywilejów używany przez jądro do sprawdzenia uprawnień wątku.
Ograniczający (ang. bounding; na wątek od Linuksa 2.6.25)
Zbiór przywilejów ograniczających jest mechanizmem używanym do ograniczenia przywilejów
pozyskiwanych w trakcie execve(2).
Od Linuksa 2.6.25, jest to zbiór przywilejów przypisywany do wątku. W starszych jądrach, zbiór
przywilejów ograniczających był systemowy i dzielony przez wszystkie wątki systemu.
Więcej szczegółów opisano w rozdziale Zbiór przywilejów ograniczających poniżej.
Tła (ang. ambient; od Linuksa 4.3)
Jest to zbiór przywilejów zachowywany na przestrzeni execve(2) nieuprzywilejowanego programu.
Przywileje tła przestrzegają zasady, że żaden przywilej nie może zostać przywilejem tła, jeśli nie
jest zarówno dozwolony jak i dziedziczny.
Zbiór przywilejów tła można modyfikować bezpośrednio za pomocą prctl(2). Przywileje tła są
automatycznie zmniejszane, jeśli zmniejszony zostanie odpowiadający przywilej dozwolony lub
dziedziczny.
Wykonanie programu zmieniającego identyfikator użytkownika lub grupy ze względu na bity ustawienia
ID użytkownika lub grupy podczas wykonania (suid/sgid) albo programu, który ma jakiekolwiek
przywileje plikowe, wyczyści zbiór przywilejów tła. Przywileje tła są dodawane do zbioru
dozwolonego i przypisywane do zbioru efektywnego przy wywołaniu execve(2). Jeśli przywilej tła
spowoduje zwiększenie przywilejów dozwolonych i efektywnych procesu podczas execve(2), nie wyzwoli
to trybu bezpiecznego wykonania opisanego w ld.so(8).
Wątek potomny utworzony za pomocą fork(2) dziedziczy kopie zbioru przywilejów swojego rodzica. Szczegóły
wpływu execve(2) na przywileje opisano w rozdziale Transformacja przywilejów podczas execve() poniżej.
Za pomocą capset(2), wątek może zmieniać swój zbiór przywilejów, zob. rozdział Programowe dostosowywanie
zbioru przywilejów poniżej.
Od Linuksa 3.2, plik /proc/sys/kernel/cap_last_cap ujawnia wartość numeryczną najwyższego przywileju
obsługiwanego przez działające jądro; można to wykorzystać do określenia najwyższego bitu, jaki można
ustawić w zbiorze przywilejów.
Przywileje pliku
Od Linuksa 2.6.24 jądro obsługuje powiązanie zbioru przywilejów z plikiem wykonywalnym za pomocą
setcap(8). Zbiory przywilejów pliku są przechowywane w atrybucie rozszerzonym (zob. setxattr(2) i
xattr(7)) o nazwie security.capability. Zapis do tego atrybutu rozszerzonego wymaga przywileju
CAP_SETFCAP. Zbiory przywilejów pliku, razem ze zbiorem przywilejów wątku, określają przywileje wątku po
execve(2).
Istnieją trzy zbiory przywilejów pliku:
Dozwolone (ang. permitted; wcześniej znane jako wymuszone - ang. forced):
Te przywileje są automatycznie dozwolone dla wątku, niezależnie od przywilejów dziedzicznych
wątku.
Dziedziczne (ang. inheritable; wcześniej znane jako dozwolone - ang. allowed):
Na tym zbiorze wykonywana jest operacja AND ze zbiorem dziedzicznym wątku, w celu określenia które
przywileje dziedziczne są włączone w zbiorze dozwolonym wątku, po execve(2).
Efektywne (ang. effective)
Nie jest to zbiór, lecz pojedynczy bit. Jeśli jest ustawiony, to podczas execve(2) wszystkie nowo
dozwolone przywileje wątku są również podnoszone w zbiorze efektywnym. Jeśli bit jest
nieustawiony, to po execve(2), żaden z nowo dozwolonych przywilejów nie trafia do nowego zbioru
efektywnego.
Włączenie efektywnego bitu przywilejów pliku wymusza sytuację, że przywilej dozwolony lub
dziedziczny dowolnego pliku, który powoduje pozyskanie przez wątek odpowiadającego przywileju
podczas execve(2) (zob. Transformacja przywilejów podczas execve() poniżej) pozyska również ten
przywilej w swoim zbiorze efektywnym. Z tego względu przy przypisywaniu przywilejów do pliku
(cap_set_file(3), cap_set_fd(3), setcap(8)), jeśli poda się znacznik przywileju efektywnego, jako
mającą być włączoną dla dowolnego przywileju, to znacznik efektywny musi być również podany jako
włączony dla wszystkich innych przywilejów, dla których odpowiadający znacznik dozwolony lub
dziedziczny jest włączony.
Wersjonowanie atrybutu rozszerzonego przywilejów pliku
W celu zachowania przyszłej rozszerzalności, jądro obsługuje sposób kodowania numeru wersji wewnątrz
atrybutu rozszerzonego security.capability, który jest używany do implementacji przywilejów pliku.
Poniższe numery wersji są wewnętrzne i niewidoczne wprost dla aplikacji w przestrzeni użytkownika. Do tej
pory obsługiwane są następujące wersje:
VFS_CAP_REVISION_1
Była to oryginalna implementacja przywilejów pliku, obsługująca 32-bitowe maski przywilejów pliku.
VFS_CAP_REVISION_2 (od Linuksa 2.6.25)
Ta wersja pozwalała na maski przywilejów pliku o rozmiarze 64 bitów oraz była konieczna wobec
przekroczenia przez przywileje liczby 32. Jądro kontynuuje obsługę plików, które mają 32-bitową
maskę przywilejów w wersji 1, w sposób przezroczysty, lecz przy dodawaniu przywilejów do plików,
które uprzednio ich nie posiadały oraz przy modyfikacji przywilejów istniejących plików,
automatycznie użyje wersji 2 (lub wersji 3, zgodnie z opisem poniżej).
VFS_CAP_REVISION_3 (od Linuksa 4.14)
Wersja 3 przywilejów plików zapewnia przywileje przestrzeni nazw plików (opisanych niżej).
Podobnie jak w wersji 2 przywilejów pliku, maski przywilejów w wersji 3 mają rozmiar 64 bitów.
Jednak oprócz tego, w atrybucie rozszerzonym security.capability zakodowano przestrzeń nazw
identyfikatora użytkownika root (jest to wartość, którą użytkownik o identyfikatorze 0 wewnątrz
tej przestrzeni nazw przypisuje początkowej przestrzeni nazw użytkownika).
Przywileje pliku w wersji 3 są zaprojektowane do wspólnej egzystencji z przywilejami pliku w
wersji 2 tj. we współczesnym systemie Linux część plików może mieć przywileje w wersji 2, a inne w
wersji 3.
Przed Linuksem 4.14, jedynym rodzajem atrybutu rozszerzonego przywileju pliku, jaki mógł być dołączony do
pliku, był atrybut VFS_CAP_REVISION_2. Od jądra Linux 4.14, wersja atrybutu rozszerzonego
security.capability dołączonego do pliku zależy od okoliczności, w jakich utworzono atrybut.
Od Linuksa 4.14, atrybut rozszerzony security.capability jest tworzony (lub przekształcany) automatycznie
na atrybut w wersji 3 (VFS_CAP_REVISION_3) jeśli spełnione są oba poniższe warunki:
• Wątek zapisujący do atrybutu rezyduje w niepierwotnej przestrzeni nazw użytkownika (ściślej mówiąc:
wątek rezydujący w przestrzeni nazw użytkownika innej niż ta, z której zamontowano zasadniczy system
plików.)
• Wątek ma przywilej CAP_SETFCAP wobec i-węzła pliku, co oznacza, że (a) wątek ma przywilej CAP_SETFCAP
wobec swojej przestrzeni nazw użytkownika oraz (b) identyfikatory użytkownika i grupy i-węzła pliku
mają przypisania w przestrzeni nazw użytkownika zapisującego.
Gdy tworzony jest atrybut rozszerzony security.capability VFS_CAP_REVISION_3, identyfikator użytkownika
root tworzącego wątku w przestrzeni nazw użytkownika jest zapisywany w atrybucie rozszerzonym.
Odmiennie, przy tworzeniu lub modyfikacji atrybutu rozszerzonego security.capability z uprzywilejowanego
(CAP_SETFCAP) wątku rezydującego w przestrzeni nazw, w której zamontowano zasadniczy system plików
(zwykle oznacza to pierwotną przestrzeń nazw użytkownika), atrybut zostanie automatycznie utworzony w
wersji 2 (VFS_CAP_REVISION_2).
Proszę zauważyć, że utworzenie wersji 3 atrybutu rozszerzonego security.capability jest automatyczne.
Oznacza to, że jeśli program w przestrzeni użytkownika dokonuje zapisu (setxattr(2)) atrybutu
security.capability w wersji 2, jądro automatycznie utworzy atrybut w wersji 3, jeśli atrybut jest
utworzony w okolicznościach opisach powyżej. Odpowiednio, gdy pobierany jest atrybut security.capability
w wersji 3 (getxattr(2)) przez proces rezydujący w przestrzeni nazw użytkownika, który został utworzony
przez identyfikator użytkownika roota (lub potomek tej przestrzeni nazw użytkownika), zwracany atrybut
jest (automatycznie) upraszczany, aby wyglądał na atrybut w wersji 2 (tzn. wartość zwracana ma rozmiar
atrybutu w wersji 2 oraz nie zawiera identyfikatora użytkownika root). To tłumaczenie w locie oznacza, że
w narzędziach przestrzeni użytkownika (np. setcap(1) i getcap(1)) nie są konieczne zmiany aby używać tych
narzędzi do tworzenia i pobierania atrybutów security.capability w wersji 3.
Proszę zwrócić uwagę, że plik może posiadać powiązany z nim atrybut rozszerzony security.capability w
wersji 2 albo w wersji 3, ale nie obu: utworzenie albo modyfikacja atrybutu rozszerzonego
security.capability automatycznie zmodyfikuje wersję, w zależności od okoliczności, w jakich utworzono
lub zmodyfikowano atrybut rozszerzony.
Transformacja przywilejów podczas execve()
Podczas execve(2), jądro oblicza nowe przywileje procesu za pomocą poniższego algorytmu:
P'(tła) = (plik jest uprzywilejowany) ? 0 : P(tła)
P'(dozwolony) = (P(dziedziczny) & F(dziedziczny)) |
(F(dozwolony) & P(ograniczający)) | P'(tła)
P'(efektywny) = F(efektywny) ? P'(dozwolony) : P'(tła)
P'(dziedziczny) = P(dziedziczny) [tzn. bez zmian]
P'(ograniczający) = P(ograniczający) [tzn. bez zmian]
gdzie:
P() oznacza wartość zbioru przywilejów wątku przed execve(2)
P'() oznacza wartość zbioru przywilejów wątku po execve(2)
F() oznacza zbiór przywilejów pliku
Proszę zwrócić uwagę na detale odnoszące się do powyższych reguł transformacji przywilejów:
• Zbiór przywilejów tła jest obecny jedynie od Linuksa 4.3. Przy określaniu transformacji zbioru tła
podczas execve(2), plikiem uprzywilejowanym jest plik posiadający przywileje lub ustawiony bit
ustawienia ID użytkownika lub grupy podczas wykonania (suid/sgid).
• Przed Linuksem 2.6.25, zbiór ograniczający był atrybutem systemowym dzielonym przez wszystkie wątki.
Ta wartość systemowa była używana do obliczania podczas execve(2) nowego zbioru dozwolonego w ten sam
sposób jak pokazano powyżej dla P(ograniczającego).
Uwaga: podczas przekształceń przywilejów opisanych powyżej, przywileje plików mogą zostać zignorowane
(potraktowane jako puste) z tych samych powodów jak ignorowane są bity ustawienia ID użytkownika lub
grupy podczas wykonania (suid/sgid); zob. execve(2). Przywileje pliku są ignorowane w podobny sposób,
jeśli rozruch jądra nastąpił z opcją no_file_caps.
Uwaga: zgodnie z powyższymi regułami, jeśli proces z niezerowym identyfikatorem użytkownika wykona
execve(2), to wszystkie przywileje obecne w jego zbiorze dozwolonym i efektywnym zostaną wyczyszczone.
Sposób traktowania przywilejów, gdy proces z identyfikatorem użytkownika równym zero wykonuje execve(2),
opisano w rozdziale Przywileje i wykonanie programów przez roota poniżej.
Kontrola bezpieczeństwa plików binarnych ślepych na przywileje
Plikiem binarnym ślepym na przywileje (ang. capability-dumb) jest program oznaczony jako posiadający
przywileje pliku, ale który nie został zmieniony w celu używania API libcap(3) do modyfikacji swoich
przywilejów (innymi słowy jest to program korzystający z tradycyjnego bitu ustawienia ID roota podczas
wykonania (suid), który został przełączony do korzystania z przywilejów pliku, ale którego kodu nie
zmodyfikowano w celu rozumienia przywilejów). W przypadku takich programów bit przywilejów efektywnych
jest ustawiany na pliku, dzięki czemu przywileje dozwolone pliku są automatycznie włączone w zbiorze
efektywnym procesu, gdy plik jest wykonywany. Jądro rozpoznaje plik, który posiada ustawiony bit
efektywnych przywilejów, jako ślepego na przywileje, do celu opisywanej tu kontroli.
Przy wykonywaniu pliku binarnego ślepego na przywileje, jądro sprawdza, czy proces pozyskał wszelkie
przywileje dozwolone, które zostały podane w zbiorze dozwolonym pliku, po transformacji przywilejów
opisanej wyżej (typowym powodem, dla którego może to nie nastąpić, jest zamaskowanie przez zbiór
ograniczający przywilejów niektórych przywilejów ze zbioru dozwolonego pliku). Jeśli proces nie pobierze
pełnego zbioru przywilejów dozwolonych, to execve(2) nie powiedzie się z błędem EPERM. Zapobiega się w
ten sposób potencjalnemu zagrożeniu bezpieczeństwa, które mogłoby wystąpić, gdyby aplikacja ślepa na
przywileje została wykonana z mniejszymi przywilejami niż jest to wymagane. Proszę zauważyć, że z
definicji, aplikacja nie może sama rozpoznać tego problemu, ponieważ nie korzysta z API libcap(3).
Przywileje i wykonanie programów przez roota
Aby odtworzyć tradycyjną semantykę uniksową, jądro w sposób specjalny traktuje przywileje pliku, gdy
program jest wykonywany przez proces z UID 0 (tj. roota) lub gdy wykonywany jest program z bitem
ustawienia ID roota (suid).
Po przeprowadzeniu zmian wobec efektywnego identyfikatora procesu wyzwolonych przez bit ustawienia ID
użytkownika (suid) pliku binarnego — jak np. przełączenie efektywnego identyfikatora użytkownika na 0
(tj. root), ponieważ wykonano program z ustawieniem ID użytkownika (suid) — jądro oblicza zbiór
przywilejów pliku zgodnie z poniższymi zasadami:
(1) Jeśli rzeczywistym lub efektywnym identyfikatorem użytkownika jest 0 (tj. root), to zbiory
dziedziczne i dozwolone pliku są ignorowane; zamiast tego są one rozważane jako wszystkie (tzn.
wszystkie przywileje włączone). Wobec tego zachowania istnieje jeden wyjątek, opisany poniżej w
rozdziale Programy z ustawieniem ID użytkownika (suid), które posiadają przywileje pliku.
(2) Jeśli proces ma identyfikator efektywny użytkownika równy 0 (tj. root) lub włączono bit efektywny
pliku, to rozważany jest bit efektywny pliku (jako włączony).
Te rozważane wartości zbioru przywilejów pliku są następnie używane zgodnie z opisem powyżej, do
obliczenia transformacji przywilejów procesu podczas execve(2).
Dlatego, gdy proces z niezerowym UID wykonuje execve(2) na programie z ustawieniem ID roota podczas
wykonania (suid), który nie posiada dołączonych przywilejów albo gdy proces, którego rzeczywiste i
efektywne identyfikatory użytkownika wynoszą 0 i wykonuje execve(2) na programie, obliczenie nowych
dozwolonych przywilejów procesu upraszcza się do:
P'(dozwolony) = P(dziedziczny) | P(ograniczający)
P'(efektywny) = P'(dozwolony)
W efekcie, proces zyskuje wszystkie przywileje ze swojego zbioru dozwolonego i efektywnego, z wyjątkiem
tych wyłączonych zbiorem przywilejów ograniczających (w obliczeniu P'(dozwolonego), wyrażenie P'(tła)
można uprościć i wykreślić, ponieważ jest to z definicji prawidłowy podzbiór P(dziedzicznych)).
Specjalne traktowanie użytkownika o identyfikatorze równym 0 (tj. roota) opisane w niniejszym
podrozdziale, można wyłączyć za pomocą mechanizmu securebits opisanego poniżej.
Programy z ustawieniem ID roota podczas wykonania (suid), które posiadają przywileje pliku
Istnieje jeden wyjątek wobec zachowania opisanego powyżej w rozdziale Przywileje i wykonanie programów
przez roota. Jeśli (a) wykonywany plik binarny ma dołączone przywileje oraz (b) proces ma rzeczywisty
identyfikator użytkownika, który nie jest równy 0 (tj. nie jest rootem) oraz (c) proces ma efektywny
identyfikator użytkownika równy 0 (tj. root), to bity przywilejów pliku są honorowane (tzn. nie są
rozważane jako wszystkie włączone). Standardową sytuacją, w której może to nastąpić, jest wykonywanie
programu z ustawieniem ID roota podczas wykonania (suid), który ma również przywileje pliku. Gdy taki
program jest wykonywany, to proces zyskuje wyłącznie przywileje nadane przez program (tzn. nie wszystkie
przywileje, jak stałoby się przy wykonaniu programu z ustawieniem ID roota podczas wykonania (suid),
który nie ma przypisanych żadnych przywilejów pliku).
Proszę zauważyć, że można przypisać zbiór pusty przywilejów do pliku programu, zatem możliwe jest
utworzenie programu z ustawieniem ID roota podczas wykonania (suid), który zmienia efektywny i zapisany
suid procesu wykonującego program na 0, ale nie przyznaje mu żadnych przywilejów.
Zbiór przywilejów ograniczających
Zbiór przywilejów ograniczających jest mechanizmem bezpieczeństwa, którego można użyć do ograniczenia
przywilejów, które można zyskać podczas execve(2). Zbiór ograniczający jest używany na następujące
sposoby:
• Podczas execve(2), zbiór przywilejów ograniczających jest sumowany ze zbiorem przywilejów dozwolonych,
a wynik tej operacji jest przypisywany do zbioru przywilejów dozwolonych wątku. Zbiór przywilejów
ograniczających ogranicza zatem przywileje dozwolone, które mogą być przyznane plikowi wykonywalnemu.
• (Od Linuksa 2.6.25) Zbiór przywilejów ograniczających działa jako nadzbiór ograniczający wobec
przywilejów, które mogą być dodane przez wątek do swojego zbioru dziedzicznego za pomocą capset(2).
Oznacza to, że jeśli przywilej nie występuje w zbiorze ograniczającym, to wątek nie może dodać go do
swoich przywilejów dozwolonych, tym samym nie może zachować tego przywileju swoim zbiorze
dopuszczalnym, gdy wykona execve(2) na pliku, który posiada ten przywilej w swoim zbiorze
dziedzicznym.
Proszę zauważyć, że zbiór ograniczający ogranicza przywileje dozwolone, ale nie ogranicza przywilejów
dziedzicznych. Jeśli wątek zachowa przywilej, niebędący w jego zbiorze ograniczającym, w swoim zbiorze
dziedzicznym, to może wciąż zyskać ten przywilej w swoim zbiorze dozwolonym, wykonując plik, posiadający
ten przywilej w swoim zbiorze dziedzicznym.
W zależności od wersji jądra, zbiór przywilejów ograniczających jest atrybutem albo systemowym, albo
przypisanym wątkowi.
Zbiór przywilejów ograniczających od Linuksa 2.6.25
Od Linuksa 2.6.25, zbiór przywilejów ograniczających jest przypisany wątkowi (opisany niżej systemowy
zbiór przywilejów ograniczających już nie istnieje).
Zbiór ograniczający jest dziedziczony w momencie wykonania fork(2) od wątku rodzicielskiego i jest
zachowywany przy execve(2).
Wątek może usunąć przywileje ze swojego zbioru ograniczającego za pomocą operacji PR_CAPBSET_DROP
prctl(2), zakładając że ma przywilej CAP_SETPCAP. Po usunięciu przywileju ze zbioru ograniczającego, nie
da się go tam przywrócić. Wątek może sprawdzić czy przywilej znajduje się w jego zbiorze ograniczającym,
za pomocą operacji PR_CAPBSET_READ prctl(2).
Usuwanie przywilejów ze zbioru ograniczającego jest obsługiwane wyłącznie, jeśli w jądro wkompilowano
przywileje pliku. Przed Linuksem 2.6.33, przywileje pliku były opcjonalne i konfigurowało się je opcją
CONFIG_SECURITY_FILE_CAPABILITIES. Od Linuksa 2.6.33 opcję tę usunięto, a przywileje pliku są zawsze
częścią jądra. Gdy przywileje pliku wkompilowano w jądro, proces init (przodek wszystkich procesów)
zaczyna działanie z pełnym zbiorem ograniczającym. Jeśli przywileje pliku nie są wkompilowane w jądro, to
init rozpocznie z pełnym zbiorem ograniczającym minus CAP_SETPCAP, ponieważ przywilej ten zmienia
znaczenie, gdy nie występują przywileje pliku.
Usunięcie przywileju ze zbioru ograniczającego nie usuwa go ze zbioru dziedzicznego wątku. Uniemożliwia
jednak ponowne dodanie przywileju do zbioru dziedzicznego wątku w przyszłości.
Zbiór przywilejów ograniczających przed Linuksem 2.6.25
Przed Linuksem 2.6.25 zbiór przywilejów ograniczających jest atrybutem systemowym, dotyczącym wszystkich
wątków w systemie. Zbiór ograniczający jest dostępny za pośrednictwem pliku /proc/sys/kernel/cap-bound
(co mylące, ten parametr maski bitowej jest w /proc/sys/kernel/cap-bound prezentowany jako liczba
dziesiętna ze znakiem).
Tylko proces init może ustawić przywileje w zbiorze przywilejów ograniczających, natomiast
superużytkownik (precyzyjniej: proces z przywilejem CAP_SYS_MODULE) może jedynie usunąć przywileje z tego
zbioru.
W standardowym systemie, maska zbioru przywilejów ograniczających zawsze prowadzi do usunięcia przywileju
CAP_SETPCAP. Aby usunąć to ograniczenie (niebezpieczne!), należy zmodyfikować definicję CAP_INIT_EFF_SET
w include/linux/capability.h i przebudować jądro.
Funkcję systemowego zbioru przywilejów ograniczających dodano w jądrze Linux 2.2.11.
Wpływ zmian identyfikatora użytkownika na przywileje
Aby zachować tradycyjną semantykę przejścia pomiędzy identyfikatorami użytkowników równymi i różnymi od
0, jądro dokonuje następujących zmian w zbiorach przywilejów wątku przy zmianach następujących
identyfikatorów użytkownika (za pomocą setuid(2), setresuid(2) lub podobnych): rzeczywistego,
efektywnego, zbioru zapisanego oraz systemu plików:
• Jeśli jeden lub kilka z identyfikatorów: rzeczywistego, efektywnego lub zbioru zapisanego wynosił
uprzednio 0, a wynikiem zmian identyfikatorów użytkowników jest wartość niezerowa wszystkich tych
identyfikatorów, to ze zbioru przywilejów: dozwolonego, efektywnego i tła usuwane są wszystkie
przywileje.
• Jeśli efektywny identyfikator użytkownika zmienił się z 0 na wartość niezerową, to ze zbioru
efektywnego usuwane są wszystkie przywileje.
• Jeśli efektywny identyfikator użytkownika zmienił się z wartości niezerowej na 0, to zbiór dozwolony
jest kopiowany do zbioru efektywnego.
• Jeśli identyfikator użytkownika systemu plików zmienił się z 0 na wartość niezerową (zob.
setfsuid(2)), to następujące przywileje są usuwane ze zbioru efektywnego: CAP_CHOWN, CAP_DAC_OVERRIDE,
CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID, CAP_LINUX_IMMUTABLE (od Linuksa 2.6.30), CAP_MAC_OVERRIDE
i CAP_MKNOD (od Linuksa 2.6.30). Jeśli UID systemu plików zmieni się z wartości niezerowej na 0, to
przywileje włączone w zbiorze dozwolonym są włączane w zbiorze efektywnym.
Jeśli wątek posiadający wartość równą 0 dla jednego lub kilku swoich identyfikatorów użytkownika chce
zapobiec usunięciu swojego zbioru przywilejów dozwolonych przy zresetowaniu wszystkich swoich wartości
identyfikatorów użytkownika na wartości niezerowe, może to uczynić za pomocą znacznika securebits
SECBIT_KEEP_CAPS opisanego niżej.
Programowe dostosowywanie zbioru przywilejów
Wątek może pobierać i zmieniać swoje zbiory przywilejów: dozwolonych, efektywnych i dziedzicznych za
pomocą wywołań systemowych capget(2) i capset(2). Zaleca się jednak stosowanie do tego celu
cap_get_proc(3) i cap_set_proc(3) z pakietu libcap. Zmiany zbiorów przywilejów wątku rządzą się
następującymi prawami:
• Jeśli wywołujący nie posiada przywileju CAP_SETPCAP, to nowy zbiór dziedziczny musi być podzbiorem
kombinacji istniejących zbiorów: dziedzicznego i dozwolonego.
• (Od Linuksa 2.6.25) Nowy zbiór dziedziczny musi być podzbiorem kombinacji istniejących zbiorów:
dziedzicznego i ograniczającego.
• Nowy zbiór dozwolony musi być podzbiorem istniejącego zbioru dozwolonego (tzn. nie da się zyskać
nowych przywilejów dozwolonych, których wątek nie miał do tej pory).
• Nowy zbiór efektywny musi być podzbiorem nowego zbioru dozwolonego.
Znaczniki securebits: tworzenie środowiska korzystającego wyłącznie z przywilejów
Począwszy od Linuksa 2.6.26 i jądra, w którym włączono przywileje pliku, Linux implementuje zbiór
znaczników securebits przypisanych wątkowi, które mogą wyłączyć specjalne traktowanie przywilejów
identyfikatora użytkownika równego 0 (tj. roota). Występują znaczniki:
SECBIT_KEEP_CAPS
Ustawienie tego znacznika pozwala wątkowi posiadającemu jeden lub więcej UID-ów równych 0 na
zachowanie przywilejów w swoim zbiorze dozwolonym, po przełączeniu wszystkich swoich UID-ów na
wartości niezerowe. Jeśli znacznik ten nie jest ustawiony, to takie przełączenie powoduje utratę
przez wątek wszystkich przywilejów dozwolonych. Znacznik ta jest zawsze czyszczony przy wykonaniu
execve(2).
Proszę zauważyć, że nawet gdy ustawiony jest znacznik SECBIT_KEEP_CAPS, to przywileje efektywne
wątku są usuwane przy przełączeniu swojego efektywnego UID-u na wartość niezerową. Jednak gdy
wątek ma ten znacznik ustawiony, jego efektywny UID ma już wartość niezerową, a wątek przełączy
następnie wszystkie inne UID-y na wartości niezerowe, to przywileje efektywne wątku nie zostaną
usunięte.
Ustawienie znacznika SECBIT_KEEP_CAPS jest ignorowane, gdy ustawiony jest znacznik
SECBIT_NO_SETUID_FIXUP (ten ostatnia zapewnia nadzbiór efektów pierwszego znacznika).
Znacznik zapewnia taką samą funkcjonalność, jak starsza operacja PR_SET_KEEPCAPS prctl(2).
SECBIT_NO_SETUID_FIXUP
Ustawienie tego znacznika powstrzyma jądro przed dostosowywaniem zbiorów przywilejów procesu:
dozwolonych, efektywnych i tła, w sytuacji, gdy UID-y wątku: efektywne i systemu plików, są
przełączane między wartościami zera i niezerowymi. Więcej informacji w rozdziale Wpływ zmian
identyfikatora użytkownika na przywileje powyżej.
SECBIT_NOROOT
Jeśli bit ten jest ustawiony, jądro nie przydziela przywilejów gdy wykonywany jest program z
ustawieniem ID roota podczas wykonania (suid), albo gdy proces z efektywnym lub rzeczywistym
UID-em równym 0 wywołuje execve(2). (zob. rozdział Przywileje i wykonanie programów przez roota
powyżej.)
SECBIT_NO_CAP_AMBIENT_RAISE
Ustawienie tego znacznika uniemożliwia podniesienie przywilejów tła za pomocą operacji
PR_CAP_AMBIENT_RAISE prctl(2).
Każdy z powyższych znaczników „podstawowych” ma towarzyszący mu znacznik „blokujący”. Ustawienie
znacznika „blokującego” jest nieodwracalne i zapobiega dalszym zmianom odpowiadającemu mu znacznikowi
„podstawowemu”. Istnieją następujące znaczniki blokujące: SECBIT_KEEP_CAPS_LOCKED,
SECBIT_NO_SETUID_FIXUP_LOCKED, SECBIT_NOROOT_LOCKED i SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED.
Znaczniki securebits można zmodyfikować i pobrać za pomocą operacji PR_SET_SECUREBITS i PR_GET_SECUREBITS
prctl(2). Do modyfikowania znaczników potrzebny jest przywilej CAP_SETPCAP. Proszę zauważyć, że stałe
SECBIT_* są dostępne tylko wówczas, gdy są umieszczone w pliku nagłówkowym <linux/securebits.h>.
Znaczniki securebits są dziedziczone przez procesy potomne. Podczas execve(2) zachowywane są wszystkie
znaczniki poza SECBIT_KEEP_CAPS, który jest zawsze usuwany.
Aplikacja może użyć następującego wywołania do zablokowania siebie i wszystkich swoich potomków w
środowisku, w którym jedyną metodą zyskania przywilejów, jest wykonanie programu z powiązanymi
przywilejami plików:
prctl(PR_SET_SECUREBITS,
/* SECBIT_KEEP_CAPS wyłączone */
SECBIT_KEEP_CAPS_LOCKED |
SECBIT_NO_SETUID_FIXUP |
SECBIT_NO_SETUID_FIXUP_LOCKED |
SECBIT_NOROOT |
SECBIT_NOROOT_LOCKED);
/* Ustawienie/zablokowanie SECBIT_NO_CAP_AMBIENT_RAISE
nie jest wymagane */
Programy z ustawieniem ID roota podczas wykonania („set-user-ID-root”) na przestrzeń użytkownika
Programy z ustawieniem ID roota podczas wykonania (suid), których identyfikatory użytkownika pasują do
identyfikatorów użytkownika, który utworzył przestrzeń nazw użytkownika, będą miały przyznane przywileje
w zbiorach procesu: dozwolonym i efektywnym, przy wykonywaniu przez dowolny proces z tej przestrzeni nazw
i z każdej potomnej przestrzeni nazw.
Reguły regulujące transformację przywilejów procesu podczas execve(2) są identyczne z opisanymi w
Transformacja przywilejów podczas execve() oraz Przywileje i wykonanie programów przez roota powyżej, z
jedyną różnicą, że w drugim z podrozdziałów „root” jest identyfikatorem użytkownika tworzącego przestrzeń
nazw użytkownika.
Przywileje pliku w przestrzeni nazw
Tradycyjne (tzn. w wersji 2) przywileje pliku wiążą jedynie zbiór masek przywilejów z binarnym plikiem
wykonywalnym. Gdy proces wykonuje plik binarny z takimi przywilejami, zyskuje powiązane przywileje (w
swojej przestrzeni nazw) według reguł opisanych w rozdziale Transformacja przywilejów podczas execve()
powyżej.
Ponieważ przywileje pliku w wersji 2 przyznają przywileje procesowi wykonującemu bez względu na
przestrzeń nazw, w której on rezyduje, jedynie procesy uprzywilejowane mogą przypisywać przywileje do
pliku. Tu „uprzywilejowany” oznacza proces, który ma przywilej CAP_SETFCAP w przestrzeni nazw
użytkownika, w której zamontowano system plików (zwykle pierwotna przestrzeń nazw użytkownika). To
ograniczenie czyni przywileje pliku bezużytecznymi w niektórych zastosowaniach. Przykładowo, w
kontenerach przestrzeni nazw użytkownika przydatna może się okazać możliwość utworzenia pliku binarnego,
który przyznaje przywileje jedynie procesowi wykonywanemu wewnątrz takiego kontenera, ale nie procesom
wykonywanym na zewnątrz kontenera.
Linux 4.14 dodał tak zwane przywileje pliku w przestrzeni nazw, w celu obsługi takich przypadków. Są one
zapisywane jako atrybuty rozszerzone security.capability wersji 3. (tzn. VFS_CAP_REVISION_3). Takie
atrybuty są tworzone automatycznie w okolicznościach opisanych w rozdziale Wersjonowanie atrybutu
rozszerzonego przywilejów pliku powyżej. Przy tworzeniu atrybutu rozszerzonego security.capability w
wersji 3., w atrybucie rozszerzonym jądro zapisze nie tylko maskę przywileju, lecz także identyfikator
użytkownika root w przestrzeni nazw.
Podobnie jak z plikiem binarnym z przywilejami pliku VFS_CAP_REVISION_2, plik binarny z przywilejami
pliku VFS_CAP_REVISION_3 przyznaje przywileje procesowi podczas execve(). Jednakże przywileje są
przyznawane tylko gdy plik binarny jest wykonywany przez proces rezydujący w przestrzeni nazw
użytkownika, którego identyfikator użytkownika 0 jest przypisany do identyfikatora użytkownika root
zachowywanego w atrybucie rozszerzonym lub gdy jest wykonywany przez proces rezydujący w potomkach takiej
przestrzeni nazw.
Interakcja z przestrzeniami nazw użytkowników
Więcej informacji o interakcji przywilejów i przestrzeni nazw użytkownika znajduje się w podręczniku
user_namespaces(7).
STANDARDY
Nie istnieją standardy opisujące przywileje, lecz linuksowa implementacja przywilejów powstała w oparciu
o wycofany szkic standardu POSIX.1e.
UWAGI
Przy próbie wykonania strace(1) na plikach binarnych posiadających przywileje (lub plikach binarnych z
ustawieniem ID roota podczas wykonania (suid)) przydatna może okazać się opcja -u <nazwa-użytkownika>.
Przykład:
$ sudo strace -o trace.log -u użytkownik ./mójprywatnyprogram
W jądrze Linux w wersjach od 2.5.27 do 2.6.26, przywileje były opcjonalną częścią jądra i mogły był
włączane i wyłączane opcją konfiguracji jądra CONFIG_SECURITY_CAPABILITIES.
Aby zobaczyć zbiory przywilejów wątku można użyć pliku /proc/pid/task/TID/status. Plik /proc/pid/status
pokazuje zbiory przywilejów głównego wątku procesu. Przed Linuksem 3.8 w tych zbiorach pokazywane były
jako włączone (1) przywileje nieistniejące. Od Linuksa 3.8, wszystkie nieistniejące przywileje (powyżej
CAP_LAST_CAP) są pokazywane jako wyłączone (0).
Pakiet libcap udostępnia zestaw procedur do ustawiania i pobierania przywilejów, który jest bardziej
komfortowy i mniej narażony na zmiany niż interfejs udostępniamy przez capset(2) i capget(2). Pakiet ten
zawiera również programy setcap(8) i getcap(8). Można go znaleźć na stronie
https://git.kernel.org/pub/scm/libs/libcap/libcap.git/refs/.
Przed Linuksem 2.6.24, oraz w Linuksie 2.6.24 do 2.6.32 - jeśli nie włączono przywilejów, wątek z
przywilejem CAP_SETPCAP może zmieniać przywileje innego wątku. Jest to jednak wyłącznie możliwość
teoretyczna, ponieważ wątek nigdy nie posiada CAP_SETPCAP w żadnym z dwóch poniższych przypadków:
• W implementacji przed wersją 2.6.25 zbiór przywilejów ograniczających na poziomie systemu,
/proc/sys/kernel/cap-bound, zawsze maskował przywilej CAP_SETPCAP usuwając go i nie da się zmienić
tego zachowania bez modyfikacji źródeł jądra i przebudowania jądra.
• Jeśli przywileje pliku są wyłączone (tzn. opcja jądra CONFIG_SECURITY_FILE_CAPABILITIES jest
wyłączona), to init uruchomi się z przywilejem CAP_SETPCAP usuniętym ze swojego zbioru ograniczającego
przypisanego do procesu, a ten zbiór ograniczający jest następnie dziedziczony przez wszystkie procesy
utworzone w systemie.
ZOBACZ TAKŻE
capsh(1), setpriv(1), prctl(2), setfsuid(2), cap_clear(3), cap_copy_ext(3), cap_from_text(3),
cap_get_file(3), cap_get_proc(3), cap_init(3), capgetp(3), capsetp(3), libcap(3), proc(5),
credentials(7), pthreads(7), user_namespaces(7), captest(8), filecap(8), getcap(8), getpcaps(8),
netcap(8), pscap(8), setcap(8)
include/linux/capability.h w drzewie źródeł jądra Linux
TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: 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.
Linux man-pages 6.9.1 13 czerwca 2024 r. Capabilities(7)