C SIGSEGV处理程序和Mprotect

4

我正在构建一个程序,使用mprotect()来限制访问一块内存。当请求该内存时,会抛出SIGSEGV信号,我使用signal()调用来监听。

一旦检测到SIGSEGV,我需要以某种方式访问所请求的内存指针(引发故障的指针)和请求的段的大小。这是否可能?

void fifoSigHandler(){

    // Needs to only remove protection from requested block of virtual memory
    mprotect(fifoVm,(size_t)fifoVm_size,PROT_WRITE);
    printf("Caught Seg Fault");
}

void fifo_init(void* vm, int vm_size, int n_frames, int page_size)
{
    fifoVm = vm;
    fifoVm_size = vm_size;
    fifoFrames = n_frames;
    fifoPageSize = page_size;

    mprotect(fifoVm,(size_t)fifoVm_size,PROT_NONE);

    signal(SIGSEGV, fifoSigHandler);
}

此外,有没有一种方法可以确定一个内存块当前分配的mprotect()级别(PROT_NONE、PROT_READ等)?
3个回答

6
您需要使用sigactionSA_SIGINFO来建立处理程序,而不是使用signal。然后,您将通过siginfo_t回调并获得有用的信息,包括si_addr
sigaction(2)所述,si_addr将包含地址。至于长度,除非您愿意解析指令,否则您将无法得到。您能做的最好的事情就是针对si_addr中报告的页面采取行动,如果这还不够,您很快就会收到另一个信号。至少,在ObjectStore中我们是这样做的。

2
我们如何引用这些有用的信息?特别是指向所请求内存的指针和大小。 - pws5068

2

您正在寻找libsigsegv http://libsigsegv.sourceforge.net/

但请注意,在Linux中调用mprotect只是信号安全的,其他POSIX系统可能不支持此功能。

很抱歉,在Linux中获取内存保护位的唯一方法是读取/proc/$pid/meminfo

另外(仅适用于Linux):如果您担心内存消耗并打算逐个启用更大映射的页面,则建议使用mmap创建您的映射,并使用MAP_NORESERVE,这样您将获得一个映射到零填充写时复制页面的映射,该页面将在第一次写入时分配物理RAM。MAP_NORESERVE指示内核不要使用交换空间来支持您的内存,从而允许您分配多达64TB的虚拟地址空间。唯一的缺点是如果您的内存用完了,可能会发生可怕的事情(oom-killer)。


1
步骤1:初始化sigaction
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
sigemptyset(&act.sa_mask);
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;

步骤2:使此sigaction处理SIGSEGV
sigaction(SIGSEGV, &act, NULL);

(可选)步骤 3:使其处理其他内存信号:
sigaction(SIGBUS, &act, NULL);
sigaction(SIGTRAP, &act, NULL);

根据需要添加错误处理

步骤4: 定义处理函数:

void handler(int signal, siginfo_t* siginfo, void* uap) {
    printf("Attempt to access memory at address %p\n", 
           siginfo->si_addr);
    #ifdef LINUX_64BIT
    printf("Instruction pointer: %p\n",
           (((ucontext_t*)uap)->uc_mcontext.gregs[16]));
    #elif LINUX_32BIT
    printf("Instruction pointer: %p\n",
           (((ucontext_t*)uap)->uc_mcontext.gregs[14]));
    #endif
}

你可以参考ucontext_tsiginfo_t的手册,以获取更有趣的数据,这些数据可以由你的处理程序提取。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接