2017-10-11 16 views
0

実行時に、現在のプロセスのグローバルシンボル名前空間にどの共有ライブラリがロードされているかを判断する方法はありますか?私は主にRTLD_GLOBALフラグを使用したdlopen()コールの結果としてロードされたものに興味があります。dlopen(RTLD_GLOBAL)経由でロードされた共有ライブラリの列挙

私は監査目的でこれを実行したいと思っています。動的にロードされる共有ライブラリは、可能であればdlopenRTLD_LOCALでロードされているため、サードパーティのコードと競合しません。グローバルシンボルの名前空間にロードされているものは厳密に制御する必要があります。

私はdl_iterate_phdr() APIを見てきましたが、この情報は含まれていないようです。

+0

をさて、あなたは(あなたがリストを持っている場合)、ライブラリがすでにRTLD_NOLOADでdlopenの例に使用してロードされている場合は、それがnullを返します確認することができます既にロードされているかどうかに応じて、ハンドルまたはハンドルを作成します。おそらくあなたを助けるかもしれない何かは、/ proc/PID /マップ解析/分析でしょう。それはあなたを助けるかもしれません[リンク](https://stackoverflow.com/questions/5103443/how-to-check-what-shared-libraries-are-loaded-at-run-time-for-a-given-process ) –

答えて

1

あなたはLD_PRELOAD=dlo.soを追加し、ここにあなたが行くgcc -shared -fPIC dlo.c -o dlo.so -ldl を使用して、それをコンパイルし

#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); 
} 

で試すことができます。あなたは依存関係dlopen()そのようにロードされたライブラリーのをキャッチしません - あなたは、私は提案はdlopen()が部分的にしか解決策をLD_PRELOADを使用して交換することだと思う特定のモード

0

でトレース/印刷/任意のdlopenの使用状況を記録することができます。

最終的に、ダイナミックリンカそのものの内部状態を傷つけることなくこれを行う方法はありませんでした。情報を持っているが、それを解釈するためにプライベートGlibcヘッダを使用しなければならないことがld.soからエクスポートされた_rtld_globalシンボルがあることがわかりました。

以下はPythonスニペットです(私のGlibcソースの読者が正しいと仮定します)、グローバルネームスペース内のすべての共有ライブラリを検索順に表示します。 RTLD_LOCALがロードされたライブラリは印刷されません。

Glibcの実装の詳細に依存しているという事実は、このアプローチが危険に苦しんでいることを意味しますが、テスト/監査の目的ではうまくいくと思います。私のCentOSの7のシステムで

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)] 

、これは印刷します

['', '/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'] 
関連する問題