¿Cómo puedo hacer que las llamadas al sistema invoquen mi controlador SIGSEGV cuando tengo memoria protegida?

StackOverflow https://stackoverflow.com/questions/1071860

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?

¿Fue útil?

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 y PTRACE_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, usos PTRACE_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.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top