Esiste un modo migliore dell'analisi / proc / self / maps per capire la protezione della memoria?
-
06-07-2019 - |
Domanda
Su Linux (o Solaris) esiste un modo migliore dell'analisi manuale ripetuta di / proc / self / maps
per capire se è possibile leggere, scrivere o eseguire ciò che è memorizzato in uno o più indirizzi in memoria?
Ad esempio, in Windows hai VirtualQuery
.
In Linux, posso mprotect
per cambiare quei valori, ma non riesco a rileggerli.
Inoltre, c'è un modo per sapere quando cambiano quelle autorizzazioni (ad esempio quando qualcuno usa mmap
su un file dietro la mia schiena) oltre a fare qualcosa di terribilmente invasivo e usare ptrace
su tutti i thread del processo e intercettare qualsiasi tentativo di creare un syscall
che potrebbe influenzare la mappa di memoria?
Aggiornamento:
Sfortunatamente, sto usando questo all'interno di una JIT che ha pochissime informazioni sul codice che sta eseguendo per ottenere un'approssimazione di ciò che è costante. Sì, mi rendo conto che potrei avere una mappa costante di dati mutabili, come la pagina vsyscall utilizzata da Linux. posso ripiegare in sicurezza supponendo che tutto ciò che non è incluso nell'analisi iniziale sia mutabile e pericoloso, ma non sono del tutto soddisfatto di questa opzione.
In questo momento, quello che faccio è leggere / proc / self / maps
e costruire una struttura attraverso la quale posso cercare binariamente la protezione di un determinato indirizzo. Ogni volta che ho bisogno di sapere qualcosa su una pagina che non è nella mia struttura rileggo / proc / self / maps supponendo che sia stata aggiunta nel frattempo o che stavo per segfault comunque.
Sembra proprio che l'analisi del testo per ottenere queste informazioni e non sapere quando cambia sia terribilmente croccante. ( / dev / inotify
non funziona praticamente su nulla in / proc
)
Soluzione
Non conosco un equivalente di VirtualQuery
su Linux. Ma alcuni altri modi per farlo che possono o meno funzionare sono:
-
si imposta un gestore di segnale che intrappola SIGBUS / SIGSEGV e si procede con la lettura o la scrittura. Se la memoria è protetta, verrà chiamato il codice di trapping del segnale. In caso contrario, il codice di trapping del segnale non viene chiamato. Ad ogni modo, vinci.
-
puoi tracciare ogni volta che chiami
mprotect
e costruisci una struttura dati corrispondente che ti aiuti a sapere se una regione è protetta da lettura o scrittura. Questo è utile se hai accesso a tutto il codice che utilizzamprotect
. -
puoi monitorare tutte le chiamate
mprotect
nel tuo processo collegando il tuo codice con una libreria che ridefinisce la funzionemprotect
. È quindi possibile creare la struttura di dati necessaria per sapere se una regione è protetta da lettura o scrittura e quindi chiamare il sistemamprotect
per impostare davvero la protezione. -
puoi provare a usare
/ dev / inotify
e monitorare il file/ proc / self / maps
per qualsiasi modifica. Immagino che questo non funzioni, ma dovrebbe valerne la pena.
Altri suggerimenti
Esiste una sorta di / was / proc / [pid | self] / pagemap, documentazione nel kernel, avvertenze qui: https://lkml.org/lkml/2015/7/14/477 Quindi non è del tutto innocuo ...