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 sigaction
with SA_SIGINFO
instead of signal
to establish your handler, and then you will get called back with useful information in a siginfo_t
, including si_addr
.
si_addr
, as explained in sigaction
(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 in si_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.