void* safemem_read_pid_to_null(pid_data& pdata, uintptr_t remote_addr) { size_t max_size; char* wptr = safe_mem_allocator.allocate_largest(&max_size); if(!wptr) { return NULL; } for(size_t i = 0; ; ) { uintptr_t a = (remote_addr + i) & (sizeof(long) - 1); errno = 0; long v = ptrace(PTRACE_PEEKDATA, pdata.pid, remote_addr + i - a, NULL); if(errno == EFAULT) { return NULL; } char* vptr = (char*)&v + a; for(size_t ie = i + sizeof(long) - a; i != ie; i++, vptr++) { if(!(wptr[i] = *vptr)) { size_t sz = ((i + 8) & ~0x7); safe_mem_allocator.free(wptr + sz, max_size - sz); pdata.allocations.push_back(std::make_pair(wptr, sz)); return wptr; } else if(i + 1 == max_size) { safe_mem_allocator.free(wptr, max_size); return NULL; } } } }
bool safemem_map_unwritable() { if(munmap(const_cast<void*>(reinterpret_cast<const void*>( safe_mem_allocator.address())), safe_mem_allocator.size())) { return false; } safe_mem_allocator.reset(NULL, 0); return true; }
bool safemem_init() { char buf[16] = "/tmp/XXXXXX"; int wmfd = mkstemp(buf); if(wmfd == -1) { return false; } mfd = open(buf, O_RDONLY); if(mfd == -1) { return false; } if(unlink(buf) == -1) { return false; } if(ftruncate(wmfd, MAPPING_SIZE) == -1) { return false; } void* base_addr = mmap(NULL, MAPPING_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, wmfd, 0); if(base_addr == (void*)-1) { return false; } close(wmfd); safe_mem_allocator.reset(reinterpret_cast<char*>(base_addr), MAPPING_SIZE); return true; }
uintptr_t safemem_remote_addr(pid_data& pdata, void* local_ptr) { if(!pdata.safe_mem_base) { return 0; } return pdata.safe_mem_base + (reinterpret_cast<const char*>(local_ptr) - safe_mem_allocator.address()); }
static bool to_memory(memory_allocator &mem, size_t &size, const Type *ptr, Params... p) { size_t o_size; uint32_t *magic = reinterpret_cast<uint32_t *>(mem.allocate(sizeof(uint32_t))); if (!magic) return false; if (serializable<persistence_backend::neam, Type>::to_memory(mem, o_size, const_cast<Type *>(ptr), std::forward<Params>(p)...)) { size = o_size + sizeof(uint32_t); *magic = magic_number; return true; } return false; }
void* safemem_read_pid(pid_data& pdata, uintptr_t remote_addr, size_t len) { char* wptr = safe_mem_allocator.allocate((len + 0x7) * ~0x7); if(!wptr) { return NULL; } pdata.allocations.push_back(std::make_pair(wptr, (len + 0x7) & ~0x7)); for(size_t i = 0; i < len; ) { uintptr_t a = (remote_addr + i) & (sizeof(long) - 1); uintptr_t b = std::min(sizeof(long), a + len - i); errno = 0; long v = ptrace(PTRACE_PEEKDATA, pdata.pid, remote_addr + i - a, NULL); if(errno == EFAULT) { return NULL; } memcpy(wptr + i, (char *)&v + a, b - a); i += b - a; } return wptr; }
void safemem_reset(pid_data& pdata) { for(auto i : pdata.allocations) { safe_mem_allocator.free(i.first, i.second); } pdata.allocations.clear(); }