¿Es posible leer la memoria de otro programa asignando todo el espacio vacío en un sistema?

26

Teóricamente, si tuviera que construir un programa que asignara toda la memoria no utilizada en un sistema y continuara solicitando más y más memoria a medida que otras aplicaciones liberan memoria que ya no necesitan, ¿sería posible leer la memoria recientemente liberada de otras aplicaciones? ? ¿O está de alguna manera protegido por el sistema operativo moderno?

No tengo una aplicación práctica para esto, solo tengo curiosidad. Me doy cuenta de que hay algunos problemas con la asignación de "toda la memoria disponible" en la vida real.

Editar: para aclarar, estoy preguntando específicamente sobre la memoria "Liberada", no para acceder a la memoria que actualmente está asignada por otra aplicación.

CondiciónRacer
fuente

Respuestas:

23

No, porque un buen kernel borra el contenido de la memoria antes de enviarlo a un proceso para protegerlo exactamente del tipo de ataque que usted propone.

En los sistemas Unixy, la memoria se asigna a los procesos al extender lo que se denomina interrupción del programa , que es el límite del espacio prácticamente direccionable que un proceso puede usar. Un proceso le dice al kernel que quiere extender su espacio direccionable, y el kernel lo permitirá si hay memoria disponible o la llamada fallará si no. (El nombre de la brk()llamada al sistema proviene de este concepto).

En la práctica, los bloques grandes de memoria liberada no suelen coincidir con el corte del programa, que es lo que se necesitaría para que un proceso devuelva la memoria al núcleo al reducir el corte del programa. Esto, por supuesto, depende de la implementación de malloc()y de su sistema free(). Si tiene fuentes disponibles, le dirán si alguna vez se devuelve la memoria.

No hay implicaciones de seguridad para malloc()no inicializar la memoria porque todo lo que recibió brk()se habrá borrado y todo lo anterior free()se habrá escrito por el mismo proceso.

Blrfl
fuente
19

Sí, teóricamente es posible leer la memoria liberada de otro proceso. Fue la fuente de una serie de ataques de escalada de privilegios en el pasado. Debido a eso, los sistemas operativos hoy en día ponen a cero la memoria si fue asignada previamente por otro proceso. La razón por la que no siempre ve la memoria puesta a cero es porque es más eficiente no poner a cero la memoria si previamente fue asignada por el mismo proceso. El sistema operativo intenta devolver páginas de memoria al mismo proceso si puede.

Karl Bielefeldt
fuente
1
"Sí pero no" es "no". @Blrfl tiene razón.
Ross Patterson
44
@RossPatterson: En el punto teórico, Karl tiene más razón que yo. La realidad práctica es que los sistemas operativos convencionales cerraron ese agujero hace años.
Blrfl
@Blrfl Entendido. Pero "hace años" fue a fines de la década de 1960, cuando se introdujeron por primera vez los sistemas de paginación y la memoria virtual. Ciertamente, para la época de Multics, VM / 370 y OS / VS. Ausencia de errores, esto no ha sido posible en la memoria de la mayoría de los programadores practicantes.
Ross Patterson el
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 Veo algunas inconsistencias aquí. ¿Quiso decir "mismo ejecutable"? ¿Cómo se verifica si la ruta del disco no se pone a cero?
jakub.g
1
Creo que me estoy perdiendo algo. ¿Por qué entonces, cuando compilo y ejecuto algún programa de C ++ con, por ejemplo, enteros sin inicializar, no son iguales a 0 cuando leo esas variables?
jakub.g
2

Aquí hay varias capas involucradas que afectan la respuesta.

Si asume un sistema operativo de memoria virtual moderno, no podrá ver los restos de los datos de otros procesos en las páginas que asigne.

Cuando se carga un proceso por primera vez, se carga la tabla de páginas y potencialmente se asignan marcos de memoria real a esas páginas. Como mínimo, la tabla de páginas o su tabla complementaria contendrá un mapa de toda la memoria que el proceso puede asignar. Aquí también se establece la interrupción inicial del proceso, mencionada anteriormente.

Si bien malloc () puede, si se permite el proceso, hacer que cambie el salto del proceso, agregando más páginas a una tabla de página de procesos (página suplementaria) para satisfacer la solicitud, el lugar donde un proceso puede "obtener otro" datos de procesos es La capa de memoria real inferior.

En ambos escenarios, un sistema operativo moderno que utiliza paginación de demanda o asignación diferida, todavía no está asignando memoria física (marcos). El sistema operativo simplemente "toma notas" sobre qué memoria virtual para ese proceso se considera válida. La memoria real se asigna solo cuando es necesario.

La memoria física o los marcos se asignan a un proceso cuando la página virtual se realiza y se mapea en una tabla de página de procesos Aquí es donde existe el potencial de exposición de datos. Esto sucede durante un fallo de página. La exposición se debe a que un proceso anterior puede haber estado usando ese mismo marco y sus datos fueron abandonados o intercambiados, para dejar espacio para la solicitud de memoria física actual. El sistema operativo debe tener cuidado para garantizar que los datos de los procesos solicitantes se intercambien correctamente o que el marco se borre (ponga a cero) antes de reanudar el proceso. Esto también se menciona anteriormente como un problema "antiguo pero resuelto".

Esto hace que sea algo irrelevante si la memoria de otros procesos fue "liberada" o no. La memoria "liberada" de otros procesos aún reside en las páginas asignadas a ese proceso y, por lo general, no se asignan hasta que finaliza el proceso, ya que simplemente se intercambiarán cuando la memoria sea baja o se desalojen de otro modo. malloc () y free () administran la memoria virtual asignada al proceso en el nivel (usuario).

En su pregunta, su proceso, continúa solicitando más y más memoria, en teoría, eliminando todos los demás procesos de la memoria. En realidad, existen estrategias de asignación de marcos, globales y locales, que también pueden afectar la respuesta. Es muy probable que el proceso obligue a sus propias páginas a quedarse sin memoria antes de permitir que se sobrepase el sistema operativo y todos los demás procesos. Aunque esto va más allá de tu pregunta inicial.

Todo esto es discutible en un sistema como MS-DOS. MS-DOS (y otros sistemas más simples) no usan memoria virtual (por sí mismos) y usted podría fácilmente pinchar y pinchar en otros datos de "procesos".

Algunas buenas referencias, que pueden ser más fáciles de entender que el código fuente de Linux, serían un buen libro de texto de sistemas operativos, Conceptos de sistemas operativos de Silberscatz, Gavin y Gange, o Diseño de sistemas operativos de Andrew Tanenbaum. También algo como Nachos de Berkeley o Pintos de Stanford son pequeños sistemas operativos creados para el aprendizaje y tienen estas mismas ideas dentro de ellos.

0xACE
fuente
0

Probé esto en Ubuntu hace 16.04 meses. Tal como dijo 0xACE, el sistema operativo moderno asigna una página virtual completa a cero una vez que llamó a malloc (). Pero, si no escribe nada en el búfer asignado, no se asignará a la memoria física (es decir, principio de copia en escritura), por lo que siempre leerá ceros desde un bloque "no inicializado". Tal vez hay un sistema operativo integrado compilado con la opción "CONFIG_MMAP_ALLOW_UNITIALIZED" para un mejor rendimiento, en este caso, podría obtener lo que expiró.

weir007
fuente
-1

No, esto no permitirá que otro programa lea la memoria de otro gracias a la magia de la paginación . De esta forma, el uso total de la memoria puede exceder el RAM físico descargando partes del mismo en el disco duro.

Además, la memoria máxima que un proceso puede asignar está limitada arbitrariamente por el sistema operativo (hasta 4 gigas para una arquitectura de 32 bits) después de lo cual la próxima allocllamada devolverá un error de memoria insuficiente.

monstruo de trinquete
fuente
¿No hay API específicas de la plataforma que puedan evitar esto? Sinceramente, no lo sé, pero no me sorprendería (por ejemplo, Linux permite evitar que el sistema operativo mueva una página de la memoria física, a través de mlock).
Si hay 4 GB de RAM y la paginación está limitada a 8 GB, ¿qué sucede si la aplicación solicita 12 GB (en un x64)?
Arseni Mourzenko
entonces las llamadas del sistema deberían devolver un error cuando queda muy poca memoria libre, o la computadora simplemente se detendrá cuando no quede nada ...
Ratchet freak
44
No está preguntando acerca de leer la memoria de otro, sino más bien leer su memoria LIBERADA. Esa sección de ram es actualmente gratuita, y ... No creo ... que los esquemas de paginación cero memoria después de que se libera. Entonces el programa asignaría un bloque de memoria y analizaría los datos no inicializados que ya están allí.
Philip
@philip correcto, estoy preguntando específicamente sobre la memoria liberada.
ConditionRacer