2017-10-11 12 views
0

Existe-t-il un moyen de déterminer au moment de l'exécution quelles bibliothèques partagées ont été chargées dans l'espace de noms de symboles global du processus en cours? Je suis principalement intéressé par tout ce qui a été chargé à la suite d'un appel dlopen() qui a utilisé le drapeau RTLD_GLOBAL. Je veux le faire à des fins d'audit - il est important pour une application sur laquelle je travaille que les bibliothèques partagées chargées dynamiquement soient chargées avec RTLD_LOCAL dans la mesure du possible afin de ne pas entrer en conflit avec le code tiers; Tout ce qui est chargé dans l'espace de noms des symboles globaux doit être étroitement contrôlé.Énumération des bibliothèques partagées chargées via dlopen (RTLD_GLOBAL)

J'ai regardé l'API dl_iterate_phdr(), mais il ne semble pas inclure cette information.

+0

Eh bien, vous pouvez vérifier si la bibliothèque est déjà chargée (si vous avez la liste) en utilisant par exemple dlopen avec RTLD_NOLOAD, qui renverra nulle ou gérer, selon si elle a déjà été chargée ou non. Quelque chose qui peut vous aider est probablement/proc/PID/maps analyse/analyse. Cela peut aussi vous aider [link] (https://stackoverflow.com/questions/5103443/how-to-check-what-shared-libraries-are-loaded-at-run-time-for-a-given-process) –

Répondre

1

Vous pouvez essayer avec

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

compiler à l'aide gcc -shared -fPIC dlo.c -o dlo.so -ldl ajouter LD_PRELOAD=dlo.so et ici vous allez. Vous pouvez vous connecter/trace/imprimer toute utilisation dlopen avec mode spécifique

0

Je pense que la suggestion de remplacer dlopen() utilise LD_PRELOAD est seulement une solution partielle - vous ne serez pas attraper dépendances d'une bibliothèque chargée de dlopen() cette façon. En fin de compte, je ne voyais aucun moyen de le faire sans gratter l'état interne du lieur dynamique lui-même. Il a trouvé qu'il y a un symbole _rtld_global exporté de ld.so qui a l'information, mais que vous devez utiliser des en-têtes Glibc privés pour l'interpréter. Ce qui suit est un extrait Python qui (en supposant que ma lecture des sources Glibc est correcte) imprime toutes les bibliothèques partagées dans l'espace de noms global dans l'ordre dans lequel elles seront recherchées. Les bibliothèques chargées avec RTLD_LOCAL ne seront pas imprimées. Le fait qu'il repose sur les détails de mise en œuvre de Glibc signifie que cette approche est lourde de dangers, mais à mes fins de test/d'audit, je pense que tout ira bien.

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

Sur mon CentOS système 7, cette impression:

['', '/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']