Mitigazione del tracollo controllando l'indirizzo anomalo in ogni errore di pagina?

8

Domanda breve

Controllerebbe se l'errore di errore di ogni pagina che punta alla memoria del kernel rilevi in modo affidabile un tentativo di exploit Meltdown, su sistemi che non hanno Intel TSX (e quindi non possono sopprimere le eccezioni)? La funzione kernel do_page_fault() di Linux è richiamata su ogni errore di pagina e l'indirizzo dell'accesso di memoria guasto è disponibile in quella funzione, quindi dovrebbe essere possibile verificare se tale indirizzo punta a un intervallo di memoria specifico per il kernel. Per un modello di minaccia in cui KPTI non è un'opzione e dove il trading off-availability (DoS non privilegiato) per la riservatezza è accettabile, questa idea è corretta?

Domanda lunga

La recente vulnerabilità di Meltdown nei processori Intel sfrutta la proprietà di esecuzione fuori ordine di tutti i processori moderni per leggere la memoria fisica arbitraria. Ciò si basa sulla possibilità di tentare ripetutamente di accedere alla memoria del kernel, nonostante il fatto che i tentativi di accesso falliranno. Questi tentativi di accesso non riusciti attivano un #PF o un errore di pagina, causando l'invio del processo dello spazio utente SIGSEGV a causa del suo tentativo di accedere alla memoria del kernel. L'attacco Meltdown sfrutta il fatto che la cache è ancora popolata con la memoria privilegiata nonostante l'accesso venga negato. La fase successiva dell'attacco consiste nell'utilizzare un attacco di temporizzazione per recuperare il contenuto della cache. Senza il supporto di TSX, tuttavia, sembra impossibile (per quanto ne so io) inibire questi errori di pagina. Su tali sistemi, Meltdown innesca necessariamente un gran numero di errori di pagina causati da tentativi di accedere alla memoria del kernel. Questo può essere rilevato dal kernel.

Da il documento , vengono descritti tre passaggi per eseguire l'attacco:

Meltdown combines the two building blocks discussed
in Section 4.  First, an attacker makes the CPU execute
a transient instruction sequence which uses an inacces-
sible secret value stored somewhere in physical memory
(cf. Section 4.1). The transient instruction sequence acts
as the transmitter of a covert channel (cf. Section 4.2),
ultimately leaking the secret value to the attacker.

  Meltdown consists of 3 steps:

Step 1  The content of an attacker-chosen memory loca-
  tion, which is inaccessible to the attacker, is loaded
  into a register.

Step 2  A transient instruction accesses a cache line
  based on the secret content of the register.

Step 3  The attacker uses Flush+Reload to determine the
  accessed cache line and hence the secret stored at the
  chosen memory location.

By repeating these steps for different memory locations,
the attacker can dump the kernel memory, including the
entire physical memory.

Dopo aver letto circa un supposto attenuazione utilizzando il sottosistema di tracciamento del kernel, ha senso che il rilevamento di un numero anormalmente elevato di errori di pagina dovuti all'accesso alla memoria del kernel sarebbe in grado di rilevare in modo affidabile Meltdown. Il mio pensiero è corretto? Tale mitigazione verrebbe semplicemente a verificare ad ogni errore di pagina se CR2 (il registro che contiene l'indirizzo faulting) è maggiore di 0xffff000000000000 , il che indicherebbe che è stato fatto un tentativo di accedere alla memoria del kernel. Il sistema potrebbe quindi indurre un panico del kernel, impedendo che l'attacco continui.

Dall'origine del kernel , do_page_fault() la funzione è definita come:

dotraplinkage void notrace
do_page_fault(struct pt_regs *regs, unsigned long error_code)
{
    unsigned long address = read_cr2(); /* Get the faulting address */
    enum ctx_state prev_state;

    prev_state = exception_enter();
    if (trace_pagefault_enabled())
        trace_page_fault_entries(address, regs, error_code);

    __do_page_fault(regs, error_code, address);
    exception_exit(prev_state);
}
NOKPROBE_SYMBOL(do_page_fault);

Questa funzione viene chiamata ogni volta che si verifica un errore di pagina, con l'indirizzo in errore salvato in address . Senza il supporto TSX, per quanto ne so, è impossibile che l'attacco eviti di entrare in questa funzione. Mi sembra di aggiungere un semplice controllo per vedere se l'indirizzo si trova in un intervallo pericoloso, quindi qualcosa sulla falsariga di BUG_ON(address > 0xffff000000000000) sarebbe in grado di rilevare in modo affidabile il 100% degli attacchi di fusione in base a questi vincoli. Ciò potrebbe essere reso più affidabile (meno probabilità di generare falsi positivi) attivando un panico solo quando si verifica un numero sufficiente di violazioni e ignorando una violazione se address è inferiore a mmap_min_addr (che implicherebbe un puntatore NULL benigno dereferenziazione ), ma ciò sarebbe necessario solo se un determinato carico di lavoro attiva falsi positivi.

Questa mitigazione non funzionerebbe se si verifica una delle seguenti condizioni:

  • Spectre, che non causa errori di pagina, può eseguire Meltdown senza abusare di eBPF.
  • Esiste un altro modo di utilizzare Meltdown senza attivare un errore di pagina, su sistemi senza TSX.
  • La funzione do_page_fault() può essere evitata quando si verifica un errore di pagina.

Quando rilegge la carta, cita la soppressione delle eccezioni usando altri metodi rispetto a TSX, ma non è del tutto chiaro per me. Lo fa sembrare come se un errore di pagina potesse essere evitato in questo modo:

if (condition_mispredicted_as_false)
    access_kernel_memory();

Se questo è vero, allora questo meccanismo di rilevamento (e quello di Capsule8) non funzionerebbe.

Questa mitigazione funzionerebbe su sistemi senza TSX, assumendo che i falsi positivi naturali non rappresentino un problema e ignorando il fatto che aprirebbe bachi DoS senza privilegi?

    
posta forest 09.01.2018 - 08:49
fonte

1 risposta

5

Ciò impedirà due su tre modi di eseguire un attacco di fusione. Sfortunatamente per te, non fa nulla per il terzo.

Il modo più semplice per eseguire un attacco di fusione è eseguire una lettura non valida con un ritardo della pipeline sufficientemente lungo che la CPU agisce speculativamente sulla lettura prima che venga attivato l'errore di pagina, quindi rileva l'errore. La tua proposta individuerà e interromperà prima che l'autore dell'attacco possa eseguire più di un paio di letture.

Il modo più veloce è usare TSX per sopprimere l'errore, ma hai specificato che TSX non è presente sul sistema.

Il terzo modo è di combinare Meltdown con la cattiva interpretazione del ramo di Spectre: addestrare il predittore del ramo a prendere il ramo "read memory" con indirizzi innocui, quindi diramarlo nell'altro modo specificando un indirizzo protetto. Questo è molto più lento rispetto ad altri modi di leggere la memoria protetta, ma dal momento che la lettura illegale viene scartata quando viene rilevato il misprediction del ramo, non viene mai generato alcun errore di pagina. Di conseguenza, le letture sono completamente invisibili al codice proposto.

    
risposta data 09.01.2018 - 11:06
fonte

Leggi altre domande sui tag