@@ -140,7 +140,7 @@ LM_LoadModule(lm_string_t path,
140
140
/********************************/
141
141
142
142
lm_bool_t
143
- find_dlopen_module_callback (lm_module_t * module , lm_void_t * arg )
143
+ find_dlfcn_module_callback (lm_module_t * module , lm_void_t * arg )
144
144
{
145
145
static const char * name_matches [] = {
146
146
"libc." , "libc-" , "libdl." , "libdl-" , "ld-musl-" , "ld-musl."
@@ -194,7 +194,7 @@ LM_LoadModuleEx(const lm_process_t *process,
194
194
return ret ;
195
195
196
196
dlopen_mod .base = LM_ADDRESS_BAD ;
197
- LM_EnumModulesEx (process , find_dlopen_module_callback , & dlopen_mod );
197
+ LM_EnumModulesEx (process , find_dlfcn_module_callback , & dlopen_mod );
198
198
if (dlopen_mod .base == LM_ADDRESS_BAD )
199
199
return ret ;
200
200
@@ -216,9 +216,9 @@ LM_LoadModuleEx(const lm_process_t *process,
216
216
ptlib .args [1 ] = RTLD_LAZY ;
217
217
if (process -> bits == 64 ) {
218
218
* (uint64_t * )& ptlib .stack [0 ] = (uint64_t )path_addr ;
219
- * (int32_t * )& ptlib .stack [4 ] = (int32_t )RTLD_LAZY ;
219
+ * (int32_t * )& ptlib .stack [8 ] = (int32_t )RTLD_LAZY ;
220
220
} else {
221
- * (uint32_t * )& ptlib .stack [0 ] = (uint64_t )path_addr ;
221
+ * (uint32_t * )& ptlib .stack [0 ] = (uint32_t )path_addr ;
222
222
* (int32_t * )& ptlib .stack [4 ] = (int32_t )RTLD_LAZY ;
223
223
}
224
224
@@ -292,3 +292,123 @@ LM_UnloadModule(const lm_module_t *module)
292
292
293
293
return LM_TRUE ;
294
294
}
295
+
296
+ /********************************/
297
+
298
+ typedef struct {
299
+ lm_address_t dlopen_addr ;
300
+ lm_address_t dlclose_addr ;
301
+ } find_dlfcn_t ;
302
+
303
+ lm_bool_t
304
+ find_dlfcn_symbols_callback (lm_symbol_t * symbol , lm_void_t * arg )
305
+ {
306
+ static const char * dlopen_matches [] = {
307
+ "__libc_dlopen_mode" , "dlopen"
308
+ };
309
+ static const char * dlclose_matches [] = {
310
+ "__libc_dlclose" , "dlclose"
311
+ };
312
+ find_dlfcn_t * parg = (find_dlfcn_t * )arg ;
313
+ size_t i ;
314
+
315
+ for (i = 0 ; i < LM_ARRLEN (dlopen_matches ); ++ i ) {
316
+ if (!strcmp (symbol -> name , dlopen_matches [i ])) {
317
+ parg -> dlopen_addr = symbol -> address ;
318
+ }
319
+ }
320
+
321
+ for (i = 0 ; i < LM_ARRLEN (dlclose_matches ); ++ i ) {
322
+ if (!strcmp (symbol -> name , dlclose_matches [i ])) {
323
+ parg -> dlclose_addr = symbol -> address ;
324
+ }
325
+ }
326
+
327
+ return (parg -> dlopen_addr == LM_ADDRESS_BAD || parg -> dlclose_addr == LM_ADDRESS_BAD ) ? LM_TRUE : LM_FALSE ;
328
+ }
329
+
330
+ LM_API lm_bool_t LM_CALL
331
+ LM_UnloadModuleEx (const lm_process_t * process ,
332
+ const lm_module_t * module )
333
+ {
334
+ lm_bool_t ret = LM_FALSE ;
335
+ lm_module_t dlfcn_mod ;
336
+ find_dlfcn_t dlfcn = { LM_ADDRESS_BAD , LM_ADDRESS_BAD };
337
+ ptrace_libcall_t ptlib ;
338
+ long link_map_iter ;
339
+ struct link_map link_map ;
340
+ char path [LM_PATH_MAX ];
341
+ void * handle = NULL ;
342
+ long call_ret ;
343
+
344
+ if (!process || !module )
345
+ return ret ;
346
+
347
+ dlfcn_mod .base = LM_ADDRESS_BAD ;
348
+ LM_EnumModulesEx (process , find_dlfcn_module_callback , & dlfcn_mod );
349
+ if (dlfcn_mod .base == LM_ADDRESS_BAD )
350
+ return ret ;
351
+
352
+ LM_EnumSymbols (& dlfcn_mod , find_dlfcn_symbols_callback , & dlfcn );
353
+ if (dlfcn .dlopen_addr == LM_ADDRESS_BAD || dlfcn .dlclose_addr == LM_ADDRESS_BAD )
354
+ return ret ;
355
+
356
+ /* Setup arguments both on the stack and on registers to prevent possible issues */
357
+ ptlib .address = dlfcn .dlopen_addr ;
358
+ ptlib .args [0 ] = (long )NULL ;
359
+ ptlib .args [1 ] = RTLD_LAZY ;
360
+ if (process -> bits == 64 ) {
361
+ * (uint64_t * )& ptlib .stack [0 ] = (uint64_t )NULL ;
362
+ * (int32_t * )& ptlib .stack [8 ] = (int32_t )RTLD_LAZY ;
363
+ } else {
364
+ * (uint32_t * )& ptlib .stack [0 ] = (uint32_t )NULL ;
365
+ * (int32_t * )& ptlib .stack [4 ] = (int32_t )RTLD_LAZY ;
366
+ }
367
+
368
+ if (ptrace_attach (process -> pid ))
369
+ goto EXIT ;
370
+
371
+ link_map_iter = ptrace_libcall (process -> pid , process -> bits , & ptlib );
372
+ if (link_map_iter == -1 || link_map_iter == 0 )
373
+ goto DETACH_EXIT ;
374
+
375
+ /* Search for the correct handle, just like in LM_UnloadModule */
376
+ for (; link_map_iter ; link_map_iter = (long )link_map .l_next ) {
377
+ if (ptrace_read (process -> pid , link_map_iter , & link_map , sizeof (link_map )) != sizeof (link_map ))
378
+ goto DETACH_EXIT ;
379
+
380
+ if (ptrace_read (process -> pid , (long )link_map .l_name , path , sizeof (path )) == 0 )
381
+ goto DETACH_EXIT ;
382
+ path [sizeof (path ) - 1 ] = '\0' ;
383
+
384
+ if (!strcmp (path , module -> path )) {
385
+ handle = (void * )link_map_iter ;
386
+ break ;
387
+ }
388
+ }
389
+
390
+ if (!handle ) {
391
+ /* If no handle was found, it means that the module is already unloaded */
392
+ ret = LM_TRUE ;
393
+ goto DETACH_EXIT ;
394
+ }
395
+
396
+ /* Call dlclose with the handle we found */
397
+ ptlib .address = dlfcn .dlclose_addr ;
398
+ ptlib .args [0 ] = (long )handle ;
399
+ if (process -> bits == 64 ) {
400
+ * (uint64_t * )& ptlib .stack [0 ] = (uint64_t )handle ;
401
+ } else {
402
+ * (uint32_t * )& ptlib .stack [0 ] = (uint32_t )handle ;
403
+ }
404
+
405
+ call_ret = ptrace_libcall (process -> pid , process -> bits , & ptlib );
406
+ if (call_ret != 0 )
407
+ goto DETACH_EXIT ;
408
+
409
+ ret = LM_TRUE ;
410
+ DETACH_EXIT :
411
+ ptrace_detach (process -> pid );
412
+ EXIT :
413
+ return ret ;
414
+ }
0 commit comments