|
7 | 7 |
|
8 | 8 | #include "doraemon_fishhook.h" |
9 | 9 |
|
| 10 | +#include <assert.h> |
10 | 11 | #include <dlfcn.h> |
11 | 12 | #include <stdbool.h> |
12 | 13 | #include <stdlib.h> |
@@ -96,10 +97,35 @@ static void doraemon_perform_rebinding_with_section(struct doraemon_rebindings_e |
96 | 97 | const bool isDataConst = strcmp(section->segname, "__DATA_CONST") == 0; |
97 | 98 | uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1; |
98 | 99 | void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr); |
99 | | - vm_prot_t oldProtection = VM_PROT_READ; |
| 100 | + vm_prot_t oldProtection = VM_PROT_NONE; |
| 101 | + vm_address_t vmAddress = (vm_address_t)indirect_symbol_bindings; |
| 102 | + // https://opensource.apple.com/source/xnu/xnu-7195.141.2/osfmk/vm/vm_user.c.auto.html |
| 103 | + // OUT argument, but init with zero to eliminate `Variable 'vmSize' may be uninitialized when used here` warning |
| 104 | + vm_size_t vmSize = 0; |
100 | 105 | if (isDataConst) { |
101 | | - oldProtection = doraemon_get_protection(rebindings); |
102 | | - mprotect(indirect_symbol_bindings, section->size, PROT_READ | PROT_WRITE); |
| 106 | + memory_object_name_t object; |
| 107 | +#ifdef __LP64__ |
| 108 | + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; |
| 109 | + vm_region_basic_info_data_64_t vmRegionBasicInfoData; |
| 110 | + kern_return_t kernelReturn = vm_region_64(mach_task_self(), &vmAddress, &vmSize, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&vmRegionBasicInfoData, &count, &object); |
| 111 | +#else |
| 112 | + mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT; |
| 113 | + vm_region_basic_info_data_t vmRegionBasicInfoData; |
| 114 | + kern_return_t kernelReturn = vm_region(mach_task_self(), &vmAddress, &vmSize, VM_REGION_BASIC_INFO, (vm_region_info_t)&vmRegionBasicInfoData, &count, object); |
| 115 | +#endif |
| 116 | + if (__builtin_expect(kernelReturn == KERN_SUCCESS, true)) { |
| 117 | + oldProtection = vmRegionBasicInfoData.protection; |
| 118 | + } else { |
| 119 | + assert(false && "vm_region() failure."); |
| 120 | + |
| 121 | + return; |
| 122 | + } |
| 123 | + kernelReturn = vm_protect(mach_task_self(), vmAddress, vmSize, false, oldProtection | VM_PROT_WRITE); |
| 124 | + if (__builtin_expect(kernelReturn != KERN_SUCCESS, false)) { |
| 125 | + assert(false && "vm_protect() failure."); |
| 126 | + |
| 127 | + return; |
| 128 | + } |
103 | 129 | } |
104 | 130 | for (uint i = 0; i < section->size / sizeof(void *); i++) { |
105 | 131 | uint32_t symtab_index = indirect_symbol_indices[i]; |
@@ -128,17 +154,8 @@ static void doraemon_perform_rebinding_with_section(struct doraemon_rebindings_e |
128 | 154 | symbol_loop:; |
129 | 155 | } |
130 | 156 | if (isDataConst) { |
131 | | - int protection = 0; |
132 | | - if (oldProtection & VM_PROT_READ) { |
133 | | - protection |= PROT_READ; |
134 | | - } |
135 | | - if (oldProtection & VM_PROT_WRITE) { |
136 | | - protection |= PROT_WRITE; |
137 | | - } |
138 | | - if (oldProtection & VM_PROT_EXECUTE) { |
139 | | - protection |= PROT_EXEC; |
140 | | - } |
141 | | - mprotect(indirect_symbol_bindings, section->size, protection); |
| 157 | + kern_return_t kernelReturn = vm_protect(mach_task_self(), vmAddress, vmSize, false, oldProtection); |
| 158 | + assert(kernelReturn == KERN_SUCCESS && "vm_protect() failure."); |
142 | 159 | } |
143 | 160 | } |
144 | 161 |
|
|
0 commit comments