2017-10-11 711 views
0

有沒有辦法在運行時確定哪些共享庫已加載到當前進程的全局符號名稱空間中?我主要對任何因使用RTLD_GLOBAL標誌的dlopen()調用而加載的任何內容感興趣。枚舉通過dlopen加載的共享庫(RTLD_GLOBAL)

我想對審計的目的做到這一點 - 它是我對動態加載的共享庫工作的重要應用程序加載與的RTLD_LOCALdlopen儘可能以不與第三方的代碼相沖突;任何加載到全局符號名稱空間的內容都需要嚴格控制。

我已經看過dl_iterate_phdr() API,但它似乎沒有包含此信息。

+0

那麼,你可以使用例如與RTLD_NOLOAD dlopen的檢查,如果庫已經被加載(如果你有列表),這將返回null或處理,取決於它是否已經被加載。可能對你有幫助的東西可能是/ proc/PID/maps解析/分析。這也可以幫助你[鏈接](https://stackoverflow.com/questions/5103443/how-to-check-what-shared-libraries-are-loaded-at-run-time-for-a-given-process ) –

回答

1

您可以

#define _GNU_SOURCE 
#include <dlfcn.h> 

typedef void *(*orig_dl)(const char *file, int mode); 
void *dlopen(const char *file, int mode) 
{ 
    orig_dl o_dlopen; 
    o_dlopen = (orig_dl)dlsym(RTLD_NEXT, "dlopen"); 
    return o_dlopen(file, mode); 
} 

嘗試使用gcc -shared -fPIC dlo.c -o dlo.so -ldl 添加LD_PRELOAD=dlo.so,在這裏你去編譯它。您可以登錄/跟蹤/打印任何dlopen的使用與特定的模式

0

我認爲這個建議dlopen()使用LD_PRELOAD只是局部解決方案來替換 - 你是不會依賴裝有dlopen()這樣一個圖書館的

最後,我看不出有什麼辦法可以做到這一點,而不需要動態鏈接器本身的內部狀態。它發現從ld.so導出的_rtld_global符號具有該信息,但您必須使用私有的Glibc標頭來解釋它。

以下是一個Python代碼片段(假設我對Glibc源代碼的閱讀是正確的)按全部命名空間中的搜索順序打印所有共享庫。裝載有RTLD_LOCAL的庫不會被打印。

事實上,它依賴於Glibc的實現細節意味着這種方法充滿了危險,但爲了我的測試/審計目的,我認爲它會很好地完成。

import ctypes 

# Abridged type declarations pillaged from Glibc. See: 
# - https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/generic/ldsodefs.h 
# - https://sourceware.org/git/?p=glibc.git;a=blob;f=include/link.h 

class link_map(ctypes.Structure): 
    _fields_ = [ 
     ("l_addr", ctypes.c_size_t), 
     ("l_name", ctypes.c_char_p), 
    ] 


class r_scope_elem(ctypes.Structure): 
    _fields_ = [ 
     ("r_list", ctypes.POINTER(ctypes.POINTER(link_map))), 
     ("r_nlist", ctypes.c_uint), 
    ] 


class rtld_global(ctypes.Structure): 
    _fields_ = [ 
     ("_ns_loaded", ctypes.POINTER(link_map)), 
     ("_ns_nloaded", ctypes.c_uint), 
     ("_ns_main_searchlist", ctypes.POINTER(r_scope_elem)), 
    ] 

_rtld_global = rtld_global.in_dll(ctypes.CDLL(None), "_rtld_global") 
searchlist = _rtld_global._ns_main_searchlist[0] 

print [searchlist.r_list[n][0].l_name for n in xrange(searchlist.r_nlist)] 

在我的CentOS 7系統,該打印:

['', '/lib64/libpython2.7.so.1.0', '/lib64/libpthread.so.0', '/lib64/libdl.so.2', 
'/lib64/libutil.so.1', '/lib64/libm.so.6', '/lib64/libc.so.6', 
'/lib64/ld-linux-x86-64.so.2']