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

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -