2010-08-09 12 views
5

Mi chiedo se c'è un modo per proteggere da scrittura ogni pagina in uno spazio di indirizzi del processo Linux (dall'interno del processo stesso, tramite mprotect()). Per "ogni pagina", intendo davvero ogni pagina dello spazio di indirizzamento del processo che potrebbe essere scritta da un normale programma in esecuzione in modalità utente - quindi, il testo del programma, le costanti, le globali e l'heap - - ma sarei felice con solo costanti, globals e heap. Non voglio proteggere da scrittura lo stack - che sembra una cattiva idea.Posso proteggere da scrittura ogni pagina nello spazio degli indirizzi di un processo Linux?

Un problema è che non so da dove iniziare la protezione di scrittura . Guardando a /proc/pid/maps, che mostra le sezioni della memoria in uso per un dato pid, sembrano sempre iniziare con l'indirizzo 0x08048000, con il testo del programma. (In Linux, per quanto posso dire, la memoria di un processo è presentata con il testo del programma sul fondo , quindi le costanti sopra quella, quindi le globali, quindi l'heap, quindi uno spazio vuoto di dimensioni variabili a seconda sulla dimensione dello stack o dello stack e quindi lo stack crescente dalla parte superiore della memoria all'indirizzo virtuale 0xffffffff.) C'è un modo per indicare dove si trova la parte superiore dello heap (chiamando sbrk(0), che restituisce semplicemente un puntatore alla "pausa" corrente , ovvero la parte superiore dell'heap), ma non in realtà un modo per dire a dove inizia l'heap.

Se provo a proteggere tutte le pagine da 0x08048000 fino all'interruzione, I alla fine ottengo un errore mprotect: Cannot allocate memory. Non so perché mprotect sarebbe allocando comunque memoria, e Google non è molto utile. Qualche idea?

Tra l'altro, il motivo che voglio fare questo è perché voglio creare un elenco di tutte le pagine che vengono scritti durante una corsa del programma , e il modo in cui posso pensare di fare questo è di proteggere da scrittura tutte le pagine, lasciare che qualsiasi tentativo di scrittura causi un errore di scrittura, quindi implementare un gestore di errori di scrittura che aggiungerà la pagina all'elenco e quindi rimuovere la protezione di scrittura . Penso di sapere come implementare il gestore, se solo potessi capire quali pagine proteggere e come farlo.

Grazie!

+1

In realtà ho già un codice che fa esattamente quello che stai cercando di fare. La tua idea funzionerà, ma non puoi proteggere le pagine in cui risiedono le tue liste "queste pagine scritte", o il tuo gestore SEGV causerà un SEGV! – Borealid

+0

@Borealid, grazie, e questo è ora il problema che sto cercando di risolvere (ho il gestore segfault e l'analisi/proc/self/maps che funziona ora). Come evitare di proteggere le pagine che contengono quell'elenco? L'assegnazione della lista sullo stack funzionerebbe, ma poi non vedo alcun modo per passarlo al gestore. In alternativa, potrei allocarlo come globale, ma mi piacerebbe utilizzare una struttura dati più elaborata di una matrice a lunghezza fissa (come un contenitore STL) e potrei non sapere sempre dove si trova l'elenco che sto scrivendo in memoria. –

+0

@borealid: hai detto che hai codice che fa esattamente questo - ti dispiacerebbe condividere il tuo codice? Sono nuovo qui e non sono riuscito a trovare un modo per contattarti direttamente (back-channel). Sto cercando di fare esattamente ciò che sta facendo Linsey, quindi qualsiasi esempio di codice sarebbe molto utile. –

risposta

5

Si riceve ENOMEM da mprotect() se si tenta di chiamarlo su pagine che non sono mappate.

La soluzione migliore è aprire /proc/self/maps e leggerlo una riga alla volta con fgets() per trovare tutti i mapping nel processo.Per ogni mapping scrivibile (indicato nel secondo campo) che non è lo stack (indicato nell'ultimo campo), chiamare mprotect() con l'indirizzo di base e la lunghezza corretti (calcolati dagli indirizzi di inizio e di fine nel primo campo).

Nota che a questo punto sarà necessario impostare il gestore degli errori, poiché l'atto di leggere il file maps causerà probabilmente scritture all'interno dello spazio indirizzo.

+0

Grazie - Speravo che ci fosse un modo per aggirare le mappe/proc/auto/mappe, ma sembra che non ci sia (dalla discussione su http://stackoverflow.com/questions/269314/è-ci-a-parsing proc-self-mappe-meglio-modo-che-a-figure-out-memory-protectio). –

0

Inizio semplice. Proteggi da scrittura alcune pagine e assicurati che il tuo gestore di segnali funzioni per queste pagine. Quindi preoccuparsi di ampliare l'ambito della protezione. Per esempio, probabilmente non c'è bisogno di protezione da scrittura del codice sezione: i sistemi operativi possono implementare write-or-eseguire la semantica di protezione sulla memoria che impedirà sezioni di codice da sempre di essere scritta a:

+0

Sì, per questo problema non possiamo assumere per ora nessun codice auto-modificante. Sarei a posto sia con la protezione in scrittura della sezione di codice che non, a seconda di quale sia più semplice. –

+0

In realtà quello che stavo cercando di dire è che le sezioni del codice sono probabilmente già protette da scrittura. –

Problemi correlati