add mach_vm_msync

This commit is contained in:
Ray Redondo 2022-06-17 23:18:21 -05:00
parent 814434f139
commit b37026af03
8 changed files with 81 additions and 2 deletions

View File

@ -52,6 +52,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_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_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);
#if DSERVER_EXTENDED_DEBUG
@ -97,6 +98,7 @@ typedef struct dtape_hooks {
dtape_hook_task_map_file_f task_map_file;
dtape_hook_task_get_next_region_f task_get_next_region;
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;
#if DSERVER_EXTENDED_DEBUG

View File

@ -594,8 +594,12 @@ kern_return_t mach_vm_map_external(vm_map_t target_map, mach_vm_offset_t* addres
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) {
dtape_stub_unsafe();
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) {
if (!dtape_hooks->task_change_protection(map->dtape_task->context, address, size, sync_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) {

View File

@ -149,6 +149,7 @@ enum dserver_s2c_msgnum {
dserver_s2c_msgnum_mmap,
dserver_s2c_msgnum_munmap,
dserver_s2c_msgnum_mprotect,
dserver_s2c_msgnum_msync,
};
typedef enum dserver_s2c_msgnum dserver_s2c_msgnum_t;
@ -207,10 +208,24 @@ typedef struct dserver_s2c_reply_mprotect {
int errno_result;
} 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 {
dserver_s2c_call_mmap_t mmap;
dserver_s2c_call_munmap_t munmap;
dserver_s2c_call_mprotect_t mprotect;
dserver_s2c_call_msync_t msync;
} dserver_s2c_call_t;
#if __cplusplus

View File

@ -180,6 +180,7 @@ namespace DarlingServer {
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);
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;

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);
int _munmap(uintptr_t address, size_t length, 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 _undeferLocked(std::unique_lock<std::shared_mutex>& lock);
@ -235,6 +236,7 @@ namespace DarlingServer {
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);
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 undefer();

View File

@ -633,6 +633,16 @@ void DarlingServer::Process::changeProtection(uintptr_t address, size_t pageCoun
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]+)");
uintptr_t DarlingServer::Process::getNextRegion(uintptr_t address) const {

View File

@ -297,6 +297,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_cast<DarlingServer::Process*>(task_context)->_dispose();
};
@ -358,6 +367,7 @@ struct DTapeHooks {
.task_map_file = dtape_hook_task_map_file,
.task_get_next_region = dtape_hook_task_get_next_region,
.task_change_protection = dtape_hook_task_change_protection,
.task_sync_memory = dtape_hook_task_sync_memory,
.task_context_dispose = dtape_hook_task_context_dispose,
#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;
};
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) {
int err = 0;
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() {
std::shared_lock lock(_rwlock);
_runningCondvar.wait(lock, [&]() {