如何触发内存范围访问异常?

时间:2017-08-06 11:12:53

标签: c posix

当程序对可配置存储区进行写访问时,程序如何发出信号?

这与某些调试器中的数据断点功能类似。需要POSIX兼容性,但只要它适用于Linux就不需要。

这里有一个我想要的说明性代码:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void configure_trap(void *FROM, void *TO){
  /*
  Set a trap on write access to any memory location from
    address FROM to address TO.
  When the trap is triggered, send SIGTRAP to the process.
  There is no need for an answer to have the full code, just
    an indication on how to proceed.
  */
}

char *ptr;

void trap_signal_handler(int signum){
  if(ptr[123] == 'x'){
    printf("Invalid value in ptr[123] !!!\n");
    /*
    Print a backtrace using libunwind. (Not part of this question.)
    */
  }
}

void some_function(){
  ptr[123] = 'x';
  /*
  This write access could be performed directly in this function or
    another function called directly or indirectly by this one and it
    could reside in this program or in an external library or could even
    be performed in a system call.
  trap_signal_handler should be called at this point.
  After the signal handler has been executed, program should resume
    normal operation.
  */
}

int main(){
  struct sigaction sa = { .sa_handler = trap_signal_handler };
  sigaction(SIGTRAP, &sa, NULL);
  ptr = malloc(1024);
  configure_trap(&ptr[123], &ptr[123]);
  some_function();
  return(0);
}

谢谢!

2 个答案:

答案 0 :(得分:2)

首先,使用mprotect()将页面标记为只读。然后在编写时,SIGSEGV将被提升。您将为此安装信号处理程序,如果使用sigaction完成,您可以通过检查si_addr来了解访问了哪个地址。有关详情,请参阅:C SIGSEGV Handler & Mprotect

请注意,mprotect()的粒度为一页,这意味着如果您尝试保护单个字节,实际上您将保护4 KB(如果这是您的页面大小)。

答案 1 :(得分:1)

使用https://github.com/vicencb/qdbp项目。

  1. 首先mprotect将内存页面设为只读。
  2. 当引发SIGSEGV时,它会一次向程序执行一条指令,直到导致写入只读存储器的指令为止。
  3. 然后它会调用你的回调。