Co to jest Prelink i do czego służy?
Większość aplikacji korzysta ze współdzielonych bibliotek, które muszą zostać załadowane do pamięci w czasie pracy programu, co za każdym razem wiąże się z koniecznością dynamicznego połączenia programu z potrzebnymi mu bibliotekami. W przypadku większości małych programów proces ten trwa bardzo krótko. Jednak w przypadku programów napisanych w języku C++ lub posiadających wiele zależności symbolicznych, proces dynamicznego łączenia może zająć sporo czasu.
W przeciętnym systemie biblioteki rzadko ulegają modyfikacjom, więc kiedy program jest uruchamiany, czynności wykonywane podczas dynamicznego łączenia są zawsze jednakowe. Prelink wykorzystuje ten fakt i dokonuje dynamicznego łączenia tylko raz, po czym zapisuje wyniki na stałe w pliku wykonywalnym programu.
Prelinkowanie może skrócić czas uruchamiania programów. Przykładowo, czas potrzebny do uruchomienia typowego programu dla środowiska KDE może zostać skrócony nawet o 50%. Jedynym obowiązkiem użytkownika jest ponowne uruchomienie polecenia prelink po każdej aktualizacji biblioteki używanej przez prelinkowany program.
Ostrzeżenie: Prelinkowanie nie działa na Hardened Gentoo. Dzieje się tak dlatego, że oba projekty próbują zmienić adresowanie bibliotek współdzielonych. Jednak prelinkowanie z opcją -R przydziela przypadkowe adresy współdzielonym bibliotekom, co w pewnym stopniu zapewnia odpowiedni poziom bezpieczeństwa. |
2. Instalacja programu Prelink
Aby rozpocząć, należy zainstalować program prelink. Podczas jego instalacji wykonywana jest seria testów, mających na celu określenie, czy korzystanie z prelinkowania w danym systemie będzie w pełni bezpieczne.
Listing 2.1: Instalacja polecenia Prelink |
# emerge prelink
|
U części użytkowników instalowanie programu prelink kończy się błędem z powodu niepowodzenia podczas testowania systemu. Testy te zostały wprowadzone ze względów bezpieczeństwa. Można je pominąć, jednak w takim przypadku zachowanie polecenia prelink może być nieobliczalne. Przyczyną niepowodzenia testów jest zwykle nieprawidłowa instalacja podstawowych pakietów systemowych, takich jak binutils, gcc i glibc. Instalacja tych pakietów w podanej kolejności może wpłynąć na poprawę sytuacji i tym samym możliwość instalacji programu prelink bez pomijania testów.
Uwaga: Wskazówka: W przypadku pojawienia się błędu istnieje możliwość ręcznej instalacji programu prelink (./configure ; make ; make check). Jeżeli wystąpił błąd, zawsze można przejrzeć pliki *.log w katalogu zawierającym programy testujące. Z zawartości tych plików można wyłowić przydatne wskazówki, pomocne przy usuwaniu błędu. |
Jeżeli istnieje określona sekwencja kroków, w wyniku której w innym systemie również pojawia się identyczny błąd, należy wysłać ich opis na Bugzillę Gentoo.
Należy również zwrócić uwagę, żeby wśród flag w zmiennych CFLAGS/CXXFLAGS nie znajdowała się opcja -fPIC. W przeciwnym wypadku konieczne będzie jej usunięcie i ponowne przebudowanie całego systemu.
Wywołanie env-update spowoduje wygenerowanie pliku /etc/prelink.conf, w którym zawarta jest lista plików przeznaczonych do prelinkowania.
Listing 2.2: Wywoływanie env-update |
# env-update
|
Niestety nie jest możliwe prelinkowanie programów skompilowanych przy użyciu starych wersji binutils. Większość z tych programów pochodzi z pakietów aplikacji rozpowszechnianych wyłącznie w postaci binarnej, które instalowane są zwykle w katalogu /opt. Utworzenie następującego pliku spowoduje, że wspomniane programy zostaną pominięte podczas prelinkowania.
Listing 2.3: /etc/env.d/60prelink |
PRELINK_PATH_MASK="/opt" |
Uwaga: Można określić więcej katalogów do pominięcia poprzez oddzielenie ich nazw dwukropkami. |
Do prelinkowania wszystkich programów w katalogach wymienionych w pliku /etc/prelink.conf można użyć polecenia:
Listing 3.1: Prelinkowanie wyszczególnionych programów |
# prelink -amR
|
Ostrzeżenie: Jeżeli w systemie jest mało miejsca na dysku, prelinkowanie całego może się skończyć obcięciem i tym samym zniszczeniem niektórych plików wykonywalnych, czego efektem będzie pad systemu. Należy wtedy użyć polecenia file albo readelf, aby szybko sprawdzić stan podejrzanego pliku. Najlepiej jednak, przed prelinkowaniem, sprawdzić ilość wolnego miejsca na dysku wywołując df -h. |
| Opis użytych parametrów: | |
| -a | "All": prelinkuje wszystkie programy. |
| -m | Oszczędzaj pamięć wirtualną. Przydatne w przypadku prelinkowania większej ilości bibliotek. |
| -R | Tryb losowy - przyporządkowuje przypadkowe adresy, co skutkuje wzrostem poziomu bezpieczeństwa poprzez zwiększenie odporności na ataki z wykorzystaniem przepełnienia bufora (buffer overflow). |
Uwaga: Więcej parametrów i szczegółów dotyczących użycia powyższych można odnaleźć na stronie manuala: man prelink. |
Pakiet sys-devel/prelink-20060213 ,i późniejsze, instaluje zadania do wykonania przez cron w pliku /etc/cron.daily/prelink. Aby je uaktywnić należy edytować plik /etc/conf.d/prelink. Dzięki temu prelinkowanie będzie uruchamiane codziennie, zaoszczędzając nam ręcznego wpisywania poleceń.
Przyspieszanie uruchamiania KDE po prelinkowaniu
Czas uruchamiania KDE może zostać znacznie zredukowany w wyniku prelinkowania. Aby dodatkowo skrócić czas uruchamiania KDE, można je skonfigurować tak, aby przestało korzystać z programu kdeinit, który po prelinkowaniu nie jest już potrzebny.
Aby tego dokonać, wystarczy umieścić wiersz KDE_IS_PRELINKED="true" w pliku /etc/env.d/*kdepaths*.
Jeżeli w przyszłości prelink przestanie być porządany w systemie, należy najpierw usunąć zadanie cron z katalogu /etc/cron.daily i pliku /etc/conf.d/prelink. Następnie należy usunąć prelink ze wszystkich plików binarnych:
Listing 3.2: Usuwanie prelinka z plików binarnych |
# prelink -au
|
Na koniec należy usunąć pakiet prelink:
Listing 3.3: Usuwanie prelinka |
# emerge -aC prelink
|
4. Znane problemy i ich rozwiązania
Przyczyną tego problemu jest niewłaściwie skompilowana biblioteka, podczas kompilacji której nie podano parametru -fPIC.
Oto lista bibliotek, które nie zostały poprawione lub których poprawienie nie jest możliwe:
Jeżeli sprawcą problemu jest biblioteka nie ujęta na tej liście, najlepiej zgłosić ten fakt, wraz z łatą (jeśli to możliwe), dodającą we właściwych miejscach flagę -fPIC do CFLAGS.
Po prelinkowaniu systemu niektóre statyczne programy przestają działać.
W systemie opartym na glibc tak naprawdę nie istnieje coś takiego, jak w 100% statyczny program. Skompilowanie programu statycznie w stosunku do glibc nie oznacza, że program nie będzie posiadał innych zależności, w stosunku do innych plików systemowych. Oto, jak problem wyjaśnił Dick Howell:
"Pomysł ze statycznie skompilowanymi programami ma na celu uniezależnienie ich od zainstalowanych w systemie bibliotek. Niestety w Linuksie oraz, jak sądzę, w innych systemach opartych o GLIBC, nie jest to do końca możliwe. Jest np. sprawa biblioteki "libnss" (Name Service Switch, przez niektórych nie wiedzieć czemu, nazywana Network Security System), która udostępnia interfejs dostępu do różnych baz danych uwierzytelniania, informacji sieciowych i wielu innych rzeczy. Ma to na celu uniezależnienie aplikacji od konfiguracji sieciowej konkretnego systemu. Pomysł jest niezły, jednak zmiany w GLIBC mogą powodować problemy z jej załadowaniem. Nie można statycznie włączyć biblioteki "libnss", ponieważ dla każdego systemu jest ona inaczej skonfigurowana. Problem wydaje się leżeć w statycznym linkowaniu innych bibliotek składowych GLIBC, np. "libpthread", "libm" oraz "libc", w wyniku czego powstają niekompatybilne odwołania do funkcji biblioteki "libnss"."
Prelink kończy z błędem "prelink: dso.c:306: fdopen_dso: Assertion `j == k' failed."
Jest to znany problem, przystępnie opisany tutaj. Prelink nie radzi sobie z plikami wykonywalnymi, skompresowanymi programem UPX. Począwszy od prelinka w wersji 20021213 jedynym sposobem ominięcia problemu jest nakazanie poleceniu prelink pominięcie takich programów. W rozdziale Konfiguracja opisano prosty sposób, w jaki można tego dokonać.
Używam grsecurity i mam wrażenie, że prelinkowanie nie działa.
Aby prelinkować programy w systemie używającym grsecurity, z opcją losowego generowania adresów bazowych w funkcji mmap(), konieczne jest WYŁĄCZENIE tej funkcji dla pliku /lib/ld-2.3.*.so. Można tego dokonać przy użyciu polecenia chpax, jednak plik nie może być danym momencie używany przez żaden program (najlepiej zrobić to uruchamiając system z płyty CD).
Błąd ten może oznaczać nadmierny poziom skomplikowania dowiązań symbolicznych. Występuje na przykład, gdy dwa dowiązania wskazują wzajemnie na siebie. Częstym powodem takiego problemu jest na przykład /usr/lib/lib -> lib. Aby naprawić dowiązania, można je zmienić ręcznie lub posłużyć się programem dostarczanym razem z pakietem symlinks:
Listing 4.1: Naprawianie dowiązań |
# emerge symlinks # symlinks -drv / |
Więcej informacji na temat tego błędu można znaleźć w Bugzilli oraz na forum Gentoo.
Prelinkowanie może drastycznie przyspieszyć uruchamianie wielu dużych aplikacji. W dodatku jest ono wspierane przez Portage. Prelinkowanie jest również bezpieczne, ponieważ zawsze można odwrócić ten proces dla dowolnego pliku wykonywalnego, jeżeli sprawia on kłopoty. Wystarczy pamiętać, aby po aktualizacji glibc lub innych bibliotek zawsze ponownie uruchomić prelink w celu uaktualnienia wszystkich programów.
Materiał udostępniany na podstawie licencji Creative Commons - Attribution / Share Alike.