Consentire a un programma in modalità utente di accedere alla memoria dello spazio del kernel ed eseguire le istruzioni IN e OUT vanifica lo scopo di avere modalità CPU?


19

Quando la CPU è in modalità utente, la CPU non può eseguire istruzioni privilegiate e non può accedere alla memoria dello spazio del kernel.

E quando la CPU è in modalità kernel, la CPU può eseguire tutte le istruzioni e può accedere a tutta la memoria.

Ora in Linux, un programma in modalità utente può accedere a tutta la memoria (usando /dev/mem) e può eseguire le due istruzioni privilegiate INe OUT(usando iopl()credo).

Quindi un programma in modalità utente in Linux può fare la maggior parte delle cose (penso molte cose) che possono essere fatte in modalità kernel.

Consentire a un programma in modalità utente di avere tutta questa potenza non ha lo scopo di avere modalità CPU?

Risposte:


23

Quindi un programma in modalità utente in Linux può fare la maggior parte delle cose (penso molte cose) che possono essere fatte in modalità kernel.

Bene, non tutti i programmi in modalità utente possono, solo quelli con i privilegi appropriati. E questo è determinato dal kernel.

/dev/memè protetto dalle consuete autorizzazioni di accesso al filesystem e dalla CAP_SYS_RAWIOfunzionalità. iopl()e ioperm()sono anche limitati attraverso la stessa capacità.

/dev/mempuò anche essere compilato completamente dal kernel ( CONFIG_DEVMEM).

Consentire a un programma in modalità utente di avere tutta questa potenza non ha lo scopo di avere modalità CPU?

Beh forse. Dipende da cosa si desidera siano in grado di eseguire processi con spazio utente privilegiato. I processi dello spazio utente possono anche eliminare l'intero disco rigido se hanno accesso a /dev/sda(o equivalente), anche se ciò vanifica lo scopo di disporre di un driver del file system per gestire l'accesso alla memoria.

(Quindi c'è anche il fatto che iopl()funziona utilizzando le modalità di privilegio della CPU su i386, quindi non si può dire che possa vanificare il loro scopo.)


2
Anche ioplnon consente tutte le istruzioni privilegiate, quindi è ancora utile per assicurarsi che un programma con spazio utente errato non venga eseguito accidentalmente invdsaltando attraverso un puntatore di funzione danneggiato che punta alla memoria eseguibile che inizia con 0F 08byte. Ho aggiunto una risposta con alcuni dei motivi di non sicurezza per cui è utile che i processi dello spazio utente elevino i loro privilegi.
Peter Cordes,

16

Solo allo stesso modo che modprobe"sconfigge" la sicurezza caricando il nuovo codice nel kernel.

Per vari motivi, a volte ha più senso avere un codice semi-privilegiato (come i driver grafici all'interno del server X) in esecuzione nello spazio utente anziché in un thread del kernel.

  • Poterlo killpiù facilmente, a meno che non blocchi l'HW.
  • Avendolo richiesto-page il suo codice / dati dai file nel filesystem. (La memoria del kernel non è impaginabile)
  • Dandogli il suo spazio di indirizzi virtuale in cui i bug nel server X potrebbero semplicemente arrestare il server X, senza rimuovere il kernel.

Non fa molto per la sicurezza, ma ci sono grandi vantaggi in termini di affidabilità e architettura del software.

L'inserimento di driver grafici nel kernel potrebbe ridurre i cambi di contesto tra client X e server X, come un solo utente user-> kernel-> invece di dover inserire i dati in un altro processo di spazio di utilizzo, ma i server X sono storicamente troppo grandi e con errori volerli completamente nel kernel.


Sì, il codice dannoso con questi priv potrebbe assumere il kernel se lo desidera, usando /dev/memper modificare il codice del kernel.

O ad esempio su x86, eseguire cliun'istruzione per disabilitare gli interrupt su quel core dopo aver effettuato una ioplchiamata di sistema per impostare il suo livello di privilegio IO su ring 0.

Ma anche x86 iopl"solo" dà accesso ad alcune istruzioni : in / out (e le versioni di stringa in / out) e cli / sti. Non ti permette di usare rdmsro wrmsrdi leggere o scrivere "registri specifici del modello" (ad esempio, IA32_LSTARche imposta l'indirizzo del punto di ingresso del kernel per l' syscallistruzione x86-64 ), o usa lidtper sostituire la tabella descrittore di interrupt (che ti permetterebbe di prendere totalmente sulla macchina dal kernel esistente, almeno su quel core.)

Non è nemmeno possibile leggere i registri di controllo (come CR3 che contiene l'indirizzo fisico della directory di pagina di livello superiore, che un processo di attacco potrebbe trovare utile come offset /dev/memper modificare le proprie tabelle di pagine in alternativa a mmappiù di /dev/mem. )

invd(invalidare tutte le cache senza riscrittura !! ( caso d'uso = BIOS iniziale prima della configurazione della RAM)) è un altro divertente che richiede sempre il CPL 0 completo (livello di privilegio corrente), non solo IOPL. Anche wbinvdè privilegiato perché è così lento (e non interrompibile) e deve svuotare tutte le cache su tutti i core. (Vedere C'è un modo per svuotare l'intera cache CPU relativa a un programma? E l'uso di istruzioni WBINVD )

I bug che causano il salto a un indirizzo errato eseguono i dati come codice, pertanto non possono eseguire accidentalmente nessuna di queste istruzioni in un server X dello spazio utente.


Il livello di privilegio corrente (in modalità protetta e lunga) è rappresentato dai 2 bit bassi di cs(il selettore del segmento di codice) . mov eax, cs/ and eax, 3funziona in qualsiasi modalità per leggere il livello di privilegio.

Per scrivere il livello di privilegio, fai un jmp faro call farper impostare CS:RIP(ma la voce GDT / LDT per il segmento di destinazione può limitarlo in base al vecchio livello di privilegio, motivo per cui lo spazio utente non può farlo per elevarsi). Oppure usi into syscallper passare al ring 0 in un punto di ingresso del kernel.


In realtà, sono abbastanza sicuro che sia solo un "selettore" di codice nella sala Intel. Era un segmento nell'8086/8088, forse nell'80186, ma nell'80286, era indicato come un selettore, e da allora non credo che abbiano cambiato ufficialmente quella terminologia.
un CVn l'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.