Mi chiedo se qualcuno abbia precedentemente proposto, valutato o implementato la seguente misura per rafforzare i sistemi contro sovraccarichi di buffer basati su heap: fondamentalmente, stack di canarini, ma applicati prima dei puntatori di funzione negli oggetti memorizzati nell'heap piuttosto che prima del ritorno indirizzi memorizzati nello stack.
Considera una struttura come
struct whatever {
int blah;
char buf[256];
void (*fp)(); // a function pointer
}
Notare che se c'è un sovraccarico che scrive oltre la fine del campo buf
, sarà possibile sovrascrivere il campo del puntatore della funzione fp
.
Un compilatore potrebbe plausibilmente difendersi introducendo un canarino - un valore casuale segreto - memorizzato tra il buffer e il puntatore della funzione. Fondamentalmente, il compilatore trasformerebbe il layout della struttura in
struct whatever {
int blah;
char buf[256];
unsigned int canary; // inserted by compiler; not exposed to source code
void (*fp)(); // a function pointer
}
Ad esempio, il compilatore potrebbe organizzare la scrittura del campo canary
con un valore segreto globale ogni volta che il programma scrive su fp
, e potrebbe verificare che il valore di canary
rimanga invariato ogni volta che il programma legge da fp
.
Questo è fondamentalmente l'analogo dei canarini dello stack, ma dove ora ci concentriamo sulla protezione dei puntatori di funzione nell'heap invece degli indirizzi di ritorno nello stack. Sembra un'idea naturale.
Qualcuno ha proposto questo prima? Qualcuno ha prototipato o valutato il costo delle prestazioni di fare qualcosa del genere? Esistono ostacoli non evidenti alla distribuzione (oltre al fatto che richiede modifiche ai compilatori, proprio come fanno i canarini)?
Ricerca che ho fatto: sono a conoscenza dell'idea di inserire le pagine di protezione tra gli oggetti nell'heap, ma è diverso (protegge da overflow di heap che vanno oltre i limiti di un singolo oggetto, mentre sto parlando su qualcosa da proteggere dagli overflow dell'heap che rimangono all'interno dell'area di un singolo oggetto heap). Ho familiarità con Cruiser e ContraPolice , che posiziona i canarini tra gli oggetti nell'heap, ma che si focalizza anche sugli overflow degli oggetti incrociati piuttosto che sugli overflow degli oggetti interni. Ho anche familiarità con l'uso dei canarini dello stack o con la crittografia puntatore per proteggere i metadati di malloc, ma, ancora una volta, non protegge contro gli overflow degli oggetti e serve a proteggere i metadati di malloc piuttosto che i puntatori di funzione.