Trap all accesses to an address range (Linux)

心已入冬 提交于 2019-12-03 00:23:11

On X86 you can set Trap flag for the caller's context to get SIGTRAP after one instruction (this flag is typically used for single-stepping). That is, when SIGSEGV is encountered, you set TF in the caller's EFLAGS (see ucontext.h), enable reading with mprotect and return. If SIGSEGV is repeated instantly with the same IP, you enable writing (and optionally disable reading, if you want to distinguish read-modify-write from write-only access). If you get SIGSEGV from the same IP for read-only and write-only protection, enable read-write.

Whenever you get SIGTRAP, you can analyze what value was written (if it was a write access), and you can also re-protect the page to trap future accesses.

Correction: if both reads and writes can have side-effects, try write-only protection first, then apply reading side-effects and try read-only protection, then enable writing and handle side-effects of writing in the final SIGTRAP handler.

UPDATE: I was deadly wrong on recommending hypothetical write-only protection which turns out not to exist on most architectures. Fortunately there's a more straightforward way to know whether the operation that failed tries to read memory, at least on x86:

Page fault exception pushes an error code to the stack, which is available in Linux SIGSEGV handler as the err member of sigcontext structure. Bit 1 of the error code is 1 for write faults and 0 otherwise. For read-modify-write operation, it will be 0 initially (here you can emulate reading, knowing exactly that it's going to happen).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!