Merge pull request #2 from rdrpenguin04/main

Add mach_vm_msync
This commit is contained in:
Ariel Abreu 2022-06-18 23:01:21 -04:00 committed by GitHub
commit 5bd9a87821
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 2 deletions

View File

@ -56,6 +56,7 @@ typedef int (*dtape_hook_task_free_pages_f)(void* task_context, uintptr_t addres
typedef uintptr_t (*dtape_hook_task_map_file_f)(void* task_context, int fd, size_t page_count, int protection, uintptr_t address_hint, size_t page_offset, dtape_memory_flags_t flags); typedef uintptr_t (*dtape_hook_task_map_file_f)(void* task_context, int fd, size_t page_count, int protection, uintptr_t address_hint, size_t page_offset, dtape_memory_flags_t flags);
typedef uintptr_t (*dtape_hook_task_get_next_region_f)(void* task_context, uintptr_t address); typedef uintptr_t (*dtape_hook_task_get_next_region_f)(void* task_context, uintptr_t address);
typedef bool (*dtape_hook_task_change_protection_f)(void* task_context, uintptr_t address, size_t page_count, int protection); typedef bool (*dtape_hook_task_change_protection_f)(void* task_context, uintptr_t address, size_t page_count, int protection);
typedef bool (*dtape_hook_task_sync_memory_f)(void* task_context, uintptr_t address, size_t size, int sync_flags);
typedef void (*dtape_hook_task_context_dispose_f)(void* task_context); typedef void (*dtape_hook_task_context_dispose_f)(void* task_context);
#if DSERVER_EXTENDED_DEBUG #if DSERVER_EXTENDED_DEBUG
@ -101,6 +102,7 @@ typedef struct dtape_hooks {
dtape_hook_task_map_file_f task_map_file; dtape_hook_task_map_file_f task_map_file;
dtape_hook_task_get_next_region_f task_get_next_region; dtape_hook_task_get_next_region_f task_get_next_region;
dtape_hook_task_change_protection_f task_change_protection; dtape_hook_task_change_protection_f task_change_protection;
dtape_hook_task_sync_memory_f task_sync_memory;
dtape_hook_task_context_dispose_f task_context_dispose; dtape_hook_task_context_dispose_f task_context_dispose;
#if DSERVER_EXTENDED_DEBUG #if DSERVER_EXTENDED_DEBUG

View File

@ -594,8 +594,28 @@ kern_return_t mach_vm_map_external(vm_map_t target_map, mach_vm_offset_t* addres
dtape_stub_unsafe(); dtape_stub_unsafe();
}; };
kern_return_t mach_vm_msync(vm_map_t map, mach_vm_address_t address, mach_vm_size_t size, vm_sync_t sync_flags) { kern_return_t mach_vm_msync(vm_map_t map, mach_vm_offset_t address, mach_vm_size_t size, vm_sync_t sync_flags) {
dtape_stub_unsafe(); int linux_flags = 0;
// TODO: give the Linux bits names/macros
if (sync_flags & VM_SYNC_ASYNCHRONOUS) {
linux_flags |= 1 << 0;
}
if (sync_flags & VM_SYNC_SYNCHRONOUS) {
linux_flags |= 1 << 2;
}
if (sync_flags & VM_SYNC_INVALIDATE) {
linux_flags |= 1 << 1;
}
if (!dtape_hooks->task_sync_memory(map->dtape_task->context, address, size, linux_flags)) {
return KERN_FAILURE;
}
return KERN_SUCCESS;
}; };
kern_return_t mach_vm_page_info(vm_map_t map, mach_vm_address_t address, vm_page_info_flavor_t flavor, vm_page_info_t info, mach_msg_type_number_t* count) { kern_return_t mach_vm_page_info(vm_map_t map, mach_vm_address_t address, vm_page_info_flavor_t flavor, vm_page_info_t info, mach_msg_type_number_t* count) {

View File

@ -149,6 +149,7 @@ enum dserver_s2c_msgnum {
dserver_s2c_msgnum_mmap, dserver_s2c_msgnum_mmap,
dserver_s2c_msgnum_munmap, dserver_s2c_msgnum_munmap,
dserver_s2c_msgnum_mprotect, dserver_s2c_msgnum_mprotect,
dserver_s2c_msgnum_msync,
}; };
typedef enum dserver_s2c_msgnum dserver_s2c_msgnum_t; typedef enum dserver_s2c_msgnum dserver_s2c_msgnum_t;
@ -207,10 +208,24 @@ typedef struct dserver_s2c_reply_mprotect {
int errno_result; int errno_result;
} dserver_s2c_reply_mprotect_t; } dserver_s2c_reply_mprotect_t;
typedef struct dserver_s2c_call_msync {
dserver_s2c_callhdr_t header;
uint64_t address;
uint64_t size;
int sync_flags;
} dserver_s2c_call_msync_t;
typedef struct dserver_s2c_reply_msync {
dserver_s2c_replyhdr_t header;
int return_value;
int errno_result;
} dserver_s2c_reply_msync_t;
typedef union dserver_s2c_call { typedef union dserver_s2c_call {
dserver_s2c_call_mmap_t mmap; dserver_s2c_call_mmap_t mmap;
dserver_s2c_call_munmap_t munmap; dserver_s2c_call_munmap_t munmap;
dserver_s2c_call_mprotect_t mprotect; dserver_s2c_call_mprotect_t mprotect;
dserver_s2c_call_msync_t msync;
} dserver_s2c_call_t; } dserver_s2c_call_t;
#if __cplusplus #if __cplusplus

View File

@ -180,6 +180,7 @@ namespace DarlingServer {
void freePages(uintptr_t address, size_t pageCount); void freePages(uintptr_t address, size_t pageCount);
uintptr_t mapFile(int fd, size_t pageCount, int protection, uintptr_t addressHint, size_t pageOffset, bool fixed, bool overwrite); uintptr_t mapFile(int fd, size_t pageCount, int protection, uintptr_t addressHint, size_t pageOffset, bool fixed, bool overwrite);
void changeProtection(uintptr_t address, size_t pageCount, int protection); void changeProtection(uintptr_t address, size_t pageCount, int protection);
void syncMemory(uintptr_t address, size_t size, int sync_flags);
uintptr_t getNextRegion(uintptr_t address) const; uintptr_t getNextRegion(uintptr_t address) const;

View File

@ -126,6 +126,7 @@ namespace DarlingServer {
uintptr_t _mmap(uintptr_t address, size_t length, int protection, int flags, int fd, off_t offset, int& outErrno); uintptr_t _mmap(uintptr_t address, size_t length, int protection, int flags, int fd, off_t offset, int& outErrno);
int _munmap(uintptr_t address, size_t length, int& outErrno); int _munmap(uintptr_t address, size_t length, int& outErrno);
int _mprotect(uintptr_t address, size_t length, int protection, int& outErrno); int _mprotect(uintptr_t address, size_t length, int protection, int& outErrno);
int _msync(uintptr_t address, size_t size, int sync_flags, int& outErrno);
void _deferLocked(bool wait, std::unique_lock<std::shared_mutex>& lock); void _deferLocked(bool wait, std::unique_lock<std::shared_mutex>& lock);
void _undeferLocked(std::unique_lock<std::shared_mutex>& lock); void _undeferLocked(std::unique_lock<std::shared_mutex>& lock);
@ -235,6 +236,7 @@ namespace DarlingServer {
void freePages(uintptr_t address, size_t pageCount); void freePages(uintptr_t address, size_t pageCount);
uintptr_t mapFile(int fd, size_t pageCount, int protection, uintptr_t addressHint, size_t pageOffset, bool fixed, bool overwrite); uintptr_t mapFile(int fd, size_t pageCount, int protection, uintptr_t addressHint, size_t pageOffset, bool fixed, bool overwrite);
void changeProtection(uintptr_t address, size_t pageCount, int protection); void changeProtection(uintptr_t address, size_t pageCount, int protection);
void syncMemory(uintptr_t address, size_t size, int sync_flags);
void defer(bool wait = false); void defer(bool wait = false);
void undefer(); void undefer();

View File

@ -633,6 +633,16 @@ void DarlingServer::Process::changeProtection(uintptr_t address, size_t pageCoun
return thread->changeProtection(address, pageCount, protection); return thread->changeProtection(address, pageCount, protection);
}; };
void DarlingServer::Process::syncMemory(uintptr_t address, size_t size, int sync_flags) {
auto thread = _pickS2CThread();
if (!thread) {
throw std::system_error(ESRCH, std::generic_category());
}
return thread->syncMemory(address, size, sync_flags);
};
static const std::regex memoryRegionEntryAddressRegex("([0-9a-fA-F]+)\\-([0-9a-fA-F]+)"); static const std::regex memoryRegionEntryAddressRegex("([0-9a-fA-F]+)\\-([0-9a-fA-F]+)");
uintptr_t DarlingServer::Process::getNextRegion(uintptr_t address) const { uintptr_t DarlingServer::Process::getNextRegion(uintptr_t address) const {

View File

@ -302,6 +302,15 @@ struct DTapeHooks {
} }
}; };
static bool dtape_hook_task_sync_memory(void* task_context, uintptr_t address, size_t size, int sync_flags) {
try {
static_cast<DarlingServer::Process*>(task_context)->syncMemory(address, size, sync_flags);
return true;
} catch (std::system_error e) {
return false;
}
};
static void dtape_hook_task_context_dispose(void* task_context) { static void dtape_hook_task_context_dispose(void* task_context) {
static_cast<DarlingServer::Process*>(task_context)->_dispose(); static_cast<DarlingServer::Process*>(task_context)->_dispose();
}; };
@ -363,6 +372,7 @@ struct DTapeHooks {
.task_map_file = dtape_hook_task_map_file, .task_map_file = dtape_hook_task_map_file,
.task_get_next_region = dtape_hook_task_get_next_region, .task_get_next_region = dtape_hook_task_get_next_region,
.task_change_protection = dtape_hook_task_change_protection, .task_change_protection = dtape_hook_task_change_protection,
.task_sync_memory = dtape_hook_task_sync_memory,
.task_context_dispose = dtape_hook_task_context_dispose, .task_context_dispose = dtape_hook_task_context_dispose,
#if DSERVER_EXTENDED_DEBUG #if DSERVER_EXTENDED_DEBUG

View File

@ -1171,6 +1171,34 @@ int DarlingServer::Thread::_mprotect(uintptr_t address, size_t length, int prote
return reply->return_value; return reply->return_value;
}; };
int DarlingServer::Thread::_msync(uintptr_t address, size_t size, int sync_flags, int& outErrno) {
Message callMessage(sizeof(dserver_s2c_call_msync_t), 0);
auto call = reinterpret_cast<dserver_s2c_call_msync_t*>(callMessage.data().data());
call->header.call_number = dserver_callnum_s2c;
call->header.s2c_number = dserver_s2c_msgnum_msync;
call->address = address;
call->size = size;
call->sync_flags = sync_flags;
s2cLog.debug() << "Performing _msync with address=" << call->address << ", size=" << call->size << ", sync_flags=" << call->sync_flags << s2cLog.endLog;
auto maybeReplyMessage = _s2cPerform(std::move(callMessage), dserver_s2c_msgnum_msync, sizeof(dserver_s2c_reply_msync_t));
if (!maybeReplyMessage) {
s2cLog.debug() << "_msync call interrupted" << s2cLog.endLog;
outErrno = EINTR;
return -1;
}
auto replyMessage = std::move(*maybeReplyMessage);
auto reply = reinterpret_cast<dserver_s2c_reply_msync_t*>(replyMessage.data().data());
s2cLog.debug() << "_msync returned return_value=" << reply->return_value << ", errno_result=" << reply->errno_result << s2cLog.endLog;
outErrno = reply->errno_result;
return reply->return_value;
};
uintptr_t DarlingServer::Thread::allocatePages(size_t pageCount, int protection, uintptr_t addressHint, bool fixed, bool overwrite) { uintptr_t DarlingServer::Thread::allocatePages(size_t pageCount, int protection, uintptr_t addressHint, bool fixed, bool overwrite) {
int err = 0; int err = 0;
int flags = MAP_PRIVATE | MAP_ANONYMOUS; int flags = MAP_PRIVATE | MAP_ANONYMOUS;
@ -1215,6 +1243,13 @@ void DarlingServer::Thread::changeProtection(uintptr_t address, size_t pageCount
} }
}; };
void DarlingServer::Thread::syncMemory(uintptr_t address, size_t size, int sync_flags) {
int err = 0;
if (_msync(address, size, sync_flags, err) < 0) {
throw std::system_error(err, std::generic_category(), "S2C msync call failed");
}
};
void DarlingServer::Thread::waitUntilRunning() { void DarlingServer::Thread::waitUntilRunning() {
std::shared_lock lock(_rwlock); std::shared_lock lock(_rwlock);
_runningCondvar.wait(lock, [&]() { _runningCondvar.wait(lock, [&]() {