Speculative execution e bug hardware

I processori moderni, per migliorare le prestazioni, possono decidere di eseguire in anticipo alcune istruzioni che probabilmente dovranno eseguire in futuro, invece che aspettare tempi morti. Se il l'algoritmo di predizione aveva ragione abbiamo un incremento delle performance, altrimenti si buttano via i risultati e si va avanti come se nulla fosse successo, ma senza neanche aver perso tempo.

Anche se l'algoritmo di predizione funziona nel 50% dei casi (come ad esempio un algoritmo completamente randomico) si ha un significativo miglioramento delle prestazioni!

Questo modo di operare basato su una scommessa si chiama esecuzione speculativa, in quanto appunto il processore specula sul risultato di quelle istruzioni che possono andare a modificare il flusso di esecuzione del programma, come ad esempio:

  • salti condizionati
  • chiamate a funzione
  • ritorno dalle funzioni

in modo da ottenere un significativo miglioramento delle performance.

Meltdown & Spectre

Nel Gennaio del 2018 due vulnerabilità vengono rese note: Meltdown e Spectre. Sono entrambe vulnerabilità che riguardano l'esecuzione speculativa di praticamente tutti i processori dell'epoca, anche se di produttori diversi.

Meltdown permette ad un processo di leggere la memoria di altri processi, questo accade perché il codice che viene eseguito in maniera speculativa può accedere a tutti gli indirizzi di memoria, anche a quelli non direttamente associati al processo. Questo attacco permette quindi di estrarre tutti i segreti dagli altri processi, ma anche dal kernel!

Spectre al contrario si basa sulla possibilità di far eseguire, ad un altro processo, codice arbitrario durante l'esecuzione speculativa. Anche in questo modo si può forzare l'estrazione di segreti appartenenti all'altro processo, che può anche essere lo stesso kernel.

Attacchi side-channel

Entrambi gli attacchi metdown e spectre non permettono di estrarre dati direttamente. Quello che fanno è usare i dati per eseguire degli accessi alla memoria cache in maniera dipendente dal dato letto. L'attaccante successivamente, per poter estrarre i dati davvero, è costretto a misurare i tempi di accesso alla memoria:

  • se i tempi sono bassi allora probabilmente il codice speculativo vi ha acceduto
  • se i tempi sono alti, probabilmente il codice non vi ha acceduto.

Questa tecnica è nota come FLUSH+RELOAD ed è utilizzata spesso in questo genere di attacchi.

Più in generale qualsiasi tecnica che permette di ottenere informazioni in maniera indiretta è detto attacco side-channel. Alcuni esempi ricorrenti di side-channel sono:

  • timing attacks: misurare il tempo di esecuzione di un software o una routine permette spesso di ottenere informazioni sul risultato della computazione
  • power monitoring: monitorare la potenza dell'hardware a volte può essere utile a capire cosa sta facendo, sia per il consumo stesso che per il rumore che l'hardware può aggiungere sul canale di alimentazione