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



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

static void hdl (int sig, siginfo_t *siginfo, void *context) {
printf("Caught Signal %dn", sig);
}
int main() {
struct sigaction act;
memset (&act, '', 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("%dn", *ip);
return 0;
}

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

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

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

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

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

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

volatile sigatomic_t ip_int;
// ...
ip_int = (sigatomic_t) ip;

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

如果您不确定是否已经拥有所需的权限,但确信您有足够的权限来获取它们,那么先发制人地预先获取它们怎么样?

最新更新