Für den Zweck der Durchführung von
Rechteprüfungen unterscheiden traditionelle UNIX-Implementierungen
zwei Arten von Prozessen: Privilegierte Prozesse (deren effektive
Benutzerkennung 0 ist, auch als Superuser oder Root benannt) und
unprivilegierte Prozesse (deren effektive UID von Null verschieden
ist). Privilegierte Prozesse übergehen alle
Kernel-Rechteprüfungen, während unprivilegierte Prozesse der
vollen Rechteprüfung, basierend auf den Berechtigungsnachweisen des
Prozesses (normalerweise: effektive UID, effektive GID und ergänzende
Gruppenliste), unterliegen.
Beginnend mit Kernel 2.2 unterteilt Linux die Privilegien, die
traditionell mit dem Superuser assoziiert sind, in getrennte Einheiten, die
als Capabilitys bekannt sind. Diese können unabhängig
voneinander aktiviert oder deaktiviert werden. Capabilitys sind ein Attribut
pro Thread.
Die folgende Liste zeigt die in Linux implementierten Capabilitys
und die Aktionen oder Verhalten, die jede Capability erlaubt:
- CAP_AUDIT_CONTROL
(seit Linux 2.6.11)
- Kernel-Auditierung aktivieren und deaktivieren; die
Auditierung-Filterregel ändern; den Auditstatus und Filterregel
abfragen.
- CAP_AUDIT_READ
(seit Linux 3.16)
- Erlaubt das Schreiben des Audit-Protokolls über einen
Multicast-Netlink-Socket.
- CAP_AUDIT_WRITE
(seit Linux 2.6.11)
- Datensätze in das Audit-Protokoll des Kernels schreiben.
- CAP_BLOCK_SUSPEND
(seit Linux 3.5)
- Funktionalitäten einsetzen, die die System-Supsendierung blockieren
können (epoll(7) EPOLLWAKEUP,
/proc/sys/wake_lock).
- CAP_BPF (seit
Linux 5.8)
- privilegierte BPF-Aktionen einsetzen; siehe bpf(2) und
bpf-helpers(7).
- Diese Capability wurde in Linux 5.8 hinzugefügt, um die
BPF-Funktionalität aus der überladenen Capability
CAP_SYS_ADMIN auszugliedern.
- CAP_CHECKPOINT_RESTORE
(seit Linux 5.9)
- Aktualisiert /proc/sys/kernel/ns_last_pid (siehe
pid_namespaces(7));
- verwendet die Funktionalität set_tid von
clone3(2);
- liest die Inhalte der symbolischen Links in /proc/[PID]/map_files
für andere Prozesse.
- Diese Capability wurde in Linux 5.9 hinzugefügt, um die
Prüfpunkt-/Wiederherstellungs-Funktionalität aus der
überladenen Capability CAP_SYS_ADMIN auszugliedern.
- CAP_CHOWN
- beliebige Änderungen an Datei-UIDs und GIDs vornehmen (siehe
chown(2)).
- CAP_DAC_OVERRIDE
- Lese-, Schreibe und Ausführrechteprüfungen umgehen. (DAC ist
die Abkürzung für »discretionary access
control«, benutzerbestimmbare Zugriffssteuerung)
- CAP_DAC_READ_SEARCH
- Dateileserechteprüfungen und Verzeichnislese- und
-ausführrechteprüfungen umgehen.
- open_by_handle_at(2) aufrufen.
- Verwenden Sie den Schalter AT_EMPTY_PATH von linkat(2), um
einen Link auf eine Datei, auf die sich ein Dateideskriptor bezieht, zu
erstellen.
- CAP_FOWNER
- Rechteprüfungen umgehen, die normalerweise verlangen, dass die
Dateisystem-UID des Prozesses mit der UID der Datei übvereinstimmt
(z.B. chmod(2), utime(2)), hierbei sind Aktionen, die durch
CAP_DAC_OVERRIDE und CAP_DAC_READ_SEARCH abgedeckt sind,
ausgeschlossen;
- Inode-Schalter für beliebige Dateien setzen (siehe
ioctl_iflags(2));
- Zugriffssteuerlisten (»Access Control Lists«, ACLs) auf
beliebige Dateien setzen;
- »sticky«-Bit von Verzeichnissen beim Dateilöschen
ignorieren;
- verändert Benutzer-erweiterte Attribute bei
»sticky«-Verzeichnissen, die irgendeinem Benutzer
gehören;
- O_NOATIME für beliebige Dateien in open(2) und
fcntl(2) setzen.
- CAP_FSETID
- Set-User-ID- und Set-Group-ID-Modus-Bits nicht zurücksetzen, wenn
eine Datei verändert wird;
- das Set-Group-ID-Bit für eine Datei setzen, deren GID nicht auf das
Dateisystem- oder eine der ergänzenden GIDs des aufrufenden
Prozesses passt.
- CAP_IPC_LOCK
- Speicher sperren (mlock(2), mlockall(2), mmap(2),
shmctl(2)).
- CAP_IPC_OWNER
- Rechteprüfungen für Aktionen mit System-V-IPC-Objekten
umgehen.
- CAP_KILL
- Rechteprüfungen beim Senden von Signalen umgehen (siehe
kill(2)). Dies schließt die
ioctl(2)-KDSIGACCEPT-Aktion mit ein.
- CAP_LEASE
(seit Linux 2.4)
- Etabliert Ausleihen für beliebige Dateien (siehe
fcntl(2)).
- CAP_LINUX_IMMUTABLE
- Setzt die Inode-Schalter FS_APPEND_FL und FS_IMMUTABLE_FL
(siehe ioctl_iflags(2)).
- CAP_MAC_ADMIN
(seit Linux 2.6.25)
- MAC-Konfiguration oder Statusänderungen erlauben. Implementiert
für das Smack-Linux-Security-Modul (LSM).
- CAP_MAC_OVERRIDE
(seit Linux 2.6.25)
- Mandatory Access Control (MAC) außer Kraft setzen. Für das
Smack-LSM implementiert.
- CAP_MKNOD
(seit Linux 2.4)
- Spezielle Dateien mittels mknod(2) erstellen.
- CAP_NET_ADMIN
- Verschiedene Netz-bezogene Aktionen durchführen:
- Schnittstellenkonfiguration;
- Administration von IP-Firewall, Masquerading und Abrechnung;
- Routing-Tabellen verändern;
- an beliebige Adresse für eine transparente Proxyfunktion
binden;
- type-of-service (TOS) setzen;
- Treiberstatistiken bereinigen;
- den »promiscuous«-Modus einschalten;
- Multicasting aktivieren;
- setsockopt(2) verwenden, um die folgenden Socket-Optionen zu
setzen: SO_DEBUG, SO_MARK, SO_PRIORITY (für
eine Priorität außerhalb des Bereichs 0 bis 6),
SO_RCVBUFFORCE und SO_SNDBUFFORCE.
- CAP_NET_BIND_SERVICE
- Einen Socket an einen privilegierten Internet-Domain-Port binden
(Portnummern kleiner als 1024).
- CAP_NET_BROADCAST
- (Unbenutzt) Socket-Broadcasts durchführen und auf Multicasts
warten.
- CAP_NET_RAW
- RAW- und PACKET-Sockets verwenden;
- an beliebige Adresse für eine transparente Proxyfunktion
binden.
- CAP_PERFMON
(seit Linux 5.8)
- verschiedene Leistungsüberwachungsmechanismen einzusetzen,
einschließlich:
- perf_event_open(2) aufrufen;
- verschiedene BPF-Aktionen einzusetzen, die Leistungsauswirkungen
haben.
- Diese Capability wurde in Linux 5.8 hinzugefügt, um die
Überwachungsfunktionalität aus der überladenen
Capability CAP_SYS_ADMIN auszugliedern. Siehe auch die
Kernelquelldatei Documentation/admin-guide/perf-security.rst.
- CAP_SETGID
- Beliebige Manipulationen an den GIDs und der Liste der ergänzenden
GIDs des Prozesses vornehmen;
- GID fälschen, wenn Socket-Berechtigungsnachweise via
UNIX-Domain-Sockets weitergebeben werden;
- eine Gruppenkennungs-Abbildung in einen Benutzernamensraum schreiben
(siehe user_namespaces(7)).
- CAP_SETFCAP
(seit Linux 2.6.24)
- Setzt beliebige Capabilitys auf einer Datei.
- CAP_SETPCAP
- Falls Datei-Capabilitys unterstützt werden (d.h. seit Linux
2.6.24): Füge alle Capabilitys aus der Begrenzungsmenge des Threads
zu der vererbbaren Menge hinzu; entferne Capabilitys aus der
Begrenzungsmenge (via prctl(2) PR_CAPBSET_DROP); nehme
Änderungen an den securebits-Schaltern vor.
- Falls Datei-Capabilites nicht unterstützt werden (d.h. Kernel vor
Linux 2.6.24): eine Capability in der erlaubten Capability-Menge oder von
anderen Prozessen entfernen oder dafür bewilligen. (Diese
Eigenschaft von CAP_SETPCAP ist nicht verfügbar, falls der
Kernel für die Unterstützung von Datei-Capabilitys
konfiguriert ist, da CAP_SETPCAP für diese Kernel eine
komplett andere Semantik aufweist.)
- CAP_SETUID
- CAP_SYS_ADMIN
- Hinweis: Diese Capability ist überladen, siehe Hinweise
für Kernel-Entwickler weiter unten.
- eine Reihe von Systemadministratoraktionen ausführen, darunter:
quotactl(2), mount(2), umount(2),
pivot_root(2), swapon(2), swapoff(2),
sethostname(2) und setdomainname(2);
- privilegierte syslog(2)-Aktion ausführen (seit Linux 2.6.37
sollte CAP_SYSLOG verwandt werden, um diese Aktion zu
erlauben);
- den VM86_REQUEST_IRQ-Befehl vm86(2) ausführen;
- auf die gleiche Prüfpunkt-/Wiederherstellungsfunktionalität
zugreifen, die durch CAP_CHECKPOINT_RESTORE gelenkt wird (die
letztere, aber schwächere Capability wird für den Zugriff
auf dieses Funktionalität bevorzugt).
- die gleichen BPF-Aktionen durchführen, die durch CAP_BPF
gelenkt werden (die letztere, aber schwächere Capability wird
für den Zugriff auf dieses Funktionalität bevorzugt).
- die gleichen Leistungsüberwachungsmechanismen einsetzen, die durch
CAP_PERFMON gelenkt werden (die letztere, aber schwächere
Capability wird für den Zugriff auf dieses Funktionalität
bevorzugt).
- IPC_SET- und IPC_RMID-Aktion auf beliebigen
System-V-IPC-Objekten ausführen;
- RLIMIT_NPROC-Ressourcenbegrenzung außer Kraft setzen;
- Aktionen an den erweiterten Attributen trusted und security
durchführen (siehe xattr(7));
- lookup_dcookie(2) verwenden;
- ioprio_set(2) verwenden, um IOPRIO_CLASS_RT und (vor Linux
2.6.25) IOPRIO_CLASS_IDLE-E/A-Scheduling-Klassen zuzuweisen;
- PID fälschen, wenn Socket-Berechtigungsnachweise via
UNIX-Domain-Sockets weitergebeben werden;
- die systemweite Grenze der Anzahl der offenen Dateien
(/proc/sys/fs/file-max) in Systemaufrufen, die Dateien
öffnen (z.B. accept(2), execve(2), open(2),
pipe(2)) überschreiben;
- Schalter CLONE_* einsetzen, der neue Namensräume mit
clone(2) und unshare(2) erstellt (seit Linux 3.8
benötigt die Erzeugung von Benutzernamensräumen allerdings
keine Capability mehr);
- auf privilegierte perf-Ereignisinformationen zugreifen;
- setns(2) aufrufen (benötigt CAP_SYS_ADMIN im
Namensraum target);
- fanotify_init(2) aufrufen;
- privilegierte Aktionen KEYCTL_CHOWN und KEYCTL_SETPERM von
keyctl(2) ausführen;
- madvise(2)-MADV_HWPOISON-Aktion ausführen;
- den TIOCSTI ioctl(2) verwenden, um Zeichen in die
Eingabewarteschlange eines Terminals, dass nicht das vom aufrufenden
gesteuerte Terminal ist, einzufügen;
- veralteten Systemaufruf nfsservctl(2) verwenden;
- veralteten Systemaufruf bdflush(2) verwenden;
- verschiedene privilegierte Blockgeräte-ioctl(2)-Aktion
ausführen;
- verschiedene privilegierte Dateisystem-ioctl(2)-Aktionen
ausführen;
- privilegierte ioctl(2)-Aktionen am Gerät /dev/random
durchführen (siehe random(4));
- einen seccomp(2)-Filter installieren, ohne zuerst das
no_new_privs Thread-Attribut setzen zu müssen;
- Erlauben-/Verweigern-Regeln für Gerätesteuergruppen
verändern;
- ptrace(2) PTRACE_SECCOMP_GET_FILTER Aktionen einsetzen, um
die Seccomp-Filter verfolgter Prozesse auszugeben;
- die Aktion PTRACE_SETOPTIONS von ptrace(2) einsetzen, um den
Seccomp-Schutz des verfolgten Prozesses vorübergehend außer
Kraft zu setzen (d.h. der Schalter PTRACE_O_SUSPEND_SECCOMP);
- administrative Aktionen auf vielen Gerätetreibern
ausführen;
- Autogroup-Nice-Werte durch Schreiben von /proc/[PID]/autogroup
(siehe sched(7)) verändern.
- CAP_SYS_BOOT
- reboot(2) und kexec_load(2) verwenden.
- CAP_SYS_CHROOT
- CAP_SYS_MODULE
- Kernelmodule laden und entladen (siehe init_module(2) und
delete_module(2));
- in Kerneln vor 2.6.25: Capabilitys aus der systemweiten
Capability-Begrenzungsmenge entfernen.
- CAP_SYS_NICE
- CAP_SYS_PACCT
- acct(2) verwenden.
- CAP_SYS_PTRACE
- CAP_SYS_RAWIO
- E/A-Port-Aktionen ausführen (iopl(2) und
ioperm(2));
- auf /proc/kcore zugreifen;
- die FIBMAP-Aktion ioctl(2) einsetzen;
- Geräte für den Zugriff auf x86-modellspezifische Register
(MSRs, siehe msr(4)) öffnen;
- /proc/sys/vm/mmap_min_addr aktualisieren;
- Speichereinblendungen an Adressen unterhalb des durch
/proc/sys/vm/mmap_min_addr angegebenen Wertes erstellen;
- Dateien in /proc/bus/pci einblenden;
- /dev/mem und /dev/kmem öffnen;
- verschiedene SCSI-Geräte-Befehle ausführen;
- bestimmte Aktionen auf hpsa(4)- und cciss(4)-Geräten
ausführen;
- eine Reihe von Geräte-spezifischen Aktionen auf anderen
Geräten ausführen.
- CAP_SYS_RESOURCE
- reservierten Platz auf Ext2-Dateisystemen verwenden;
- ioctl(2)-Aufrufe ausführen, die das Journaling von Ext3
steuern;
- Platten-Kontingent-Begrenzungen außer Kraft setzen;
- Ressourcenbegrenzungen erhöhen (siehe setrlimit(2));
- RLIMIT_NPROC-Ressourcenbegrenzung außer Kraft setzen;
- maximale Anzahl von Konsolen bei der Konsolenzuteilung außer Kraft
setzen;
- maximale Anzahl an Tastaturdefinitionen außer Kraft setzen;
- mehr als 64 Hz-Unterbrechungen von der Echtzeituhr erlauben;
- die msg_qbytes-Begrenzung für eine
System-V-Nachrichtenwarteschlange über die Grenze in
/proc/sys/kernel/msgmnb anheben (siehe msgop(2) und
msgctl(2));
- erlauben, die Ressourcenbegrenzung RLIMIT_NOFILE bezüglich
der Anzahl der »laufenden« Dateideskriptoren zu umgehen,
wenn Dateideskriptoren an andere Prozesse mittels UNIX-Domain-Sockets
übergeben werden (siehe unix(7));
- die /proc/sys/fs/pipe-size-max-Begrenzung beim Setzen der
Kapazität einer Pipe mittels des F_SETPIPE_SZ-Befehls
fcntl(2) außer Kraft setzen;
- F_SETPIPE_SZ verwenden, um die Kapazität einer Pipe
über die in /proc/sys/fs/pipe-max-size angegebene Grenze
erhöhen;
- die /proc/sys/fs/mqueue/queues_max,
/proc/sys/fs/mqueue/msg_max, und
/proc/sys/fs/mqueue/msgsize_max-Begrenzungen beim Erstellen von
POSIX-Nachrichtenwarteschlangen (siehe mq_overview(7)) außer
Kraft setzen;
- die prctl(2)-Aktion PR_SET_MM einsetzen;
- /proc/[PID]/oom_score_adj auf einen Wert niedriger als den zuletzt
durch einen Prozess mit CAP_SYS_RESOURCE gesetzten Wert
setzen.
- CAP_SYS_TIME
- Systemuhr setzen (settimeofday(2), stime(2),
adjtimex(2)); Echtzeit- (Hardware-)Uhr setzen.
- CAP_SYS_TTY_CONFIG
- vhangup(2) einsetzen; verschiedene privilegierte
ioctl(2)-Aktionen auf virtuelle Terminals einsetzen.
- CAP_SYSLOG
(seit Linux 2.6.37)
- Privilegierte syslog(2)-Aktionen ausführen. Siehe
syslog(2) für Informationen, welche Aktionen Privilegien
benötigen.
- Über /proc bereitgestellte Kernel-Adressen und andere
Schnittstellen anschauen, wenn /proc/sys/kernel/kptr_restrict den
Wert 1 hat. (Lesen Sie die Diskussion über kptr_restrict in
proc(5).)
- CAP_WAKE_ALARM
(seit Linux 3.0)
- Etwas auslösen, dass das System aufwecken wird (siehe die Timer
CLOCK_REALTIME_ALARM und CLOCK_BOOTTIME_ALARM).
Eine komplette Implementierung von Capabilitys verlangt
folgendes:
- 1.
- Für alle privilegierten Aktionen muss der Kernel prüfen, ob
der Thread die benötigten Capabilitys in seiner effektiven Menge
hat.
- 2.
- Der Kernel muss Systemaufrufe bereitstellen, die es erlauben, dass die
Capability-Menge des Threads geändert und ermittelt wird.
- 3.
- Das Dateisystem muss das Anhängen von Capabilitys an
ausführbare Dateien erlauben, so dass ein Prozess solche
Capabilitys erhält, wenn die Datei ausgeführt wird.
Vor Kernel 2.6.24 waren nur die ersten zwei dieser Anforderungen
erfüllt, seit Kernel 2.6.24 sind alle drei Anforderungen
erfüllt.
Wenn Sie eine neue Kernel-Funktionalität hinzufügen,
die über eine Capability geregelt werden soll, beachten Sie die
nachfolgenden Punkte.
- Das Ziel von Capabilitys besteht darin, die Macht des Systembenutzers in
Teile zu zerlegen. Wird dann ein Programm, das eine oder mehrere
Capabilitys hat, kompromittiert, dann kann weniger Schaden angerichtet
werden, als wenn das Programm mit Root-Rechten liefe.
- Sie haben die Wahl, entweder ein neues Capability für Ihre neue
Funktionalität hinzuzufügen, oder die Funktionalität
einer bereits bestehenden Capability zuzuordnen. Um die Menge der
Capabilitys auf eine verwaltbare Größe zu begrenzen, wird
die zweite Variante bevorzugt, außer es gibt überzeugende
Gründe, die erste Variante zu wählen. (Es gibt auch eine
technische Grenze: Die Größe der Capability-Menge ist
derzeit auf 64 bit beschränkt.)
- Um zu bestimmen, zu welcher bestehenden Capability Ihre neue
Funktionalität am besten zugeordnet werden könnte,
prüfen Sie die obige Liste der Capabilitys, um ein
»Silo« zu finden, in das Ihre neue Funktionalität am
besten passt. Ein Vorgehen besteht darin, zu bestimmen, ob es andere
Funktionalitäten gibt, die Capabilitys benötigen, die immer
zusammen mit Ihrer neuen Funktionalität benötigt werden.
Falls Ihre neue Funktionalität ohne diese andere
Funktionalität nutzlos ist, dann sollten Sie die gleiche Capability
wie die andere Funktionalität verwenden.
- Verwenden Sie nicht CAP_SYS_ADMIN, falls Sie es irgendwie
vermeiden können. Ein riesiger Anteil an bestehenden
Capability-Überprüfungen ist dieser Capability zugeordnet
(siehe die Teilliste weiter oben). Sie kann glaubhaft als »der neue
Root« bezeichnet werden, da sie eine große Bandbreite an
Rechten verleiht, und andererseits bedeutet ihr großer
Geltungsbereich, dass es eine Capability ist, die von vielen
privilegierten Programmen benötigt wird. Verschlimmern Sie das
Problem nicht. Die einzigen neuen Funktionalitäten, die
CAP_SYS_ADMIN zugeordnet werden sollten, sind diejenigen, die
eng zu bestehenden Anwendungsfällen in diesem Silo
passen.
- Falls Sie ermittelt haben, dass Sie wirklich eine neue Capability
für Ihre Funktionalität benötigen, führen Sie
sie nicht als »Einzelverwendung«-Capability ein (oder
benennen Sie es so). Daher war beispielsweise die Ergänzung der
hochspezifischen CAP_SYS_PACCT wahrscheinlich ein Fehler. Versuchen
Sie stattdessen, Ihre neue Capability als ein breiteres Silo zu
identifizieren und zu benennen, in das andere, damit im Zusammenhang
stehende zukünftige Anwendungsfälle passen
könnten.
Capability-Mengen von Threads
Jeder Thread hat die folgenden Capability-Mengen, die null oder
mehr der oben aufgeführten Capabilitys enthalten:
- Permitted
(erlaubt)
- Dies ist die begrenzende Übermenge für die effektiven
Capabilitys, die ein Thread annehmen kann. Es ist auch die begrenzende
Übermenge für die Capabilites, die zu der vererbbaren Menge
durch einen Thread hinzugefügt werden dürfen, der nicht die
Capability CAP_SETPCAP in seiner effektiven Menge hat.
- Falls ein Thread eine Capability aus seiner erlaubten Menge entfernt, kann
es diese Capability niemals wiedererlangen (außer es führt
ein Set-User-ID-Root-Programm mit execve(2) aus oder ein Programm,
dessen zugeordnete Datei-Capabilitys diese Capability wieder
bewilligen).
- Inheritable
(vererbbar)
- Dies ist eine Menge von Capabilitys, die über execve(2)
hinweg erhalten bleiben. Vererbbare Capabilitys bleiben bei der
Ausführung jedes Programms vererbbar und vererbbare Capbabilities
werden zu der erlaubten Menge bei der Ausführung eines Programms,
das die entsprechenden Bits in der Datei-Vererbbaren-Menge gesetzt hat,
hinzugefügt.
- Da vererbbare Capabilitys im allgemeinen nicht über
execve(2)-Aufrufe erhalten werden, wenn dies nicht als Benutzer
root erfolgt, sollten Anwendungen, die Hilfsprogramme mit erhöhten
Capabilitys ausführen wollen, die Verwendung der unten
beschriebenen Umgebungs-Capabilitys in Betracht ziehen.
- Effective
(effektiv)
- Dies ist die Menge an Capabilitys, der vom Kernel zur Durchführung
von Rechteprüfungen für den Thread verwandt wird.
- Bounding
(pro-Thread seit Linux 2.6.25)
- Die Capability-Begrenzungsmenge ist ein Mechanismus, der zur Begrenzung
der Capabilitys, die während eines execve(2) erlangt werden,
dienen kann.
- Seit Linux 2.6.25 ist dies eine pro-Thread-Capability-Menge. In
älteren Kerneln war die Capability-Begrenzungsmenge ein
systemweites Attribut, das von allen Threads des Systems gemeinsam benutzt
wurde.
- Für weitere Details über die Capability-Begrenzungsmenge,
siehe unten.
- Ambient
(Umgebung) (seit Linux 4.3)
- Dies ist eine Menge von Capabilitys, die über execve(2)
eines nicht privilegierten Programms hinweg erhalten bleiben. Die
Umgebungs-Capability-Menge folgt der Invarianz, dass keine Capability
jemals eine Umgebungs-Capability sein kann, falls sie nicht sowohl erlaubt
als auch vererbbar ist.
- Die Umgebungs-Capability-Menge kann direkt mit prctl(2)
verändert werden. Umgebungs-Capabilitys werden automatisch
abgesenkt, falls entweder die entsprechende erlaubte oder vererbbare
Capability abgesenkt wird.
- Wird ein Programm ausgeführt, das die UID oder GID aufgrund von
set-user-ID- oder set-group-ID-Bits ändert oder das über
eine Menge an Datei-Capabilitys verfügt, dann wird die
Umgebungsmenge geleert. Umgebungs-Capabilitys werden zu der erlaubten
Menge hinzugefügt und der effektiven Menge zugewiesen, wenn
execve(2) aufgerufen wird. Falls Umgebungs-Capabilitys dazu
führen, dass die erlaubten und effektiven Capabilitys
während eines execve(2) anwachsen, löst dies keinen
sicheren Ausführmodus, wie in ld.so(8) beschrieben,
aus.
Ein mittels fork(2) erstelltes Kind erbt Kopien der
Eltern-Capability-Menge. Lesen Sie weiter unten eine Diskussion der
Behandlung von Capabilitys während execve(2).
Mittels capset(2) kann ein Thread seine eigenen
Capability-Mengen bearbeiten (siehe unten).
Seit Linux 3.2 legt die Datei /proc/sys/kernel/cap_last_cap
den numerischen Wert der höchsten vom laufenden Kernel
unterstützten Capability offen. Dies kann zur Bestimmung des
höchsten Bits, das in einer Capability-Gruppe gesetzt werden kann,
genutzt werden.
Seit Kernel 2.6.24 unterstützt der Kernel die Zuordnung von
Capability-Mengen zu einer ausführbaren Datei mittels
setcap(8). Die Datei-Capability-Mengen werden in erweiterten
Attributen namens security.capability gespeichert (siehe
setxattr(2) und xattr(7)). Das Schreiben in diese erweiterten
Attribute benötigt die Capability CAP_SETFCAP. Die
Datei-Capability-Mengen bestimmen zusammen mit den Capability-Mengen des
Threads die Capabilitys nach einem execve(2).
Die drei Datei-Capability-Mengen sind:
- Permitted
(erlaubt, früher als forced (erzwungen) bekannt):
- Diese Capabilitys werden dem Thread automatisch erlaubt, unabhängig
von den geerbten Capabilitys des Threads.
- Inheritable
(vererbbar, früher als allowed (erlaubt) bekannt):
- Diese Menge wird mittels AND mit der vererbbaren Menge des Threads
verknüpft, um zu bestimmen, welche vererbbaren Capabilitys in der
erlaubten Menge des Threads nach einem execve(2) aktiviert
werden.
- Effective
(effektiv):
- Dies ist keine Menge, sondern eher ein einziges Bit. Falls dieses Bit
gesetzt ist, dann werden während eines execve(2) die
gesamten erlaubten Capabilties für den Thread in die effektive
Menge hochgezogen. Falls dieses Bit nicht gesetzt ist, dann wird nach
einem execve(2) keine der erlaubten Capabilitys in der neuen
effektiven Menge sein.
- Aktivieren des effektiven Datei-Capability-Bits impliziert, dass jede
erlaubte oder vererbte Datei-Capability, die dazu führt, dass ein
Thread die entsprechende erlaubte Capability während eines
execve(2) erlangt (siehe die oben beschriebenen
Transformationsregeln), auch dazu führt, dass er die Capability in
seiner effektiven Menge erlangt. Werden daher Capabilitys zu einer Datei
zugeweisen ((setcap(8), cap_set_file(3),
cap_set_fd(3)), falls der effektive Schalter für irgendeine
Capability aktiviert ist, dann muss der effektive Schalter auch als
aktiviert für alle anderen Capabilitys, für die die
entsprechenden erlaubten oder vererbbaren Schalter aktiviert sind,
spezifiziert werden.
Um Erweiterbarkeit zu erlauben, unterstützt der Kernel ein
Schema, um eine Versionsnummer innerhalb des erweiterten Attributs
security.capability zu kodieren, die zur Implementierung von
Datei-Capabilitys verwandt wird. Diese Versionsnummern sind
implementierungsintern und für Benutzerraum-Anwendungen nicht direkt
sichtbar. Derzeit werden die folgenden Versionen unterstützt:
- VFS_CAP_REVISION_1
- Dies war die ursprüngliche Datei-Capability-Implementierung, die
32-Bit-Masken für Datei-Capabilitys unterstützte.
- VFS_CAP_REVISION_2
(seit Linux 2.6.25)
- Diese Version erlaubt Datei-Capability-Masken in der Größe
von 64 Bit und wurde notwendig, da die Anzahl an unterstützen
Capabilitys 32 überstieg. Der Kernel unterstützt weiterhin
transparent die Ausführung von Dateien mit
32-Bit-Version-1-Capability-Masken, aber wenn Capabilitys zu Dateien
hinzugefügt werden, die bisher keine Capabilitys hatten, oder
Capabilitys von bestehenden Dateien geändert werden, wird
automatisch das Version-2-Schema (oder möglicherweise das unten
beschriebene Version-3-Schema) verwandt.
- VFS_CAP_REVISION_3
(seit Linux 4.14)
- Version-3-Datei-Capabilitys werden zur Unterstützung von
(nachfolgend beschriebenen) namensraumbezogenen Datei-Capabilitys
bereitgestellt.
- Wie bei Version-2-Datei-Capabilitys sind die Version-3-Capability Masken
64 Bit groß. Aber zusätzlich wird die Wurzelbenutzerkennung
des Namensraums in dem erweiterten Attribut security.capability
kodiert. (Eine Namensraum-Wurzelbenutzerkennung ist der Wert, auf den die
Benutzerkennung 0 innerhalb dieses Namensraums in dem
ursprünglichen Namensraum abgebildet wird.)
- Version-3-Datei-Capabilitys sind so entwickelt worden, dass sie mit
Version-2-Capabilitys koexistieren können, d.h. auf einem modernen
Linux-System können einige Dateien Version-2-Capabilitys tragen,
während andere Version-3-Capabilitys haben.
Vor Linux 4.14 war die einzige Art des erweiterten Attributs
für Datei-Capabilitys, die an eine Datei angehängt werden
konnten, ein VFS_CAP_REVISION_2-Attribut. Seit Linux 4.14
hängt die Version des erweiterten Attributs
security.capability, die an eine Datei angehängt werden kann,
von den Umständen ab, unter denen das Attribut erstellt wurde.
Seit Linux 4.14 wird ein erweitertes Attribut
security.capability automatisch als ein
Version-3-(VFS_CAP_REVISION_3)-Attribut erstellt (oder in ein solches
umgewandelt), falls beide folgenden Punkte zutreffen:
- (1)
- Der Thread, der das Attribut schreibt, befindet sich in einem
nichtinitialen Benutzernamensraum. (Genauer: Der Thread befindet sich in
einem Benutzernamensraum, der sich von dem unterscheidet, unter dem das
darunterliegende Dateisystem eingehängt wurde.)
- (2)
- Der Thread hat die Capability CAP_SETFCAP über der
Datei-Inode, was bedeutet, dass (a) der Thread die Capability
CAP_SETFCAP in seinem eigenen Benutzernamensraum hat und (b) die
UID und GID der Datei-Inode Abbildungen in den Namensraum des schreibenden
Benutzers haben.
Wenn ein erweitertes Attribut VFS_CAP_REVISION_3
security.capability erstellt wird, wird die Wurzelbenutzerkennung des
erstellenden Namensraums des Benutzers in dem erweiterten Attribut
gespeichert.
Im Gegensatz dazu wird beim Erstellen oder Verändern eines
erweiterten Attributs security.capability aus einem privilegierten
(CAP_SETFCAP) Thread, der sich in dem Namensraum befindet, unter dem
das darunterliegende Dateisystem eingehängt wurde (dies bedeutet
normalerweise den anfänglichen Benutzernamensraum), automatisch zu
der Erstellung eines Version-2-(VFS_CAP_REVISION_2)-Attributs
führen.
Beachten Sie, dass die Erstellung von erweiterten Version
3-security.capability-Attributen automatisch erfolgt. Mit anderen
Worten: Der Kernel wird automatisch ein Version-3-Attribut erstellen, falls
das Attribut unter den oben beschriebenen Umständen erstellt wird,
wenn eine Anwendung im Benutzerraum ein security.capability-Attribut
im Version-2-Format schreibt (setxattr(2)). Entsprechend wird das
zurückgelieferte Attribut (automatisch) vereinfacht, um als
Version-2-Attribut zu erscheinen (d.h. der Rückgabewert ist die
Größe eines Version-2-Attrbutes und enthält nicht die
Root-Benutzerkennung), wenn ein
Version-3-security.capability-Attribut durch einen Prozess, der sich
innerhalb eines Benutzernamensraums befindet, der durch die
Root-Benutzerkennung (oder einem Abkömling dieses Namensraums)
erstellt wurde, abgefragt wird. Diese automatische Übersetzung
bedeutet, dass an den Werkzeugen im Benutzerraum (z.B. setcap(1) und
getcap(1)) keine Änderung vorgenommen werden muss, damit diese
Werkzeuge zum Erstellen und Abfragen von
Version-3-security.capability-Attributen verwandt werden
können.
Beachten Sie, dass der Datei entweder ein erweitertes Attribut
security.capability der Version 2 oder 3 zugeordnet werden kann, aber
nicht beide: Erstellung oder Änderung des erweiterten Attributs
security.capability wird automatisch die Version abhängig von
den Umständen, in denen das erweiterte Attribut erstellt oder
verändert wird, anpassen.
Während eines execve(2) berechnet der Kernel die
neuen Capabilitys eines Prozesses mit dem folgenden Algorithmus:
P'(ambient) = (Datei ist privilegiert) ? 0 : P(ambient)
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & P(bounding)) | P'(ambient)
P'(effective) = F(effective) ? P'(permitted) : P'(ambient)
P'(inheritable) = P(inheritable) [d.h. unverändert]
P'(bounding) = P(bounding) [d.h. unverändert]
wobei:
- P()
- bezeichnet den Wert einer Capability-Menge des Threads vor dem
execve(2)
- P'()
- bezeichnet den Wert einer Capability-Menge des Threads nach dem
execve(2)
- F()
- bezeichnet eine Datei-Capability-Menge
Beachten Sie die nachfolgenden Details in Hinblick auf die obigen
Capability-Umwandlungsregeln:
- Die Umgebungs-Capability-Menge ist erst seit Linux 4.3 vorhanden. Bei der
Bestimmung der Übergänge der Umgebungsmenge während
eines execve(2) bezeichnet eine privilegierte Datei eine, die
über Capabilitys verfügt oder das Bit
»set-user-ID« oder »set-group-ID« gesetzt
hat.
- Vor Linux 2.6.25 war die Begrenzungsmenge ein systemweites Attribut, das
von allen Threads gemeinsam benutzt wurde. Dieser systemweite Wert wurde
eingesetzt, um die neue erlaubte Menge während eines
execve(2) zu berechnen, auf die gleiche Art wie oben für
P(bounding) gezeigt.
Hinweis: Während der oben beschriebenen
Capability-Übergänge könnten aus den gleichen
Gründen, aus denen auch die Bits set-user-ID and set-group-ID
ignoriert werden, Datei-Capabilitys ignoriert (als leer betrachtet) werden;
siehe execve(2). Ähnlich werden Datei-Capabilitys ignoriert,
falls der Kernel mit der Option no_file_caps gestartet wurde.
Hinweis: Entsprechend den obigen Regeln werden alle
Capabilitys, die in der erlaubten und effektiven Menge vorhanden sind,
zurückgesetzt, falls ein Prozess mit von Null verschiedenen
Benutzerkennungen ein execve(2) durchführt. Für die
Behandlung der Capabilitys, wenn ein Prozess mit der Benutzerkennung Null
ein execve(2) durchführt, siehe unten unter Capabilitys und
Ausführung von Programmen durch root.
Ein Capability-unfähiges Programm ist eine Anwendung, die
für Datei-Capabilitys markiert ist, aber noch nicht für die
Verwendung des libcap(3)-APIs zur Bearbeitung seiner Capabilitys
konvertiert wurde. (Mit anderen Worten, dies ist ein traditionelles
»set-user-ID-root«-Programm, das auf Datei-Capabilitys
umgestellt wurde, aber dessen Code nicht angepasst wurde, um mit Capabilitys
umzugehen.) Für solche Anwendungen wird das effektive Capability-Bit
auf die Datei gesetzt, so dass die erlaubten Capabilitys automatisch beim
Ausführen der Datei in der effektiven Menge aktiviert werden. Der
Kernel erkennt für den hier beschriebenen Zweck eine Datei, die das
effektive Capability-Bit gesetzt hat, als Capability-unfähig.
Beim Ausführen eines Capability-unfähigen Programms
prüft der Kernel nach den oben beschriebenen Umwandlungen, ob der
Prozess alle erlaubten Capabilitys, die in der Datei-erlaubten Menge
angegeben wurden, erlangt hat. (Ein typischer Grund, warum dies nicht
passieren könnte, liegt darin, dass die Capability-Begrenzungsmenge
einige der Capabilitys in der Datei-erlaubten Menge ausblenden
könnte.) Falls der Prozess nicht die komplette Menge der
Datei-erlaubten Capabilitys erlangte, schlägt execve(2) mit
dem Fehler EPERM fehl. Dies verhindert mögliche
Sicherheitsrisiken, die daraus resultieren, dass ein
Capability-unfähiges Programm mit weniger als den benötigten
Privilegien ausgeführt wird. Beachten Sie, dass
definitionsgemäß die Anwendung das Problem nicht selbst
erkennen könnte, da sie nicht das libcap(3)-API einsetzt.
Um die traditionellen UNIX-Semantiken abzubilden, führt der
Kernel eine besondere Behandlung der Datei-Capabilitys durch, wenn ein
Prozess mit UID 0 (root) ein Programm ausführt und wenn ein
set-user-ID-root-Programm ausgeführt wird.
Nachdem alle Änderungen an der effektiven Kennung des
Prozesses vorgenommen wurden, die durch das Modus-Bit set-user-ID des
Programmes ausgelöst wurden, z.B. Umschalten der effektiven
Benutzerkennung auf 0 (root), da ein set-user-ID-root-Programm
ausgeführt wurde, berechnet der Kernel die Datei-Capability-Menge wie
folgt:
- 1.
- Falls die reale oder effektive Benutzerkennung des Prozesses 0 (root) ist,
dann werden die vererbbaren und erlaubten Mengen ignoriert; stattdessen
werden sie fiktiv als komplett Eins (d.h. alle Capabilitys aktiviert)
betrachtet. (Es gibt für dieses Verhalten eine Ausnahme, die unten
in Set-user-ID-root-Programme, die Datei-Capabilitys haben
beschrieben ist.)
- 2.
- Falls die effektive Benutzerkennung des Prozesses 0 (root) ist oder das
effektive Bit der Datei tatsächlich aktiviert ist, dann wird das
effektive Datei-Bit fiktiv als Eins (aktiviert) definiert.
Diese fiktiven Werte für die Capability-Menge der Datei
werden dann verwandt, um wie oben beschrieben den Übergang der
Capabilitys des Prozesses während eines execve(2) zu
berechnen.
Daher vereinfacht sich die Berechnung der neuen erlaubten
Capabilitys eines Prozesses wie folgt, wenn ein Prozess mit einer von 0
verschiedenen UID ein set-user-ID-root-Programm, das über keine
Capabilitys verfügt, mit execve(2) ausführt, oder wenn
ein Prozess, dessen reale und effektive UIDs Null sind, ein Programm mit
execve(2) ausführt:
P'(permitted) = P(inheritable) | P(bounding)
P'(effective) = P'(permitted)
Konsequenterweise erlangt der Prozess alle Capabilitys in seiner
erlaubten und effektiven Capability-Menge, außer denen, die in seiner
Capability-Begrenzungsmenge ausmaskiert sind. (In der Berechnung von
P'(permitted) kann der Ausdruck für P'(ambient) wegvereinfacht
werden, da er per Definition eine gültige Untermenge von
P(inheritable) ist.)
Die in diesem Unterabschnitt beschriebene besondere Behandlung des
Benutzers 0 (root) kann mittels des nachfolgend beschriebenen
Securebits-Mechanismus deaktiviert werden.
Es gibt zu dem unter Capabilitys und Ausführung von
Programmen durch root beschriebenen Verhalten eine Ausnahme. Falls (a)
das ausgeführte Programm über Capabilitys verfügt und
(b) die reale Benutzerkennung des Prozesses nicht 0 (root) ist und
(c) die effektive Benutzerkennung des Prozesses 0 (root) ist, dann
werden die Datei-Capabilitys berücksichtigt (d.h. sie werden nicht
fiktiv als komplett Einsen angenommen). Der normale Weg, bei dem diese
Situation auftreten kann, ist die Ausführung eines
set-UID-root-Programms, das auch über Datei-Capabilitys
verfügt. Wenn ein solches Programm ausgeführt wird, erlangt
der Prozess nur die durch das Programm eingeräumten Capabilitys (d.h.
nicht alle Capabilitys, was passierte, wenn ein set-user-ID-Root-Programm
ausgeführt würde, das keine zugeordneten Datei-Capabilitys
hat).
Beachten Sie, dass einem Programm eine leere Capability-Menge
zugeordnet werden kann und es daher möglich ist, ein
set-user-ID-root-Programm zu erstellen, das die effektive und die
gespeicherte set-user-ID des Prozesses, der das Programm ausführt,
auf 0 setzt, aber dem Prozess keine Capabilitys gewährt.
Die Capability-Begrenzungsmenge ist ein Sicherheitsmechanismus,
der zur Begrenzung der Capabilitys, die während eines
execve(2) erlangt werden können, dienen kann. Die
Begrenzungsmenge wird auf die folgende Art und Weise benutzt:
- Während eines execve(2) wird die Capability-Begrenzungsmenge
mittels AND mit der erlaubten Datei-Capability-Menge verknüpft und
das Ergebnis dieser Aktion wird der erlaubten Capability-Menge des Threads
zugewiesen. Die Capability-Begrenzungsmenge stellt daher eine Grenze
für die erlaubten Capabilitys dar, die einer ausführbaren
Datei erlaubt werden dürfen.
- (Seit Linux 2.6.25) Die Capability-Begrenzungsmenge agiert als begrenzende
Übermenge für die Capabilitys, die ein Thread zu seiner
vererbbaren Menge mittels capset(2) hinzufügen kann. Das
bedeutet, dass ein Thread eine Capability nicht zu seiner vererbbaren
Menge hinzufügen kann, falls es nicht in der Begrenzungsmenge
enthalten ist, selbst falls es in seinen erlaubten Capabilitys vorhanden
ist, wenn er eine Datei mit execve(2) ausführt, die diese
Capability in seiner vererbbaren Menge hat.
Beachten Sie, dass die Begrenzungsmenge die erlaubten
Datei-Capabilitys maskiert, aber nicht die vererbbaren Capabilitys. Falls
ein Thread eine Capability in seiner vererbbaren Menge betreut, die nicht in
seiner Begrenzungsmenge ist, dann kann er weiterhin die Capability in seiner
erlaubten Menge erlangen, indem er eine Datei ausführt, die diese
Capability in seiner vererbbaren Menge enthält.
Abhängig von der Kernelversion ist die
Capability-Begrenzungsmenge entweder ein systemweites Attribut oder ein
prozessweises Attribut.
Capability-Begrenzungsmenge seit Linux 2.6.25
Seit Linux 2.6.25 ist die Capability-Begrenzungsmenge ein
pro-Thread-Attribut. (Die nachfolgend beschriebene systemweite
Capability-Begrenzungsmenge existiert nicht mehr.)
Die Begrenzungsmenge wird bei fork(2) von dem Elternprozess
des Threads vererbt und bleibt über ein execve(2)
erhalten.
Ein Thread kann mittels der Aktion prctl(2)
PR_CAPBSET_DROP Capabilitys aus seiner Begrenzungsmenge entfernen,
vorausgesetzt, er verfügt über die Capability
CAP_SETPCAP. Sobald eine Capability aus der Begrenzungsmenge entfernt
wurde, kann sie nicht mehr zu der Menge wieder hinzugefügt werden.
Ein Thread kann mittels der Aktion prctl(2) PR_CAPBSET_READ
herausfinden, ob eine Capability in seiner Begrenzungsmenge liegt.
Entfernen von Capabilitys aus der Begrenzungsmenge ist nur
möglich, falls Datei-Capabilitys in den Kernel kompiliert wurden. In
Kerneln vor Linux 2.6.33 waren Datei-Capabilitys eine optionale
Funktionalität, die mittels der Option
CONFIG_SECURITY_FILE_CAPABILITIES konfigurierbar war. Seit Linux
2.6.33 ist die Konfigurationsoption entfernt und Datei-Capabilitys sind
immer Teil des Kernels. Wenn Datei-Capabilitys in den Kernel kompiliert
sind, beginnt der init-Prozess (der Urahn aller Prozesse) mit einer
kompletten Begrenzungsmenge. Falls Datei-Capabilitys nicht in den Kernel
kompiliert sind, dann beginnt init mit einer vollständigen
Begrenzungsmenge ohne CAP_SETPCAP, da diese Capability eine andere
Bedeutung hat, wenn es keine Datei-Capabilitys gibt.
Die Entfernung einer Capability aus der Begrenzungsmenge entfernt
sie nicht aus der vererbbaren Menge des Threads. Allerdings verhindert es
das Zurückfügen in die vererbbare Menge des Threads in der
Zukunft.
Capability-Begrenzungsmenge vor Linux 2.6.25
In Kerneln vor 2.6.25 ist die Capability-Begrenzungsmenge ein
systemweites Attribut, das alle Threads auf dem System betrifft. Auf die
Begrenzungsmenge kann über die Datei
/proc/sys/kernel/cap-bound zugegriffen werden. (Zur Erhöhung
der Konfusion wird dieser Bitmaskenparameter als vorzeichenbehaftete
Dezimalzahl in /proc/sys/kernel/cap-bound ausgedrückt.)
Nur der init-Prozess darf Capabilitys in der
Capability-Begrenzungsmenge setzen; abgesehen davon kann der Superuser (oder
genauer: ein Prozess mit der Capability CAP_SYS_MODULE) nur
Capabilitys aus dieser Menge entfernen.
Auf einem Standardsystem maskiert die Capability-Begrenzungsmenge
immer die Capability CAP_SETPCAP. Um diese Einschränkung zu
entfernen (gefährlich!), verändern Sie die Definition von
CAP_INIT_EFF_SET in include/linux/capability.h und bauen Ihren
Kernel neu.
Die systemweite Capability-Begrenzungsmengenfunktion wurde Linux
in Version 2.2.11 hinzugefügt.
Um die traditionellen Semantiken für
Übergänge zwischen 0 und von 0 verschiedenen Kennungen zu
erhalten, führt der Kernel folgende Änderungen an den
Capability-Mengen eines Threads bei Änderung der realen, effektiven,
gespeicherten und Dateisystem-Benutzerkennung (unter Verwendung von
setuid(2), setresuid(2) oder ähnlich) durch:
- 1.
- Falls einer der realen, effektiven oder gespeicherten Set-User-IDs vorher
0 war und als Ergebnis der UID-Änderung alle dieser Kennungen eine
von 0 verschiedenen Wert haben, dann werden alle Capabilitys aus den
erlaubten, effektiven und Umgebungs-Capability-Mengen
gelöscht.
- 2.
- Falls die effektive Benutzerkennung von 0 auf einen von 0 verschiedenen
Wert geändert wird, werden alle Capabilitys aus der effektiven
Menge gelöscht.
- 3.
- Falls die effektive Benutzerkennung von einem von 0 verschiedenen Wert auf
0 geändert wird, dann wird die erlaubte Menge in die effektive
Menge kopiert.
- 4.
- Falls die Dateisystem-Benutzerkennung von 0 auf einen anderen Wert
geändert wird (siehe setfsuid(2)), dann werden die folgenden
Capabilitys aus der effektiven Menge entfernt: CAP_CHOWN,
CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER,
CAP_FSETID, CAP_LINUX_IMMUTABLE (seit Linux 2.6.30),
CAP_MAC_OVERRIDE und CAP_MKNOD (seit Linux 2.6.30). Falls
die Dateisystem-UID von einem von 0 verschiedenen Wert auf 0
geändert wird, dann werden alle dieser Capabilitys, die in der
erlaubten Menge aktiviert waren, in der effektiven Menge aktiviert.
Falls ein Thread, der einen Wert 0 für mindestens eine
seiner Benutzerkennungen hat, verhindern möchte, dass seine erlaubte
Capability-Menge bereinigt wird, wenn er alle seine Benutzerkennungen auf
einen von 0 verschiedenen Wert setzt, kann er dies mittels der unten
beschriebenen SECBIT_KEEP_CAPS-Securebits-Schaltern erreichen.
Ein Thread kann seine erlaubten, effektiven und vererbbaren
Capability-Mengen mittels der Systemaufrufe capget(2) und
capset(2) ermitteln und ändern. Allerdings werden für
diesen Zweck die Verwendung von cap_get_proc(3) und
cap_set_proc(3), beide im Paket libcap bereitgestellt,
empfohlen. Die folgenden Regeln bestimmen die Änderungen an den
Capability-Mengen des Threads:
- 1.
- Falls der Aufrufende nicht über die Capability CAP_SETPCAP
verfügt, dann muss die neue vererbbare Menge eine Teilmenge der
Kombination der bestehenden vererbbaren und erlaubten Menge sein.
- 2.
- (Seit Linux 2.6.25) Die neue vererbbare Menge muss eine Teilmenge der
Kombination der bestehenden vererbbaren Menge und der
Capability-Begrenzungsmenge sein.
- 3.
- Die neue erlaubte Menge muss eine Teilmenge der bestehenden erlaubten
Menge sein (d.h. es ist nicht möglich, erlaubte Capabilitys zu
erlangen, die der Thread derzeit nicht hat).
- 4.
- Die neue effektive Menge muss eine Teilmenge der neuen erlaubten Menge
sein.
Beginnend mit Kernel 2.6.26 und mit einem Kernel, in dem
Datei-Capabilitys aktiviert sind, implementiert Linux eine Menge von
pro-Thread-securebits-Schaltern, die zur Deaktivierung von spezieller
Handhabung von Capabilitys für UID 0 (root) verwandt werden
können. Dies sind die folgenden Schalter:
- SECBIT_KEEP_CAPS
- Durch Setzen dieses Schalters darf ein Thread, der mindestens eine 0 UID
hat, Capabilitys in seiner erlaubten Menge behalten, wenn er alle UIDs auf
von 0 verschiedene Werte umschaltet. Falls dieser Schalter nicht gesetzt
ist, dann führt das Umschalten der UIDs dazu, dass er alle
erlaubten Capabilitys verliert. Dieser Schalter wird bei execve(2)
immer bereinigt.
- Bachten Sie, dass selbst mit gesetztem Schalter SECBIT_KEEP_CAPS
die effektiven Capabilitys eines Threads bereinigt werden, wenn er seine
effektive UID auf einen von Null verschiedenen Wert umschaltet. Falls der
Thread allerdings über diesen Schalter verfügt und seine
effektive UID bereits von Null verschieden ist und der Thread
anschließend alle anderen UIDs auf einen von Null verschiedenen
Wert umschaltet, dann werden die effektiven Capabilitys nicht
bereinigt.
- Die Einstellung des Schalters SECBIT_KEEP_CAPS wird ignoriert,
falls der Schalter SECBIT_NO_SETUID_FIXUP gesetzt ist. (Letzterer
Schalter stellt eine Übermenge des Effekts des ersteren Schalters
bereit.)
- Dieser Schalter stellt die gleiche Funktionalität wie die
ältere Aktion prctl(2) PR_SET_KEEPCAPS bereit.
- SECBIT_NO_SETUID_FIXUP
- Setzen dieses Schalters hindert den Kernel daran, die erlaubten,
effektiven und Umgebungs-Capability-Mengen des Prozesses anzupassen, wenn
die effektive und die Dateisystem-UID eines Threads zwischen null und von
null verschiedenen Werten umgeschaltet werden. (Lesen Sie den Abschnitt
Effekt von Benutzerkennungsänderungen auf
Capabilitys)
- SECBIT_NOROOT
- Falls dieses Bit gesetzt ist, dann verleiht der Kernel keine Capabilitys,
wenn ein Set-User-ID-Root-Programm ausgeführt wird oder wenn ein
Prozess mit einer effektiven oder realen UID von 0 execve(2)
aufruft. (Lesen Sie den Abschnitt Capabilitys und Ausführung von
Programmen durch root)
- SECBIT_NO_CAP_AMBIENT_RAISE
- Durch Setzen dieses Schalters dürfen keine Umgebungs-Capabilitys
mit der prctl(2)-Aktion PR_CAP_AMBIENT_RAISE gehoben
werden.
Jeder der obigen »basis«-Schalter hat einen
begleitenden »gesperrten« Schalter. Das Setzen eines
»gesperrten« Schalters ist unumkehrbar und hat den Effekt,
dass weitere Änderungen an dem entsprechenden Basisschalter nicht
mehr möglich sind. Die gesperrten Schalter sind:
SECBIT_KEEP_CAPS_LOCKED, SECBIT_NO_SETUID_FIXUP_LOCKED,
SECBIT_NOROOT_LOCKED und
SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED.
Die Schalter securebits können mit den Aktionen
prctl(2) PR_SET_SECUREBITS und PR_GET_SECUREBITS
geändert und abgefragt werden. Die Capability CAP_SETPCAP wird
für die Veränderung der Schalter benötigt. Beachten
Sie, dass die Konstanten SECBIT_* nur nachdem Sie die Header-Datei
<linux/securebits.h> eingebunden haben verfügbar
sind.
Die Schalter securebits werden von Kindprozessen vererbt.
Während eines execve(2) werden alle Schalter beibehalten,
außer SECBIT_KEEP_CAPS, das immer bereinigt wird.
Eine Anwendung kann den folgenden Aufruf verwenden, um sich selbst
und alle seine Abkömmlinge in eine Umgebung zu sperren, in der die
einzige Möglichkeit, Capabilitys zu erlangen, darin besteht, ein
Programm auzuführen, das über die zugeordneten
Datei-Capabilitys verfügt:
prctl(PR_SET_SECUREBITS,
/* SECBIT_KEEP_CAPS off */
SECBIT_KEEP_CAPS_LOCKED |
SECBIT_NO_SETUID_FIXUP |
SECBIT_NO_SETUID_FIXUP_LOCKED |
SECBIT_NOROOT |
SECBIT_NOROOT_LOCKED);
/* Setzen/Sperren von SECBIT_NO_CAP_AMBIENT_RAISE
ist nicht erforderlich */
Ein set-user-ID-Programm, dessen UID auf die UID passt, die einen
Benutzernamensraum erstellte, wird die Capabilitys in den erlaubten und
effektiven Mengen übertragen, wenn es durch irgendeinen Prozess
innerhalb dieses Namensraums (oder einen Benutzernamensraum, der davon
abstammt) ausgeführt wird.
Die obigen Regeln über die Umwandlung der Capabilitys des
Prozesses während eines execve(2) werden genau in den
Unterabschnitten Umwandlungen von Capabilitys während
execve() und Capabilitys und Ausführung von Programmen
durch root beschrieben, wobei im letzeren Unterabschnitt als Unterschied
»root« die UID des Erstellers des Benutzernamensraums ist.
Traditionelle (d.h. Version 2-)Datei-Capabilitys ordnen nur eine
Menge von Capability-Masken einem binären Programm zu. Wenn ein
Prozess ein Programm mit solchen Capabilitys ausführt, erlangt es die
zugeordneten Capabilitys (innerhalb seines Benutzernamensraums) wie in den
oben beschriebenen Regeln »Umwandlungen von Capabilitys
während execve()« beschrieben.
Da Version-2-Datei-Capabilitys dem ausführenden Prozess
unabhängig davon, in welchem Namensraum er sich befindet, Capabilitys
verleiht, dürfen nur privilegierte Prozesse Capabilitys einer Datei
zuordnen. Hier bedeutet »privilegiert«, dass ein Prozess
über die Capability CAP_SETFCAP in dem Benutzernamensraum, in
dem das Dateisystem eingehängt wurde (normalerweise dem initialen
Namensraum), verfügt. Diese Einschränkung führt dazu,
dass in bestimmten Einsatzfällen Datei-Capabilitys nutzlos sind. Es
kann zum Beispiel in namensraumbezogenen Containern wünschenswert
sein, in der Lage zu sein, ein Programm zu erstellen, das Capabilitys nur an
Prozesse, die innerhalb dieses Containers ausgeführt werden, zu
verleihen, aber nicht an Prozesse, die außerhalb des Containers
ausgeführt werden.
Linux 4.14 fügte sogenannte namensraumbezogene
Datei-Capabilitys hinzu, um solche Fälle zu unterstützen.
Namensraumbezogene Datei-Capabilitys werden als Version 3 (d.h.
VFS_CAP_REVISION_3) erweiterte Attribute security.capability
aufgezeichnet. Solch ein Attribut wird automatisch unter den oben in
»Erweiterte Attributversionierung von Datei-Capabilitys«
beschriebenen Umständen erstellt. Wenn ein erweitertes
Version-3-Attribut security.capability erstellt wird, zeichnet der
Kernel nicht nur die Capability-Maske in dem erweiterten Attribut auf,
sondern auch die Benutzerkennung von root in dem Namensraum.
Wie mit Programmen, die eine Datei-Capability
VFS_CAP_REVISION_2 haben, verleiht ein Programm mit Datei-Capability
VFS_CAP_REVISION_3 während eines execve() Capabilitys
an einen Prozess. Allerdings werden Capabilitys nur verliehen, falls das
Programm von einem Prozess ausgeführt wird, der in einem
Benutzernamensraum, dessen UID 0 auf die Wurzelbenutzerkennung, die in dem
erweiterten Attribut gespeichert ist, abgebildet ist oder wenn er von einem
Prozess ausgeführt wird, der in einem Nachkommen solch eines
Namensraums liegt.
Für weitere Informationen über die Interaktion von
Capabilitys und Benutzer-Namensräumen lesen Sie
user_namespaces(7).