Wenn sich die CPU im Benutzermodus befindet, kann die CPU keine privilegierten Anweisungen ausführen und kann nicht auf den Kernelspeicher zugreifen.
Wenn sich die CPU im Kernel-Modus befindet, kann sie alle Anweisungen ausführen und auf den gesamten Speicher zugreifen.
Jetzt in Linux kann ein Benutzer - Modus - Programm den gesamten Speicher zugreifen (mit /dev/mem
) und kann die beiden privilegierten Befehle ausführen IN
und OUT
(unter Verwendung iopl()
glaube ich).
Ein Programm im Benutzermodus unter Linux kann also die meisten Dinge (ich denke die meisten Dinge), die im Kernel-Modus ausgeführt werden können.
Wenn Sie einem Programm im Benutzermodus nicht erlauben, über all diese Möglichkeiten zu verfügen, wird dies dem Zweck der Verwendung von CPU-Modi entgegengewirkt?
iopl
lässt nicht alle privilegierten Anweisungen zu, daher ist es immer noch nützlich, um sicherzustellen, dass ein fehlerhaftes User-Space-Programm nicht versehentlich ausgeführtinvd
wird, indem es durch einen beschädigten Funktionszeiger springt, der auf ausführbaren Speicher zeigt, der mit0F 08
Bytes beginnt . Ich habe eine Antwort mit einigen nicht sicherheitsrelevanten Gründen hinzugefügt, warum es nützlich ist, User-Space-Prozesse ihre Berechtigungen erhöhen zu lassen.Nur auf die gleiche Weise, die die
modprobe
Sicherheit "besiegt", indem neuer Code in den Kernel geladen wird.Aus verschiedenen Gründen ist es manchmal sinnvoller, semiprivilegierten Code (wie Grafiktreiber auf dem X-Server) im User-Space auszuführen, als in einem Kernel-Thread.
kill
es leichter zu machen, es sei denn, es sperrt die HW.Es trägt nicht viel zur Sicherheit bei, bietet jedoch große Vorteile in Bezug auf Zuverlässigkeit und Softwarearchitektur.
Das Einspielen von Grafiktreibern in den Kernel kann die Anzahl der Kontextwechsel zwischen X-Clients und X-Servern verringern, z. B. wenn nur ein Benutzer-> Kernel-> Benutzer Daten in einen anderen Use-Space-Prozess einspeisen muss, aber X-Server sind in der Vergangenheit zu groß und zu fehlerhaft um sie vollständig im Kernel zu haben.
Ja, böswilliger Code mit diesen Rechten könnte den Kernel übernehmen, wenn er dies wünscht, und dazu verwenden
/dev/mem
, den Kernelcode zu ändern.Oder führen Sie beispielsweise auf x86 eine
cli
Anweisung aus, um Interrupts auf diesem Core zu deaktivieren, nachdem Sie eineniopl
Systemaufruf ausgeführt haben, um die E / A-Berechtigungsstufe auf 0 zu setzen.Aber auch x86
iopl
bietet "nur" Zugriff auf einige Anweisungen : in / out (und die String-Versionen ins / outs) und cli / sti. Es lässt nicht Sie verwendenrdmsr
oderwrmsr
zu lesen oder zu schreiben „modellspezifische Register“ (zB ,IA32_LSTAR
die den Kernel Eintrittspunktadresse für die x86-64 setztsyscall
Anweisung) oder Verwendunglidt
der Interrupt-Deskriptortabelle ersetzen (die Sie völlig würden nehmen lassen über die Maschine aus dem vorhandenen Kernel, zumindest auf diesem Kern.)Sie können nicht einmal Steuerregister lesen (wie CR3, das die physikalische Adresse des Seitenverzeichnisses der obersten Ebene enthält, das ein angreifender Prozess möglicherweise als Versatz
/dev/mem
für die Änderung seiner eigenen Seitentabellen als Alternative zu einermmap
Erweiterung von verwendet/dev/mem
. )invd
(Ungültigmachen aller Caches ohne Zurückschreiben !! ( Anwendungsfall = frühes BIOS, bevor RAM konfiguriert wird)) ist ein weiterer Spaß, der immer die volle CPL 0 (aktuelle Berechtigungsstufe) erfordert, nicht nur IOPL. Evenwbinvd
ist privilegiert, weil es so langsam (und nicht unterbrechbar) ist und alle Caches über alle Kerne hinweg leeren muss. (Siehe Gibt es eine Möglichkeit , die gesamte CPU - Cache zu einem Programm mit Bezug zu spülen? Und WBINVD Anweisung Nutzung )Fehler, die zu einem Sprung zu einer schlechten Adresse führen, bei der Daten als Code ausgeführt werden, können daher keine dieser Anweisungen versehentlich auf einem User-Space-X-Server ausführen.
Die aktuelle Berechtigungsstufe (im geschützten und langen Modus) sind die niedrigen 2 Bits von
cs
(dem Codesegment-Selektor) .mov eax, cs
/and eax, 3
arbeitet in einem beliebigen Modus, um die Berechtigungsstufe zu lesen.Um die Berechtigungsstufe zu schreiben, müssen Sie ein
jmp far
odercall far
festlegenCS:RIP
(der GDT / LDT-Eintrag für das Zielsegment kann sie jedoch basierend auf der alten Berechtigungsstufe einschränken, weshalb der Benutzer-Space dies nicht tun kann, um sich selbst zu erhöhen). Oder Sie verwendenint
odersyscall
, um an einem Kernel-Einstiegspunkt zu Ring 0 zu wechseln.quelle