¿Cómo puedo hacer que las llamadas al sistema invoquen mi controlador SIGSEGV cuando tengo memoria protegida?
-
21-08-2019 - |
Pregunta
Estoy trabajando en una biblioteca de seguimiento de memoria donde usamos mprotect
para eliminar el acceso a la mayor parte de la memoria de un programa y un controlador SIGSEGV para restaurar el acceso a páginas individuales a medida que el programa las toca.Esto funciona muy bien la mayor parte del tiempo.
Mi problema es que cuando el programa invoca una llamada al sistema (digamos read
) con memoria que mi biblioteca ha marcado como sin acceso, la llamada al sistema simplemente devuelve -1 y establece errno
a EFAULT
.Esto cambia el comportamiento de los programas que se prueban de formas extrañas.Me gustaría poder restaurar el acceso a cada página de memoria otorgada a una llamada al sistema antes de que realmente llegue al kernel.
Mi enfoque actual es crear un contenedor para cada llamada al sistema que toca la memoria.Cada contenedor tocaría toda la memoria que se le haya asignado antes de entregársela a la llamada al sistema real.Parece que esto funcionará para llamadas realizadas directamente desde el programa, pero no para aquellas realizadas por libc (por ejemplo, fread
llamará read
directamente sin usar mi envoltorio).¿Existe algún enfoque mejor?¿Cómo es posible conseguir este comportamiento?
Solución
Puedes usar ptrace(2)
lograr esto.Le permite monitorear un proceso y recibir notificaciones cada vez que ocurren ciertos eventos.Para sus propósitos, mire PTRACE_SYSCALL
lo que le permite detener el proceso al entrar y salir de la llamada al sistema.
Sin embargo, tendrá que cambiar parte de su infraestructura de seguimiento de memoria, ya que ptrace
opera de manera que un proceso padre monitorea un proceso hijo y, en lo que respecta al hijo, no tiene visibilidad de cuándo ocurre un evento monitoreado.Dicho esto, deberías poder hacer algo como:
- Configurar ptrace padre e hijo, monitoreo (al menos)
PTRACE_SYSCALL
. - El proceso hijo realiza una llamada al sistema;y se notifica a los padres.
- El padre guarda la información de llamada al sistema solicitada;y usos
PTRACE_GETREGS
yPTRACE_SETREGS
para cambiar el estado del niño en lugar de llamar a la llamada al sistema;el proceso hijo llama a la rutina de "desprotección de memoria". - Niño desprotege su memoria;luego sube
SIGUSR1
o similar para decirle al padre controlador que el trabajo de la memoria está completo. - Capturas de padres
SIGUSR
, usosPTRACE_SETREGS
para restaurar la información de llamada al sistema previamente guardada y reanuda al niño. - El niño reanuda y ejecuta la llamada al sistema original.