Ed eccoci qui in questo nuovo post. Oggi volevo parlarvi di un importantissimo bug, venuto alla luce il 3 gennaio del 2018, che affligge tutti i PC che portano come processore una CPU Intel. Questo bug, che andremo a trattare tra poco, affligge, da come si evince dalle ultime ricerche, anche in alcuni processori AMD e ARM, colpendo tutti i sistemi operativi. Quindi colpisce Windows, Linux, Mac OS, iOS, Android e moltissimi altri sistemi operativi. Insomma colpisce un po’ tutti.
Questo problema non sarà molto facile da spiegare e richiede anche da parte vostra, un minimo di competenza tecnica nel settore. Se non comprendete al meglio ciò che sarà scritto in seguito non vi preoccupate; chiedete pure nei commenti ogni chiarimento, che proverò a fornirvi nel miglior modo possibile.
Detto questo iniziamo
Il 3 gennaio 2018 il team di Google Project Zero, una task force di ricercatori Google resa operativa per cercare nuove falle di sicurezza informatiche e documentarle, per far si che vengano adottate delle soluzioni da parte delle aziende produttrici dei vari software / componenti hardware, ha scoperto la presenza di un bug che affligge tutti i processori Intel prodotti da 10 anni (quindi questo bug è stato tramandato in 10 anni di generazioni di processori fino alle nostre attuali CPU). Questo problema subito dopo è stato esteso, dopo ulteriori ricerche, anche ai processori AMD e ai processori ARM (processori presenti in moltissime tipologie di tablet e smartphone).
Questo bug ha ricevuto il nome Meltdown. Questo tipo di bug è stato associato subito dopo ad un altro bug denominato Spectre (scoperto sempre da Google Project Zero), che affligge sempre tutti i processori Intel, AMD e ARM.
Facciamo chiarezza su alcune nozioni di informatica prima di proseguire
Un sistema è formato dall’insieme del software e dell’hardware. Il software comunica con l’hardware per fare in modo che vengano svolte delle operazioni. Ci sono diversi livelli, una sorta di gerarchia. Più un livello si trova in basso, più acquisisce importanza, dato che è a contatto con una porzione di componenti molto più vasta.
I livelli sono questi: troviamo l’hardware al primo posto. Successivamente troviamo il kernel e sopra il kernel troviamo tutte le applicazioni lanciate dall’utente o avviate in automatico da altre applicazioni.
L’hardware esegue le operazioni. Le applicazioni permettono all’utente di svolgere tutte le proprie operazioni con il computer o con altre tipologie di device e il kernel permette di fare da tramite tra le applicazioni avviate e l’hardware, assegnando le risorse necessario, facendo in modo che tutte le applicazioni e tutti i processi abbiano le risorse sufficienti per funzionare correttamente e per fare in modo che il tutto venga svolto nella più totale sicurezza possibile.
Come potrete notare dallo schema che avete appena visto, per hardware si intende tutte le componenti fisiche che permettono di eseguire operazioni. Le applicazioni sono appunto i programmi lanciati dall’utente e il kernel si pone tra le due parti per fare da tramite e per fare da garante per la sicurezza.
In questo post prenderemo in esame, come si può notare anche dallo schema, solo 3 componenti hardware, che sono anche le componenti più importanti di un qualsiasi sistema.
Prendiamo quindi in considerazione l’unità di storage (che può essere un hdd o un ssd), le memorie RAM e il processore o CPU.
Facendo un piccolo ripasso, l’unità di storage serve per memorizzare dati. E’ l’unità che contiene il sistema operativo, tutti i programmi e tutti i dati dell’utente. Questo tipo di memoria è la più lenta del computer.
La RAM, memoria decisamente più veloce dell’unità di storage, serve per l’esecuzione dei processi. Al suo interno infatti vengono caricati tutti i programmi e i processi che dovranno essere eseguiti. La RAM essendo così veloce, permette di rendere pronti, praticamente al volo, tutti i dati che dovranno essere elaborati. Per la sua struttura fisica, questa memoria non può contenere dati permanentemente come invece può fare lo storage, in quando appena viene rimossa l’alimentazione (il device viene spento), tutto il suo contenuto viene azzerato.
La RAM al suo interno contiene tutta una serie di celle. Queste celle sono segnate con un indirizzo, che specifica la posizione effettiva. Quindi quando un processo ha bisogno di un eventuale dato, il Kernel lo va a recuperare semplicemente seguendo l’indirizzo che ne specifica la sua esatta posizione.
Nella RAM vengono quindi caricati sia i processi, che lo stesso kernel. Infatti la memoria RAM è divisa in due parti. C’è lo User Space, spazio dedicato alla memorizzazione di tutti i processi avviati dall’utente. E poi c’è il Kernel Space, spazio riservato esclusivamente al kernel, che permette allo stesso kernel di funzionare. Infatti come tutti i processi, anche il Kernel è caratterizzato da una serie di processi che per funzionare hanno bisogno di essere spostati nella RAM.
A differenza di come si può vedere dallo schema appena riportato, in questa memoria sia la User Memory, che la Kernel Memory, non sono memorizzate in modo ordinato. Ma sono memorizzate in modo “causale“. Posto tra virgolette questo termine in quanto comunque il kernel ha gli indirizzi di memoria che specificano dove si trovano le sue stesse componenti e la User Area ha i propri indirizzi, gestiti dal kernel, per definire dove quest’area è collocata.
Quindi di norma la User Space non ha i permessi di interagire direttamente con la memoria o con nessun componente hardware in generale, ma può solo chiedere al kernel (tramite una chiamata denominata System Call), di farlo al posto suo.
La CPU invece al suo interno ha un’altra memoria, chiamata Cache. In realtà ha diverse tipologie di memoria, ma la maggior parte delle stesse non sono accessibili neppure dal Kernel, ma sono accessibili solo e unicamente dalla CPU stessa. Dicevamo che ha diverse Cache, aventi la stessa frequenza del processore, dove al loro interno vengono contenti tutti i set di operazioni che il processore deve elaborare in quel momento.
Lo so che molti si saranno già persi in questa spiegazione, ma prometto che ora diventerà più facile (più o meno)
Che cosa svolge il processore?
Il processore, detto proprio semplicemente esegue le operazioni in sequenza. O per lo meno così ci insegnano, con molta semplicità. Con troppa semplicità, dato che questo concetto non è completamente veritiero. Chi ha studiato o chi sta studiando all’università di informatica ed ha avuto modo di studiare nel dettaglio il processore e il suo funzionamento, avrà trattato sicuramente della pratica di speculazione dei processi. In pratica sulla base delle ultime operazioni eseguite, il processore tenta di prevedere, con una tecnica chiamata speculate, quali sono le operazioni che molto probabilmente dovrà fare dopo, in modo tale da velocizzare il lavoro. Inoltre il processore pone le istruzioni di un complesso software in modo differente da come vengono dichiarate di default. In pratica, può eseguire alcune operazioni prima rispetto ad altre, per velocizzare ulteriormente il lavoro e quindi impiegare il meno tempo possibile.
Dicevamo che il processore tenta di prevedere quali operazioni dovranno essere eseguite in seguito. Un volta completato questo processo di “previsione” (poniamolo così per semplificare le cose), effettua un controllo, per verificare se la sua previsione è corretta. Se è corretta allora esegue le istruzioni predette o sistemate in modo da risparmiare tempo. Altrimenti cancella la propria speculazione e torna ad eseguire i processi come dettato dal programma avviato.
PS: Io non sono un ingegnere e quindi chiedo scusa per eventuali piccoli errori che ho commesso nello scrivere quanto avete appena letto
Quindi dove risiede questo bug?
Questo bug risiede proprio nel processo speculativo del processore. In pratica, si fa in modo che un determinato programma, includa tutta una serie di istruzioni che portano il processore a prevedere di dover eseguire delle istruzioni malevole, che portano ad un programma della user area ad interagire direttamente con la kernel area, cosa che è assolutamente proibita, in teoria. Questo set di istruzioni predetto, al momento del controllo, per un determinato valore, viene verificato e viene quindi eseguito. A questo punto è possibile arrivare a controllare il kernel. Quindi controllando il kernel, che è l’elemento di controllo e di tramite tra l’hardware e il software, è possibile controllare l’intero sistema.
Per una spiegazione tecnica e per capire quali set di istruzioni portano a sfruttare tale falla di sicurezza, consiglio di leggere la pagina documentativa del bug pubblicata direttamente da Google Project Zero.
Chi viene colpito da questo bug?
Dicevamo che il bug colpisce le CPU. Quindi il problema è rivolto a tutti i sistemi operativi mobile e desktop. Tutti nessuno escluso. Linux, Windows, Mac, Android. Tutti, proprio tutti.
Quale soluzione si deve adottare?
Questo bug non ha ancora portato alla luce nessun exploit (chiamiamolo malware per semplificare, anche se non è proprio corretto). Di conseguenza, non è ancora una minaccia. Ma potrebbe diventarlo veramente a breve. Per questo motivo si deve trovare una soluzione.
La soluzione ideale sarebbe senza dubbio rifare i processori. Ma ovviamente questo non è possibile, dato che non si possono cambiare i processori già installati nei computer. Di conseguenza, l’unico modo è che il kernel e quindi i sistemi operativi si adeguino.
La soluzione che è stata trovata si chiama Kernel page-table isolation.
Questa soluzione prevede in pratica che venga isolato il kernel e reso invisibile dalla user area. In pratica dalla user area non si può più vedere il kernel, le sue locazioni di memoria (nella ram).
Per nascondere le posizioni di memoria, l’unico modo è cancellare ogni volta tutti gli indirizzi di memoria del kernel. Questo fa si che ok si riesce a nascondere la posizione stessa del kernel, dato che non è più possibile senza gli indirizzi, sapere dove esso è memorizzato. Ma allo stesso tempo fa si che ogni volta che il processore deve effettuare un’operazione, deve ricreare tutti gli indirizzi (cercando in tutte le celle), per eseguire il processo, per poi cancellare nuovamente tutto.
Questo causa una perdita di tempo immane. Quindi le prestazioni normali di un processore possono calare fino al 30%. Una botta veramente enorme per tutti i processori vecchi, che già sono lenti, diventano ancora più lenti. Ovviamente questa è una soluzione temporanea. Infatti dalle prossime generazioni di processori che usciranno, verrà effettuato il fix a livello hardware e quindi la Kernel page-table isolation non sarà più necessaria.
Ovviamente questa perdita la si ha solo quando viene aperto un nuovo processo o durante l’esecuzione di processi particolari. Quindi non si verifica alcuna perdita quando un processo è attivo, in quanto è già attivo, ha già ricevuto le sue locazioni di memoria e i suoi indirizzi e di conseguenza non c’è bisogno di isolare il kernel per protezione. La perdita prestazionale la si ha solo durante l’apertura di un nuovo processo o di un set di processi.
I processori AMD risentono meno di questo problema, anche perché sono processori che non accedono direttamente alla memoria, quindi anche se questo bug esiste, non rappresenta un problema così grande. Ovviamente anche per queste tipologie di CPU è necessario un fix, prima software, poi dalle prossime generazioni un fix hardware, per preventivare il problema, dato che è più comune nelle CPU AMD di qualche generazione precedente. In ogni caso, questo fix non causa un enorme rallentamento del rendimento della CPU, come invece accade per i processori Intel, appena trattati.
Il fix è stato rilasciato per i sistemi operativi Windows (10, 8.1, 8, 7), iOS (11.2), Android (con una patch Google) e diversi sistemi Linux. Su Linux possiamo trovare svariati sistemi non ancora coperti per colpa della frammentazione, che rende più difficoltoso l’applicazione di patch su larga scala.
Quindi
Questo è il bug che è presente attualmente nei processori intel. Spero che vi abbia spiegato al meglio il problema e spero che questo post vi sia piaciuto.
Se è così mi fa davvero molto piacere. Con questo è tutto… alla prossima!