Wspólne biblioteki ELF - motywacja do PLT


11

Czy można użyć kodu samomodyfikującego do przyspieszenia wywoływania funkcji w dynamicznie połączonych bibliotekach?

O ile rozumiem, biblioteki współdzielone ELF używają pewnego rodzaju pośredniej tablicy skoków (tabela łączenia procedur lub PLT), aby umożliwić leniwe wiązanie funkcji bibliotecznych. Wydaje się, że celem jest uniknięcie konieczności modyfikowania tabeli w segmencie kodu, jednocześnie umożliwiając leniwe rozwiązywanie pozycji funkcji przy pierwszym wywołaniu.

Czy nie byłoby szybciej dynamicznie tworzyć kodu dla tej tabeli w czasie ładowania, a może nawet przy pierwszym wywołaniu funkcji?

Czy ma to umożliwić udostępnianie segmentu kodu między procesami w jak największym stopniu (dynamiczna tabela byłaby prywatna dla procesu)? Czy to ze względów bezpieczeństwa (kod do zapisu nie powinien być wykonywalny - ale JIT robią to cały czas, a moduł ładujący może dodawać i usuwać uprawnienia przed uruchomieniem programu)?

A może jest to kombinacja tych działań, a niewielki wzrost wydajności na wywołanie funkcji po prostu nie byłby wart wysiłku?

Odpowiedzi:


8

Przypuszczam, że mówimy o architekturze x86.

Nie można mieć kodu samodopasowującego się w trybie chronionym , który jest używany przez większość systemów operacyjnych opartych na UNIX (i nie tylko), o których wiem, ponieważ segmenty kodu są zawsze tylko do odczytu. Program ładujący nie kontroluje tego, że jest to coś, co jest obsługiwane przez podsystem zarządzania pamięcią jądra.

Ale nawet gdybyś mógł „utworzyć kod dla tej tabeli w czasie ładowania”, tak jak mówisz, byłby to sprzeczny z celem bibliotek współdzielonych. W ten sposób każdy proces miałby „prywatną” kopię funkcji biblioteki w swojej przestrzeni adresowej, skutecznie zwiększając powierzchnię pamięci - jednym z powodów, dla których tworzone były biblioteki wspólne, było rozwiązanie tego problemu.

Cały proces, który opisujesz, jest dość złożony i kosztowałby więcej cykli przetwarzania niż stosowana obecnie metoda PLT i prawdopodobnie wprowadziłby więcej nowych, interesujących problemów bezpieczeństwa.


2
Możesz użyć wywołania systemowego mprotect (2), aby strony z segmentami .text były zapisywalne i wykonywalne.
Bruce Ediger

1
Zgadza się, proszę pana. Prawdopodobnie działałoby to przyzwoicie na przeciętnym systemie UNIX, ale cały proces łączenia zostałby przerwany, gdy tylko ktoś spróbuje zahartować system np. PaX, który wymusza ograniczenia na mprotect (2).
dkaragasidis

(Wygląda na to, że w poprzednim komentarzu nie wspomniałem o @BruceEdiger)
dkaragasidis

1

OSD ELF mogą użyć flagi (DF_TEXREL), aby ogłosić, że wymagają ponownego przydzielenia poprzez zmianę sekcji tekstowej (która zwykle jest tylko do odczytu). Podejście do tabeli skoków wraz z kodem niezależnym od pozycji PIE powinny być jednak bardziej optymalne.

(Znaleziono to w http://www.akkadia.org/drepper/dsohowto.pdf , ale inne zasoby również o tym wspominają).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.