2010-08-09 12 views
5

Me pregunto si hay una forma de proteger contra escritura cada página en un espacio de direcciones de proceso Linux (desde el interior del proceso, a través de mprotect()). Por "cada página", me refiero a cada página del espacio de direcciones del proceso que podría escribirse en un programa ordinario ejecutándose en modo de usuario, por lo que el texto del programa, las constantes, las globales y el montón - - pero me gustaría con constantes, globales, y montón. No quiero proteger contra escritura la pila, que parece una mala idea.¿Puedo proteger contra escritura cada página en el espacio de direcciones de un proceso de Linux?

Un problema es que no sé por dónde empezar la memoria de protección contra escritura . Mirando /proc/pid/maps, que muestra las secciones de la memoria en uso para un pid dado, siempre parecen comenzar con la dirección 0x08048000, con el texto del programa. (En Linux, hasta donde puedo decir, la memoria de un proceso se presenta con el texto del programa en el inferior, luego constantes encima de eso, luego globales, luego el montón, luego un espacio vacío de tamaño variable dependiendo en el tamaño del montón o la pila , y luego la pila que crece desde la parte superior de la memoria en dirección virtual 0xffffffff.) Hay una manera de saber dónde está el montón (llamando al) llamando al sbrk(0), que simplemente devuelve un puntero al "ruptura" actual, es decir, la parte superior del montón), pero en realidad no es una forma de indicar dónde comienza el montón.

Si trato de proteger todas las páginas desde 0x08048000 hasta la ruptura, I finalmente obtiene un error mprotect: Cannot allocate memory. No sé por qué mprotect sería asignando memoria de todos modos, y Google no es muy útil. ¿Algunas ideas?

Por cierto, la razón por la que quiero hacer esto es porque quiero crear una lista de todas las páginas que se escriben durante una ejecución del programa y la forma en que puedo pensar para hacer esto es escribir-proteger todas las páginas, deje que cualquier intento de escritura cause un error de escritura, luego implemente un controlador de fallas de escritura que agregará la página a la lista y luego eliminará la protección de escritura . Creo que sé cómo implementar el controlador, si solo pudiera averiguar qué páginas proteger y cómo hacerlo.

Gracias!

+1

De hecho, ya tengo un código que hace exactamente lo que estás tratando de hacer. Su idea funcionará, pero no puede proteger las páginas en las que residen sus listas "these-pages-were-written", ¡o su manejador SEGV causará un SEGV! – Borealid

+0

@Borealid, gracias, y ese es ahora el problema que estoy tratando de resolver (tengo el controlador de segfault y el análisis de/proc/self/maps funcionando ahora). ¿Cómo evitar proteger las páginas que contienen esa lista? Asignar la lista en la pila funcionaría, pero luego no veo ninguna forma de pasarlo al controlador. Alternativamente, podría asignarlo como global, pero me gustaría utilizar una estructura de datos más elegante que una matriz de longitud fija (como un contenedor STL), y es posible que no siempre sepa dónde está ubicada la lista en la que estoy escribiendo en memoria. –

+0

@borealid: Dijiste que tienes un código que hace exactamente esto: ¿te importaría compartir tu código? Soy nuevo aquí, y no pude encontrar una manera de contactarlo (back-channel) directamente. Intento hacer exactamente lo que Linsey está haciendo, por lo que cualquier muestra de código sería muy útil. –

Respuesta

5

Recibe ENOMEM de mprotect() si intenta llamar en las páginas que no están asignadas.

Su mejor opción es abrir /proc/self/maps, y léelo línea por línea con fgets() para encontrar todas las asignaciones en su proceso.Para cada mapeo escribible (indicado en el segundo campo) que no es la pila (indicado en el último campo), llame al mprotect() con la dirección base y la longitud correctas (calculadas a partir de las direcciones de inicio y final en el primer campo).

Tenga en cuenta que necesitará tener su controlador de fallas ya configurado en este punto, porque el acto de leer el archivo maps en sí mismo probablemente cause escrituras dentro de su espacio de direcciones.

+0

Gracias - Tenía la esperanza de que hubiera alguna forma de tener que pasar manualmente/proc/self/maps, pero parece que no existe (de la discusión en http://stackoverflow.com/questions/269314/is-there-a-better-way-that-parsing-proc-self-maps-to-figure-out-memory-protectio). –

0

Comience simple. Proteja contra escritura algunas páginas y asegúrese de que su manejador de señales funcione para estas páginas. Luego, preocúpese por ampliar el alcance de la protección. Por ejemplo, es probable que no necesita la protección contra escritura de la sección de código: sistemas operativos pueden poner en práctica de escritura-o-ejecutar la semántica de protección sobre la memoria que evitará las secciones de código de cada vez que se escribe en:

+0

Sí, por este problema, podemos suponer que no hay código de auto modificación por el momento. Estaría bien con la protección de escritura de la sección de código o no, lo que sea más fácil. –

+0

En realidad, lo que estaba tratando de decir es que las secciones de código probablemente ya estén protegidas contra escritura. –

Cuestiones relacionadas