2016-06-09 45 views
6

Jestem zaznajomiony z użyciem dlopen(), aby sprawdzić, czy udostępniona biblioteka została załadowana do procesu przy użyciu wcześniejszego wywołania do dlopen() bez wyzwalania obciążenia, jeśli nie jest obecny, tak jak poniżej:Jak sprawdzić, czy współdzielona biblioteka linux została wstępnie załadowana przy użyciu LD_PRELOAD

void* lib = dlopen(lib_name, RTLD_NOLOAD); 
if (lib != NULL) { 
    ... 
} 

I niedawno starał się zastosować ten sam wzór, aby ustalić, czy jeden z nielicznych bibliotek współdzielonych zostały załadowane do przestrzeni procesowej przy użyciu LD_PRELOAD. Jednak we wszystkich przypadkach wyżej wymienione wywołanie do dlopen() zwraca NULL.

Więc w zasadzie, gdybym rozpocząć proces za pomocą tego wiersza poleceń

LD_PRELOAD=libawesome.so ./mycoolprocess 

a następnie uruchom następujący czek w kodzie w mycoolprocess.c

void* has_awesome = dlopen("libawesome.so", RTLD_NOLOAD); 
if (has_awesome != NULL) { 
    printf("libawesome is available\n"); 
} 

wywołanie dlopen() zawsze zwraca NULL bez względu na to, czy udostępniona biblioteka została załadowana przy użyciu LD_PRELOAD, czy nie. Na podstawie poniższego komentarza Andrew Henle próbowałem również wywołać dlopen z bezwzględną ścieżką do jednego z przeładowanych obiektów udostępnionych, ale dlopen w tym przypadku nadal zwraca wartość NULL, mimo że obiekt współdzielony jest wstępnie ładowany.

Więc moje pytanie jest dwojaki:

  1. Jeżeli powyższe prace wzór dla biblioteki, który został załadowany za pomocą LD_PRELOAD?
  2. Czy istnieje inny sposób sprawdzenia, czy określona biblioteka współużytkowana została wstępnie załadowana?
+0

Czy wstępnie załadowany obiekt udostępniony znajduje się w katalogu będącym częścią wartości 'DT_RPATH' binarnego katalogu' binarnego 'w katalogu, który znajduje się w zmiennej środowiskowej 'LD_LIBRARY_PATH', w'/lib' lub '/ usr/lib', lub inny katalog skonfigurowany za pomocą 'ldconfig'? Jeśli nie, prawdopodobnie musisz podać bezwzględną lub względną ścieżkę do 'dlopen()'. –

+0

Czy program mógł sprawdzić, czy istnieje LD_PRELOAD env var? – jftuga

+0

@AndrewHenle, wstępnie załadowane obiekty wspólne zwykle znajdują się w/usr/lib/x86_64-linux. LD_PRELOAD określa tylko nazwę biblioteki bez bezwzględnej lub względnej ścieżki. –

Odpowiedz

1

Nie i tak, odpowiednio.

dlopen() oraz sztuczka LD_PRELOAD, mimo że obie obsługują biblioteki współdzielone, działają na zasadniczo różne sposoby.

Zmienna środowiskowa LD_PRELOAD jest obsługiwana przez dynamiczny linker/loader (ld-linux.so) i wpływa na rozdzielczość rekordów relokacji w samym pliku wykonywalnym. W skrócie, w każdym punkcie kodu, w którym występuje wywołanie funkcji zdefiniowanej w bibliotece dynamicznej, linker (w czasie kompilacji) wstawi symbol zastępczy adresu pamięci, do którego ma przejść. W środowisku uruchomieniowym zastępcze są zastępowane rzeczywistymi adresami opartymi na bibliotekach współdzielonych ładowanych do pamięci, które same są wymieniane w pliku wykonywalnym, ale mogą być przesłonięte, jeśli używane jest LD_PRELOAD.

Kiedy plik wykonywalny zostanie wczytany do pamięci, a wszystkie symbole zastępcze zostaną wypełnione prawdziwymi adresami, nie ma prostego (ani przenośnego) sposobu informowania o tym, co pochodzi z miejsca. Jednak ...

Możesz może zbadać mapę pamięci uruchomionego procesu. W systemie Linux oznaczałoby to parsowanie za pomocą/proc/<pid>/maps. Zawartość pliku jest dość zrozumiała, więc po prostu wybierz jeden losowo i spójrz.

Nie mam pojęcia, jak to zrobić na innych systemach, ale uważam, że większość współczesnych unixen ma jakiś system plików/proc.