È possibile leggere la memoria da un altro programma allocando tutto lo spazio vuoto su un sistema?


26

Teoricamente, se dovessi costruire un programma che allocasse tutta la memoria inutilizzata su un sistema e continuasse a richiedere sempre più memoria poiché altre applicazioni rilasciavano la memoria di cui non avevano più bisogno, sarebbe possibile leggere la memoria rilasciata di recente da altre applicazioni ? O questo è in qualche modo protetto dal moderno sistema operativo?

Non ho un'applicazione pratica per questo, sono solo curioso. Mi rendo conto che ci sono alcuni problemi con l'allocazione di "tutta la memoria disponibile" nella vita reale.

Modifica: per chiarire, chiedo in particolare la memoria "Rilasciata", non l'accesso alla memoria che è attualmente allocata da un'altra applicazione.

Risposte:


23

No, perché un buon kernel cancella il contenuto della memoria prima che venga inviato a un processo per proteggersi esattamente dal tipo di attacco che proponi.

Sui sistemi Unixy, la memoria viene allocata ai processi estendendo quella che viene chiamata interruzione del programma , che è il limite dello spazio virtualmente indirizzabile che un processo può usare. Un processo dice al kernel che vuole estendere il suo spazio indirizzabile, e il kernel lo permetterà se la memoria è disponibile o la chiamata fallirà in caso contrario. (Il nome della brk()chiamata di sistema deriva da questo concetto.)

In pratica, grandi blocchi di memoria liberata spesso non si scontrano con l'interruzione del programma, che è ciò che sarebbe necessario per un processo per restituire memoria al kernel riducendo l'interruzione del programma. Ciò dipende ovviamente dall'implementazione di malloc()e free(). Se disponi di fonti disponibili, ti diranno se la memoria viene mai restituita.

Non ci sono implicazioni di sicurezza per malloc()non inizializzare la memoria perché tutto ciò che ha ottenuto brk()sarà stato cancellato e tutto ciò che in precedenza free()sarebbe stato scritto dallo stesso processo.


19

Sì, è teoricamente possibile leggere la memoria rilasciata di un altro processo. Era la fonte di numerosi attacchi di escalation di privilegi nel corso della giornata. Per questo motivo, al giorno d'oggi i sistemi operativi effettivamente azzerano la memoria se era stata precedentemente allocata da un altro processo. Il motivo per cui non si vede sempre l'azzeramento della memoria è perché è più efficiente non azzerare la memoria se è stata precedentemente allocata dallo stesso processo. Il sistema operativo tenta di restituire le pagine di memoria allo stesso processo, se possibile.


1
"Sì ma no" è "no". @Blrfl ha ragione.
Ross Patterson,

4
@RossPatterson: sul punto teorico, Karl ha effettivamente più ragione di me. La realtà pratica è che i sistemi operativi tradizionali hanno chiuso quel buco anni fa.
Blrfl,

@Blrfl Capito. Ma "anni fa" era alla fine degli anni '60, quando furono introdotti per la prima volta sistemi di paging e memoria virtuale. Certamente al tempo di Multics, VM / 370 e OS / VS. Assenti bug, questo non è stato possibile nella memoria della maggior parte dei programmatori professionisti.
Ross Patterson,

The reason you don't always see zeroed out memory is because it is more efficient not to zero out the memory if it was previously allocated by the same process Vedo qualche incoerenza qui. Intendevi "stesso eseguibile"? Come viene verificato se non azzerare - dal percorso del disco?
jakub.g

1
Penso che mi manchi qualcosa. Perché allora, quando compilo ed eseguo un programma C ++ con, per esempio, numeri interi non inizializzati, non sono uguali a 0 quando leggo quelle variabili?
jakub.g

2

Ci sono diversi livelli coinvolti qui che influenzano la risposta.

Se si assume un moderno sistema operativo di memoria virtuale, non sarà possibile visualizzare i resti di un altro processo dati nelle pagine allocate.

Quando un processo viene caricato per la prima volta, viene caricata la tabella delle pagine e potenzialmente vengono allocati frame di memoria reale a tali pagine. Come minimo, la tabella delle pagine o la sua tabella supplementare, conterrà una mappa di tutta la memoria che il processo può allocare. Questo è anche il punto in cui viene impostata l'interruzione iniziale del processo, menzionata sopra.

Mentre malloc () può, se il processo è consentito, causare l'interruzione del processo, aggiungendo più pagine alla tabella di una pagina di processi (pagina supplementare) per soddisfare la richiesta, il punto in cui un processo può "ottenere un altro" dati sui processi è in il livello di memoria reale inferiore.

In entrambi questi scenari un moderno sistema operativo che utilizza il paging della domanda, o allocazione lazy, non sta ancora allocando memoria fisica (frame). Il sistema operativo sta semplicemente "prendendo appunti" su quale memoria virtuale per quel processo è considerata valida. La memoria effettiva viene assegnata solo quando necessario.

La memoria fisica o i frame vengono allocati a un processo quando la pagina virtuale viene realizzata e mappata in una tabella della pagina dei processi Qui esiste il potenziale per l'esposizione dei dati. Questo accade durante un errore di pagina. L'esposizione è dovuta al fatto che un processo precedente potrebbe aver utilizzato lo stesso frame e che i suoi dati sono stati abbandonati o scambiati, per fare spazio all'attuale richiesta di memoria fisica. Il sistema operativo deve fare attenzione a garantire che i dati dei processi richiesti vengano scambiati correttamente o che il frame venga cancellato (azzerato) prima di riprendere il processo. Questo è anche menzionato sopra come un problema "vecchio ma risolto".

Ciò rende in qualche modo irrilevante se la memoria degli altri processi è stata "rilasciata" o meno. Un altro processo di memoria "liberata" risiede ancora nelle pagine assegnate a quel processo e di solito non viene decompresso fino a quando il processo non termina poiché verranno scambiati quando la memoria si esaurisce o vengono altrimenti sfrattati. malloc () e free () gestiscono la memoria virtuale assegnata al processo a livello (utente).

Nella tua domanda, il tuo processo continua a richiedere sempre più memoria, in teoria, spingendo tutti gli altri processi fuori dalla memoria. In realtà, esistono strategie di allocazione dei frame - globali e locali - che possono influenzare anche la risposta. È altrettanto probabile che il processo forzerà la memoria delle proprie pagine prima che sia autorizzato a sovraccaricare il sistema operativo e tutti gli altri processi. Anche se questo va oltre la tua domanda iniziale.

Tutto questo è discutibile in un sistema come MS-DOS. MS-DOS (e altri sistemi più semplici) non usano la memoria virtuale (da soli) e si potrebbe facilmente cercare e stimolare altri dati "process".

Alcuni buoni riferimenti, che potrebbero essere più facili da comprendere rispetto al codice sorgente di Linux, sarebbero un buon libro di testo sui sistemi operativi, Concetti sui sistemi operativi di Silberscatz, Gavin e Gange, o Sistemi operativi progettati da Andrew Tanenbaum. Anche qualcosa come Nachos di Berkeley o Pintos di Stanford sono piccoli sistemi operativi creati per l'apprendimento e hanno le stesse idee al loro interno.


0

L'ho provato su Ubuntu 16.04 mesi fa. Proprio come ha detto 0xACE, il sistema operativo moderno alloca una pagina virtuale completamente zero una volta che hai chiamato malloc (). Ma, se non si scrive nulla nel buffer allocato, non verrà mappato nella memoria fisica (ovvero, principio di copia su scrittura), quindi si leggeranno sempre zeri da un blocco "non inizializzato". Forse ci sono alcuni sistemi operativi integrati compilati con l'opzione "CONFIG_MMAP_ALLOW_UNITIALIZED" per prestazioni migliori, in questo caso potresti ottenere ciò che ti aspettavi.


-1

No, ciò non consentirà a un altro programma di leggere la memoria di un altro grazie alla magia del paging . In questo modo, l'utilizzo totale della memoria può superare il RAM fisico scaricando parti di esso sul disco rigido.

Inoltre, la memoria massima che un processo può allocare è arbitrariamente limitata dal sistema operativo (fino a 4 concerti per un'architettura a 32 bit), dopodiché la allocchiamata successiva restituirà un errore di memoria esaurita.


Non ci sono API specifiche della piattaforma che possono aggirare questo? Onestamente non lo so, ma non sarei sorpreso (ad esempio, Linux consente di impedire al sistema operativo di spostare una pagina dalla memoria fisica, tramite mlock).

Se ci sono 4 GB di RAM e il paging è limitato a 8 GB, cosa succede se l'applicazione richiede 12 GB (su un x64)?
Arseni Mourzenko,

poi le chiamate di sistema dovrebbero restituire un errore quando la memoria troppo poco libera rimarrà, che o il computer semplicemente fermerebbe quando non c'è alcuna sinistra ...
cricchetto maniaco

4
Non sta chiedendo di leggere la memoria di un altro, ma piuttosto di leggere la loro memoria RILASCIATA. Quella sezione di ram è attualmente libera, e ... non credo ... che gli schemi di paging azzerino la memoria dopo che è stata liberata. Quindi il programma allocarebbe un blocco di memoria e analizzerebbe i dati non inizializzati già presenti.
Philip

@philip corretto, sto chiedendo specificamente sulla memoria rilasciata.
ConditionRacer
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.