Wprowadzenie do Prelink w Gentoo
1.
Wprowadzenie
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.
|
Podsumowanie
-
Prelinkowania dokonuje się przy użyciu programu o nazwie prelink,
który modyfikuje plik wykonywalny tak, aby ten uruchamiał się szybciej.
-
Jeżeli jedna z bibliotek wykorzystywanych przez prelinkowany program ulegnie
modyfikacji, konieczne jest ponowne prelinkowanie programu. W przeciwnym
wypadku zostanie utracony efekt przyśpieszonego uruchamiania. W skrócie, za
każdym razem, kiedy poprzez portage aktualizowany jest pakiet, który
aktualizuje jakieś biblioteki, wszystkie programy, które z nich korzystają
muszą zostać ponownie prelinkowane.
-
Modyfikacje dokonane poleceniem prelink są w pełni odwracalne.
Polecenie to posiada funkcję undo.
-
Aktualne wersje Portage potrafią rozpoznać zmiany w sumach MD5 i znacznikach
czasowych plików wykonywalnych, dokonane w wyniku użycia prelink.
-
Nie ma potrzeby dopisywania FEATURES="prelink" do pliku
make.conf. Portage automatycznie użyje prelinkowania, jeżeli
znajdzie w systemie zainstalowany program prelink.
2.
Instalacja programu Prelink
Instalacja
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.
Przygotowanie systemu
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.
Konfiguracja
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.
|
3.
Prelinkowanie
Użycie polecenia Prelink
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.
|
Prelinkowanie w cronie
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*.
Usuwanie prelinka
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
"Cannot prelink against non-PIC shared library" (Nie można
prelinkować z biblioteką, skompilowaną bez opcji PIC)
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:
-
Biblioteki w pakiecie wine i pochodnych (w tym winex). Prelinkowanie w tym
wypadku i tak nie spowodowałoby przyśpieszenia programów napisanych dla
systemu MS Windows.
-
Biblioteka /usr/lib/liblavfile-1.6.so.0 z pakietu
media-video/mjpegtools.
-
Bliblioteki OpenGL Nvidia,
/usr/lib/opengl/nvidia/lib/libGL.so.*. Z powodu problemów z
wydajnością zostały one skompilowane bez wsparcia dla PIC.
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).
Prelink kończy pracę z błędem "prelink: Can't walk directory tree XXXX: Too
many levels of symbolic links".
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.
5.
Podsumowanie
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.
|