c++ - How to trap memory reads and writes using sigsegv? -
how trick linux thinking memory read/write successful? writing c++ library such reads/writes redirected , handled transparently end user. anytime variable written or read from, library need catch request , shoot off hardware simulation handle data there.
note library platform dependent on:
linux ubuntu 3.16.0-39-generic #53~14.04.1-ubuntu smp x86_64 gnu/linux
gcc (ubuntu 4.8.2-19ubuntu1) 4.8.2
current approach: catch sigsegv , increment reg_rip
my current approach involves getting memory region using mmap()
, shutting off access using mprotect()
. have sigsegv handler info containing memory address, export read/write elsewhere, increment context reg_rip.
void handle_sigsegv(int code, siginfo_t *info, void *ctx) { void *addr = info->si_addr; ucontext_t *u = (ucontext_t *)ctx; int err = u->uc_mcontext.gregs[reg_err]; bool is_write = (err & 0x2); // send data read/write simulation... // continue execution of program incrementing rip u->uc_mcontext.gregs[reg_rip] += 6; }
this works simple cases, such as:
int *num_ptr = (int *)nullptr; *num_ptr = 10; // write segfault
but more complex, receive sigabrt:
30729 illegal instruction (core dumped) ./$target
using mprotect() within sigsegv handler
if not increment reg_rip, handle_sigsegv()
called on , on again kernel until memory region becomes available reading or writing. run mprotect()
specific address, has multiple caveats:
- subsequent memory access not trigger sigsegv due memory region having prot_write ability. have tried create thread continuously marks region prot_none, not elude next point:
mprotect()
will, @ end of day, perform read or write memory, invalidating use case of library.
writing device driver
i have attempted write device module such library can call mmap()
on char device, driver handle reads , writes there. makes sense in theory, have not been able (or not have knowledge to) catch every load/store processor issues device. have attempted overwrite mapped vm_operations_struct
and/or inode's address_space_operations
struct, call reads/writes when page faulted or page flushed backing store.
perhaps use mmap()
, mprotect()
, explained above, on device writes data (similar /dev/null
), have process recognizes reads/writes , routes data there (?).
utilize syscall()
, provide restorer assembly function
the following pulled segvcatch
project1 converts segfaults exceptions.
#define restore(name, syscall) restore2(name, syscall) #define restore2(name, syscall)\ asm(\ ".text\n"\ ".byte 0\n"\ ".align 16\n"\ "__" #name ":\n"\ " movq $" #syscall ", %rax\n"\ " syscall\n"\ ); restore(restore_rt, __nr_rt_sigreturn) void restore_rt(void) asm("__restore_rt") __attribute__ ((visibility("hidden"))); extern "c" { struct kernel_sigaction { void (*k_sa_sigaction)(int, siginfo_t *, void *); unsigned long k_sa_flags; void (*k_sa_restorer)(void); sigset_t k_sa_mask; }; } // within main ... struct kernel_sigaction act; act.k_sa_sigaction = handle_sigegv; sigemptyset(&act.k_sa_mask); act.k_sa_flags = sa_siginfo|0x4000000; act.k_sa_restorer = restore_rt; syscall(sys_rt_sigaction, sigsegv, &act, null, _nsig / 8);
but ends functioning no different regular sigaction()
configuration. if not set restorer function signal handler not called more once, when memory region still not available. perhaps there other trickery kernel signal here.
again, entire objective of library transparently handle reads , writes memory. perhaps there better way of doing things, maybe ptrace()
or updating kernel code generates segfault signal, important part end-user's code not require changes. have seen examples using setjmp()
, longjmp()
continue after segfault, require adding calls every memory access. same goes converting segfault try/catch.
1 segvcatch project
you can use mprotect , avoid first problem note having sigsegv handler set t flag in flags register. then, add sigtrap handler restores mprotected memory , clears t flag.
the t flag causes processor single step, when segv handler returns execute single instruction, , trap.
this still leaves second problem -- read/write instruction occur. may able around problem modifying memory before and/or after instruction in 2 signal handlers...
Comments
Post a Comment