从信号处理程序中访问受保护页面的地址

时间:2018-01-26 21:38:28

标签: c

有没有办法从信号处理程序中获取ip的地址?我希望能够更改页面的权限,以便信号不会继续发射。

static void hdl (int sig, siginfo_t *siginfo, void *context) {

    printf("Caught Signal %d\n", sig);

}

int main() {

    struct sigaction act;
    memset (&act, '\0', sizeof(act));
    act.sa_sigaction = &hdl;
    act.sa_flags = SA_SIGINFO;
    if (sigaction(SIGSEGV, &act, NULL) < 0)
        return 1;

    int *ip = (int *) mmap(NULL, getpagesize(), PROT_READ, MAP_ANONYMOUS, -1, 0);
    *ip = 1;

    printf("%d\n", *ip);

    return 0;
}

2 个答案:

答案 0 :(得分:1)

这是三参数信号处理程序的预期用途之一。 si_addr参数的siginfo字段将包含引发故障的不可访问的内存字的地址。 (注意:此字段仅对SIGSEGVSIGBUS具有该含义。对于其他信号,它可能是垃圾,或者可能反而指向违规的指令。)

static void
hdl(int sig, siginfo_t *info, void *ctx)
{
    assert(sig == SIGSEGV || sig == SIGBUS);
    printf("Memory fault, addr = %p\n", info->si_addr);
}

您可以使用mprotect修复包含si_addr的页面上的权限,然后从信号处理程序返回以继续执行。

答案 1 :(得分:0)

  

有没有办法从信号处理程序中获取ip的地址?

信号处理程序没有定义的方法来直接访问任何其他函数的局部变量。

sigatomic_t足够大以容纳指针值而不截断的实现上,您可以创建类型为volatile sigatomic_t的文件范围变量,将ip强制转换为sigatomic_t },并将其分配给该变量:

volatile sigatomic_t ip_int;

// ...

    ip_int = (sigatomic_t) ip;

然后信号处理程序可以安全地读取该变量。但是,即使您的sigatomic_t可以适应这种情况,但您用于更改内存权限的任何功能似乎都不太可能是异步信号安全的。如果不是,则无法从信号处理程序中安全地调用它,在这种情况下,您是否可以安全地将数据输入信号处理程序是没有意义的。

如果您不确定自己是否已经拥有所需的权限但又有足够的权限来获取这些权限,那么如何直接获得它们,先发制人?