If I mprotect a segment with PROT_NONE and if a SIGSEGV occurs due to a write which gets handled by sigaction with sa_sigaction, We will be able to find the address where the fault occurs using siginfo_t's si_addr.

Is there a way to know the data that was tried to be over-written and the length to be over-written(that should be the length of the incoming data)?

I am trying to do this because I trying an approach close to copy-on-write mechanism for my project. Thanks.

Yes you can (sort of), however it is fairly non-trivial. The last parameter to sa_sigaction is a pointer to ucontext_t of a faulting context. Among other things, it includes uc_mcontext (describing the complete state of the cpu). It in turn contains a gregset array og general purpose registers. Now, gregset[REG_EIP] is an address of the faulting instruction. Analyzing the instruction you can recover a type of access (R/W/E/whatever), width of access (8/16/32/64/... bytes), and with a little more analysis of registers and the addressing mode you'd be able to figure out actual data (if it was write access).

This is pretty much the best you can recover.

PS: REG_EIP is of course x86 specific. If there is ARM (or something else) involved, adjust accordingly.
PPS: This is just a mere outline of what needs to be done. Devil is in details as usual.

@nezachem : Thanks for the reply. From your post, I believe I have to get into the gritty details of "How to analyse the asm code" !!! I have not done too much asm coding but is there a resource you could point be to, that would help be in tackling this problem ? Thanks.

I have to get into the gritty details

I was answering the "how do I know the data" question. Fortunately it is highly irrelevant to the task you have. For a copy-on-write, the only thing you need to know is whether to faulting context is allowed to access the page. Once you decide (according to the policies) that it is, just change permissions and restart the context.

@nezachem : Well, to be precise, I am not exactly doing copy-on-write . What I wish to do is

1. mprotect an area
2. Whenever there is a write (reads are permitted. For eg sake, I used PROT_NONE), I have to backup the old value and store it in a mapping [Key is address - Data is old_data].
3. The write is then allowed to update the page.
4. Again protect the page so step 2 & 3 can happen any number of time.
5. At any point, I should be able to roll back to the previous state(right before the step 1) if requested (Ofcourse this involves making note of the stack pointer and related register)

I know that we have getcontext and setcontext for this purpose. But I want to do the above as a learning process.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.