I’m constructing a program which uses mprotect() to restrict a block of memory from accessing. When the memory is requested, a SIGSEGV is thrown which I listen for using a signal() call.
Once the SIGSEGV has been detected, I need to somehow access the pointer to the memory that was requested (that threw the fault) and the size of the segment requested. Is this possible?
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);
}
Additionally, is there a way to determine the level of mprotect() a block of memory is currently assigned (PROT_NONE,PROT_READ, etc..)?
You have to use
sigactionwithSA_SIGINFOinstead ofsignalto establish your handler, and then you will get called back with useful information in asiginfo_t, includingsi_addr.si_addr, as explained insigaction(2), will contain the address. As for the length, well, you’re out of luck unless you’re willing to parse instructions. Best you can do is take action for the page reported insi_addr, and then if that’s not enough, you’ll get another signal soon enough. At least, that’s how we did things in ObjectStore.