Nella versione in sviluppo del kernel Linux 5.12 è stata inclusa l'implementazione del meccanismo KFence (Kernel Electric Fence), che controlla l'uso della memoria, intercettando gli accessi oltre i limiti dei buffer, gli accessi alla memoria dopo il rilascio e altri errori simili.
Questa funzionalità era già presente nel kernel come opzione di compilazione KASAN (kernel address sanitizer, utilizza Address Sanitizer nelle moderne gcc e clang) - tuttavia era principalmente progettata per l'uso in fase di debug. Il sottosistema KFence si distingue da KASAN per l'alta velocità operativa, consentendo così di utilizzare questa funzionalità anche su kernel in sistemi operativi in produzione.
L'implementazione su sistemi operativi in produzione consentirà di rilevare errori di gestione della memoria che non si manifestano in esecuzioni di test e che emergono solo sotto carichi operativi o durante un funzionamento prolungato (con un lungo uptime). Inoltre, l'uso di KFence su sistemi operativi in produzione permetterà di aumentare notevolmente il numero di macchine coinvolte nel controllo del funzionamento del kernel con la memoria.
Le spese generali minime, indipendenti dal carico, sono raggiunte in KFence grazie all'inserimento di pagine di protezione (guard pages) nella memoria heap a intervalli fissi. Al termine di ciascun intervallo di protezione, KFence attraverso il sistema di allocazione della memoria standard (allocatore SLAB o SLUB) aggiunge una nuova pagina di protezione dal pool di oggetti KFence e avvia un nuovo conteggio del tempo. Ogni oggetto KFence è collocato in una pagina di memoria separata, e le pagine di memoria ai bordi sinistro e destro formano pagine di protezione (guard pages), la cui dimensione è scelta casualmente.
In questo modo, le pagine con oggetti sono separate da pagine di protezione, le quali sono configurate per generare "page fault" ad ogni accesso. Per rilevare le operazioni di scrittura oltre il limite del buffer all'interno delle pagine con oggetti si utilizzano inoltre "zone rosse" basate su modelli, che occupano memoria non utilizzata dagli oggetti, rimanente a causa dell'allineamento delle dimensioni delle pagine di memoria. —+————+————+————+————+————+— | xxxxxxxxx | O : | xxxxxxxxx | : O | xxxxxxxxx | | xxxxxxxxx | B : | xxxxxxxxx | : B | xxxxxxxxx | | x GUARD x | J : RED- | x GUARD x | RED- : J | x GUARD x | | xxxxxxxxx | E : ZONE | xxxxxxxxx | ZONE : E | xxxxxxxxx | | xxxxxxxxx | C : | xxxxxxxxx | : C | xxxxxxxxx | | xxxxxxxxx | T : | xxxxxxxxx | : T | xxxxxxxxx | —+————+————+————+————+————+—
In caso di tentativo di accesso a un'area al di fuori dei confini del buffer, l'operazione coinvolge la pagina di protezione, il che porta alla generazione di un «page fault», che viene intercettato da KFence e registra nel log i dati relativi al problema rilevato. Di default, KFence non blocca l'errore e fornisce solo un avviso nel log, ma è disponibile una configurazione «panic_on_warn», che consente di mettere il kernel in uno stato di crash (panic) in caso di errore.
Fonte: opennet.ru
