È stato rilevato un overflow dello stack da hardware o software?


26

È compito del software (sistema operativo) rilevare overflow dello stack o viene rilevato un overflow dello stack nell'hardware, causando un'eccezione nella CPU?


Direi hardware, attraverso errori MMU sulla maggior parte delle CPU. x86 in modalità 32 bit aveva una segmentazione oltre al paging e il "Stack Segment" è associato, come i segmenti Code, Data, Ext ... sia con un indirizzo base che con una dimensione. Qualsiasi accesso al di fuori di tale intervallo provocherebbe un errore.
TEMLIB,

Risposte:


25

Può essere software, hardware o entrambi o nessuno.

Esistono due tipi di overflow: overflow quando si cresce lo stack (quando si immette una funzione) e overflow quando si accede a un array nello stack. Gli overflow durante la crescita dello stack possono essere rilevati effettuando un controllo dei limiti sull'ingresso della funzione, per verificare che vi sia spazio sufficiente (e segnalare un errore o aumentare lo stack se non lo è). Gli overflow quando si accede a un array nello stack sono solo un problema in linguaggi di basso livello che non verificano i limiti dell'array; la soluzione è quella di verificare i limiti dell'array.

Questi approcci software hanno il vantaggio di funzionare in modo completamente affidabile: si può essere certi che verrà rilevato qualsiasi overflow dello stack. Il loro aspetto negativo è che aumentano la dimensione del codice e il tempo di esecuzione. L'hardware può aiutare fornendo un metodo per rilevare la maggior parte degli overflow senza alcun costo, purché non si verifichino overflow. Su un'architettura con una MMU ¹, l'ambiente di runtime può disporre di mappare lo stack su un limite di pagina, con la pagina successiva non mappata.

+---------------+---------------+---------------+---------------+
| stack                         | unmapped      | other stuff   |
|    ----> direction of growth  |               |               |
+---------------+---------------+---------------+---------------+
^               ^               ^               ^               ^  page boundaries

In questo modo, se il software tenta di accedere ai dati oltre il limite della pagina (sia perché il puntatore dello stack si è spostato oltre il limite o perché l'accesso dell'array è fuori dai limiti e oltre il limite), causerà un errore accedendo ad un'area non mappata . Questo succede solo se l'overflow è abbastanza piccolo: se la quantità di overflow è troppo grande, il programma potrebbe finire per accedere ad altre cose dall'altra parte del gap nello spazio degli indirizzi.

Gli aspetti negativi dell'approccio hardware sono che non è completamente affidabile poiché un overflow di una grande quantità potrebbe non essere rilevato e che non rileva overflow dell'array che rimangono all'interno dello spazio indirizzabile.

Per rilevare overflow di array, un'altra tecnica software è un canarino : inserire un valore speciale nella parte superiore dello stack o tra i frame e verificare che il valore canary non sia cambiato al ritorno della funzione. Questa è anche una tecnica imperfetta poiché l'overflow potrebbe evitare del tutto il canarino o potrebbe non essere rilevato perché il valore del canarino è stato ripristinato al momento della verifica. Tuttavia, è utile rendere più difficile lo sfruttamento di alcune vulnerabilità di sicurezza.

Il modo più sicuro ed economico per evitare overflow dello stack è calcolare la quantità di stack di cui il programma avrà bisogno prima di iniziare a eseguirlo, mediante analisi statica. Tuttavia, ciò non è sempre pratico: la quantità di stack necessaria a un programma è in generale non determinabile e dipende dai dati manipolati dal programma.

¹ Lo stesso principio può essere applicato anche con una sola MPU o senza protezione della memoria se esiste un singolo thread il cui stack si trova ai margini delle mappature fisiche esistenti.


4
Non chiamerei un array fuori limite l'accesso a uno stack overflow, anche se l'array si trova nello stack. È solo un caso speciale di overflow del buffer.
CodesInChaos,

La mancata allocazione agli elementi dello stack primario a cui fa riferimento un puntatore non stack / frame o offset non costante eviterebbe gli overflow tradizionali dello stack. L'uso di uno stack di indirizzi di ritorno separato (o stack di spargimento di RA / register come Itanium) ridurrebbe almeno notevolmente le opportunità di programmazione orientate al ritorno.
Paul A. Clayton,

L'accesso fuori limite è più propriamente chiamato overrun , non overflow.
Ben Voigt,

3
@ awesomebing1 non tutte le piattaforme rilevano overflow dello stack. Potresti semplicemente finire per sovrascrivere qualunque cosa sia dopo lo stack (simile a qualsiasi altro buffer overflow).
user253751

1
@CodesInChaos, a volte gli overflow del buffer nei buffer allocati nello stack sono chiamati "overflow dello stack" (in breve). Certo, quella terminologia può essere un po 'confusa senza contesto.
DW
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.