35
35
#include <mach-o/dyld.h>
36
36
#include <mach-o/loader.h>
37
37
#include <mach-o/nlist.h>
38
+ #include <pthread.h>
38
39
39
40
#ifdef __LP64__
40
41
typedef struct mach_header_64 mach_header_t ;
@@ -54,13 +55,18 @@ typedef struct nlist nlist_t;
54
55
#define SEG_DATA_CONST "__DATA_CONST"
55
56
#endif
56
57
58
+ #ifndef SEG_AUTH_CONST
59
+ #define SEG_AUTH_CONST "__AUTH_CONST"
60
+ #endif
61
+
57
62
struct rebindings_entry {
58
63
struct rebinding * rebindings ;
59
64
size_t rebindings_nel ;
60
65
struct rebindings_entry * next ;
61
66
};
62
67
63
68
static struct rebindings_entry * _rebindings_head ;
69
+ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ;
64
70
65
71
static int prepend_rebindings (struct rebindings_entry * * rebindings_head ,
66
72
struct rebinding rebindings [],
@@ -90,7 +96,7 @@ static vm_prot_t get_protection(void *sectionStart) {
90
96
mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64 ;
91
97
vm_region_basic_info_data_64_t info ;
92
98
kern_return_t info_ret = vm_region_64 (
93
- task , & address , & size , VM_REGION_BASIC_INFO_64 , (vm_region_info_64_t )& info , & count , & object );
99
+ task , & address , & size , VM_REGION_BASIC_INFO_64 , (vm_region_info_64_t )& info , & count , & object );
94
100
#else
95
101
mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT ;
96
102
vm_region_basic_info_data_t info ;
@@ -109,17 +115,23 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings,
109
115
char * strtab ,
110
116
uint32_t * indirect_symtab ) {
111
117
const bool isDataConst = strcmp (section -> segname , SEG_DATA_CONST ) == 0 ;
118
+ const bool isAuthConst = strcmp (section -> segname , SEG_AUTH_CONST ) == 0 ;
112
119
uint32_t * indirect_symbol_indices = indirect_symtab + section -> reserved1 ;
113
120
void * * indirect_symbol_bindings = (void * * )((uintptr_t )slide + section -> addr );
114
121
vm_prot_t oldProtection = VM_PROT_READ ;
115
- if (isDataConst ) {
116
- oldProtection = get_protection (rebindings );
117
- mprotect (indirect_symbol_bindings , section -> size , PROT_READ | PROT_WRITE );
122
+ vm_size_t trunc_address = (vm_size_t )indirect_symbol_bindings ;
123
+ vm_size_t trunc_size = 0 ;
124
+ if (isDataConst || isAuthConst ) {
125
+ trunc_address = trunc_page ((vm_size_t )indirect_symbol_bindings );
126
+ trunc_size = (vm_size_t )indirect_symbol_bindings - trunc_address ;
127
+ pthread_mutex_lock (& mutex );
128
+ oldProtection = get_protection ((void * )trunc_address );
129
+ mprotect ((void * )trunc_address , section -> size + trunc_size , PROT_READ | PROT_WRITE );
118
130
}
119
131
for (uint i = 0 ; i < section -> size / sizeof (void * ); i ++ ) {
120
132
uint32_t symtab_index = indirect_symbol_indices [i ];
121
133
if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL ||
122
- symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS )) {
134
+ symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS )) {
123
135
continue ;
124
136
}
125
137
uint32_t strtab_offset = symtab [symtab_index ].n_un .n_strx ;
@@ -142,7 +154,7 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings,
142
154
}
143
155
symbol_loop :;
144
156
}
145
- if (isDataConst ) {
157
+ if (isDataConst || isAuthConst ) {
146
158
int protection = 0 ;
147
159
if (oldProtection & VM_PROT_READ ) {
148
160
protection |= PROT_READ ;
@@ -153,7 +165,8 @@ static void perform_rebinding_with_section(struct rebindings_entry *rebindings,
153
165
if (oldProtection & VM_PROT_EXECUTE ) {
154
166
protection |= PROT_EXEC ;
155
167
}
156
- mprotect (indirect_symbol_bindings , section -> size , protection );
168
+ mprotect ((void * )trunc_address , section -> size + trunc_size , protection );
169
+ pthread_mutex_unlock (& mutex );
157
170
}
158
171
}
159
172
@@ -164,12 +177,12 @@ static void rebind_symbols_for_image(struct rebindings_entry *rebindings,
164
177
if (dladdr (header , & info ) == 0 ) {
165
178
return ;
166
179
}
167
-
180
+
168
181
segment_command_t * cur_seg_cmd ;
169
182
segment_command_t * linkedit_segment = NULL ;
170
183
struct symtab_command * symtab_cmd = NULL ;
171
184
struct dysymtab_command * dysymtab_cmd = NULL ;
172
-
185
+
173
186
uintptr_t cur = (uintptr_t )header + sizeof (mach_header_t );
174
187
for (uint i = 0 ; i < header -> ncmds ; i ++ , cur += cur_seg_cmd -> cmdsize ) {
175
188
cur_seg_cmd = (segment_command_t * )cur ;
@@ -183,31 +196,32 @@ static void rebind_symbols_for_image(struct rebindings_entry *rebindings,
183
196
dysymtab_cmd = (struct dysymtab_command * )cur_seg_cmd ;
184
197
}
185
198
}
186
-
199
+
187
200
if (!symtab_cmd || !dysymtab_cmd || !linkedit_segment ||
188
201
!dysymtab_cmd -> nindirectsyms ) {
189
202
return ;
190
203
}
191
-
204
+
192
205
// Find base symbol/string table addresses
193
206
uintptr_t linkedit_base = (uintptr_t )slide + linkedit_segment -> vmaddr - linkedit_segment -> fileoff ;
194
207
nlist_t * symtab = (nlist_t * )(linkedit_base + symtab_cmd -> symoff );
195
208
char * strtab = (char * )(linkedit_base + symtab_cmd -> stroff );
196
-
209
+
197
210
// Get indirect symbol table (array of uint32_t indices into symbol table)
198
211
uint32_t * indirect_symtab = (uint32_t * )(linkedit_base + dysymtab_cmd -> indirectsymoff );
199
-
212
+
200
213
cur = (uintptr_t )header + sizeof (mach_header_t );
201
214
for (uint i = 0 ; i < header -> ncmds ; i ++ , cur += cur_seg_cmd -> cmdsize ) {
202
215
cur_seg_cmd = (segment_command_t * )cur ;
203
216
if (cur_seg_cmd -> cmd == LC_SEGMENT_ARCH_DEPENDENT ) {
204
217
if (strcmp (cur_seg_cmd -> segname , SEG_DATA ) != 0 &&
205
- strcmp (cur_seg_cmd -> segname , SEG_DATA_CONST ) != 0 ) {
218
+ strcmp (cur_seg_cmd -> segname , SEG_DATA_CONST ) != 0 &&
219
+ strcmp (cur_seg_cmd -> segname , SEG_AUTH_CONST ) != 0 ) {
206
220
continue ;
207
221
}
208
222
for (uint j = 0 ; j < cur_seg_cmd -> nsects ; j ++ ) {
209
223
section_t * sect =
210
- (section_t * )(cur + sizeof (segment_command_t )) + j ;
224
+ (section_t * )(cur + sizeof (segment_command_t )) + j ;
211
225
if ((sect -> flags & SECTION_TYPE ) == S_LAZY_SYMBOL_POINTERS ) {
212
226
perform_rebinding_with_section (rebindings , sect , slide , symtab , strtab , indirect_symtab );
213
227
}
@@ -221,21 +235,21 @@ static void rebind_symbols_for_image(struct rebindings_entry *rebindings,
221
235
222
236
static void _rebind_symbols_for_image (const struct mach_header * header ,
223
237
intptr_t slide ) {
224
- rebind_symbols_for_image (_rebindings_head , header , slide );
238
+ rebind_symbols_for_image (_rebindings_head , header , slide );
225
239
}
226
240
227
241
int rebind_symbols_image (void * header ,
228
242
intptr_t slide ,
229
243
struct rebinding rebindings [],
230
244
size_t rebindings_nel ) {
231
- struct rebindings_entry * rebindings_head = NULL ;
232
- int retval = prepend_rebindings (& rebindings_head , rebindings , rebindings_nel );
233
- rebind_symbols_for_image (rebindings_head , (const struct mach_header * ) header , slide );
234
- if (rebindings_head ) {
235
- free (rebindings_head -> rebindings );
236
- }
237
- free (rebindings_head );
238
- return retval ;
245
+ struct rebindings_entry * rebindings_head = NULL ;
246
+ int retval = prepend_rebindings (& rebindings_head , rebindings , rebindings_nel );
247
+ rebind_symbols_for_image (rebindings_head , (const struct mach_header * ) header , slide );
248
+ if (rebindings_head ) {
249
+ free (rebindings_head -> rebindings );
250
+ }
251
+ free (rebindings_head );
252
+ return retval ;
239
253
}
240
254
241
255
int rebind_symbols (struct rebinding rebindings [], size_t rebindings_nel ) {
0 commit comments