Przestrzeń nazw konsolidatora

Dynamiczny linker stawia czoła dwóm wyzwaniom w projektowaniu Treble VNDK:

  • Biblioteki współdzielone SP-HAL i ich zależności, w tym biblioteki VNDK-SP, są ładowane do procesów frameworka. Powinny istnieć pewne mechanizmy zapobiegające konfliktom symboli.
  • dlopen() i android_dlopen_ext() mogą wprowadzić pewne zależności w czasie wykonywania, które nie są widoczne w czasie kompilacji i mogą być trudne do wykrycia za pomocą analizy statycznej.

Te dwa wyzwania można rozwiązać za pomocą mechanizmu przestrzeni nazw linkera . Mechanizm ten zapewnia dynamiczny linker. Może izolować biblioteki współdzielone w różnych przestrzeniach nazw linkerów, dzięki czemu biblioteki o tej samej nazwie biblioteki, ale z różnymi symbolami, nie będą powodować konfliktów.

Z drugiej strony mechanizm przestrzeni nazw konsolidatora zapewnia elastyczność, dzięki czemu niektóre biblioteki współdzielone mogą być eksportowane przez przestrzeń nazw konsolidatora i używane przez inną przestrzeń nazw konsolidatora. Te wyeksportowane biblioteki współdzielone mogą stać się interfejsami programowania aplikacji, które są publiczne dla innych programów, ukrywając jednocześnie szczegóły ich implementacji w przestrzeniach nazw konsolidatora.

Na przykład /system/lib[64]/libcutils.so i /system/lib[64]/vndk-sp-${VER}/libcutils.so to dwie biblioteki współdzielone. Te dwie biblioteki mogą mieć różne symbole. Są ładowane do różnych przestrzeni nazw linkerów, więc moduły frameworku mogą zależeć od /system/lib[64]/libcutils.so , a biblioteki współdzielone SP-HAL mogą zależeć od /system/lib[64]/vndk-sp-${VER}/libcutils.so .

Z drugiej strony /system/lib[64]/libc.so jest przykładem biblioteki publicznej, która jest eksportowana przez przestrzeń nazw konsolidatora i importowana do wielu przestrzeni nazw konsolidatora. Zależności pliku /system/lib[64]/libc.so , takie jak libnetd_client.so , są ładowane do przestrzeni nazw, w której znajduje się /system/lib[64]/libc.so . Inne przestrzenie nazw nie będą miały dostępu do tych zależności. Mechanizm ten hermetyzuje szczegóły implementacji, zapewniając jednocześnie interfejsy publiczne.

Jak to działa?

Linker dynamiczny odpowiada za ładowanie bibliotek współdzielonych określonych we wpisach DT_NEEDED lub bibliotek współdzielonych określonych przez argument dlopen() lub android_dlopen_ext() . W obu przypadkach dynamiczny linker znajduje przestrzeń nazw linkera, w której znajduje się obiekt wywołujący, i próbuje załadować zależności do tej samej przestrzeni nazw linkera. Jeśli dynamiczny linker nie może załadować biblioteki współdzielonej do określonej przestrzeni nazw konsolidatora, pyta połączoną przestrzeń nazw konsolidatora o wyeksportowane biblioteki współdzielone.

Format pliku konfiguracyjnego

Format pliku konfiguracyjnego opiera się na formacie pliku INI. Typowy plik konfiguracyjny wygląda następująco:

dir.system = /system/bin
dir.system = /system/xbin
dir.vendor = /vendor/bin

[system]
additional.namespaces = sphal,vndk

namespace.default.isolated = true
namespace.default.search.paths = /system/${LIB}
namespace.default.permitted.paths = /system/${LIB}/hw
namespace.default.asan.search.paths = /data/asan/system/${LIB}:/system/${LIB}
namespace.default.asan.permitted.paths = /data/asan/system/${LIB}/hw:/system/${LIB}/hw

namespace.sphal.isolated = true
namespace.sphal.visible = true
namespace.sphal.search.paths = /odm/${LIB}:/vendor/${LIB}
namespace.sphal.permitted.paths = /odm/${LIB}:/vendor/${LIB}
namespace.sphal.asan.search.paths  = /data/asan/odm/${LIB}:/odm/${LIB}
namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}:/vendor/${LIB}
namespace.sphal.asan.permitted.paths  = /data/asan/odm/${LIB}:/odm/${LIB}
namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}:/vendor/${LIB}
namespace.sphal.links = default,vndk
namespace.sphal.link.default.shared_libs = libc.so:libm.so
namespace.sphal.link.vndk.shared_libs = libbase.so:libcutils.so

namespace.vndk.isolated = true
namespace.vndk.search.paths = /system/${LIB}/vndk-sp-29
namespace.vndk.permitted.paths = /system/${LIB}/vndk-sp-29
namespace.vndk.links = default
namespace.vndk.link.default.shared_libs = libc.so:libm.so

[vendor]
namespace.default.isolated = false
namespace.default.search.paths = /vendor/${LIB}:/system/${LIB}

Plik konfiguracyjny zawiera:

  • Na początku kilka właściwości mapowania sekcji katalogów, aby dynamiczny linker mógł wybrać efektywną sekcję.
  • Kilka sekcji konfiguracyjnych przestrzeni nazw linkera:
    • Każda sekcja zawiera kilka przestrzeni nazw (wierzchołki wykresu) i kilka zastępczych łączy między przestrzeniami nazw (łuki wykresu).
    • Każda przestrzeń nazw ma własną izolację, ścieżki wyszukiwania, dozwolone ścieżki i ustawienia widoczności.

Poniższe tabele szczegółowo opisują znaczenie każdej właściwości.

Właściwość mapowania sekcji katalogu

Nieruchomość Opis Przykład

dir. name

Ścieżka do katalogu, którego dotyczy sekcja [ name ] .

Każda właściwość odwzorowuje pliki wykonywalne w katalogu na sekcję konfiguracji przestrzeni nazw konsolidatora. Mogą istnieć dwie (lub więcej) właściwości o tej samej name , ale wskazujących różne katalogi.

dir.system = /system/bin
dir.system = /system/xbin
dir.vendor = /vendor/bin

Oznacza to, że konfiguracja określona w sekcji [system] dotyczy plików wykonywalnych ładowanych z /system/bin lub /system/xbin .

Konfiguracja określona w sekcji [vendor] dotyczy plików wykonywalnych ładowanych z /vendor/bin .

Właściwości relacji

Nieruchomość Opis Przykład
additional. namespaces

Rozdzielana przecinkami lista dodatkowych przestrzeni nazw (oprócz default przestrzeni nazw) dla sekcji.

additional. namespaces = sphal, vndk

Oznacza to, że w konfiguracji [system] istnieją trzy przestrzenie nazw ( default , sphal i vndk ).

namespace. name . links

Rozdzielana przecinkami lista zastępczych przestrzeni nazw.

Jeśli w bieżącej przestrzeni nazw nie można znaleźć biblioteki współdzielonej, linker dynamiczny próbuje załadować bibliotekę współdzieloną z rezerwowych przestrzeni nazw. Przestrzeń nazw określona na początku listy ma wyższy priorytet.

namespace. sphal. links = default, vndk

Jeśli biblioteka współdzielona lub plik wykonywalny żąda biblioteki współdzielonej, której nie można załadować do przestrzeni nazw sphal , linker dynamiczny próbuje załadować bibliotekę współdzieloną z default przestrzeni nazw.

Następnie, jeśli nie można załadować biblioteki współdzielonej z default przestrzeni nazw, linker dynamiczny próbuje załadować bibliotekę współdzieloną z przestrzeni nazw vndk .

Na koniec, jeśli wszystkie próby zawiodą, dynamiczny linker zwróci błąd.

namespace. name . link. other . shared_libs

Rozdzielana dwukropkami lista bibliotek współdzielonych, które można przeszukiwać w other przestrzeniach nazw, jeśli tych bibliotek nie można znaleźć w przestrzeni name .

Tej właściwości nie można używać z namespace. name . link. other . allow_all_shared_libs .

namespace. sphal. link. default. shared_libs = libc.so: libm.so

Oznacza to, że łącze rezerwowe akceptuje tylko libc.so lub libm.so jako żądaną nazwę biblioteki. Dynamiczny linker ignoruje łącze rezerwowe ze sphal do default przestrzeni nazw, jeśli żądana nazwa biblioteki nie jest libc.so lub libm.so .

namespace. name . link. other . allow_all_shared_libs

Wartość logiczna wskazująca, czy wszystkie biblioteki współdzielone mogą być przeszukiwane w other przestrzeni nazw, jeśli tych bibliotek nie można znaleźć w przestrzeni name .

Tej właściwości nie można używać z namespace. name . link. other . shared_libs .

namespace. vndk. link. sphal. allow_all_shared_libs = true

Oznacza to, że wszystkie nazwy bibliotek mogą przechodzić przez łącze rezerwowe z przestrzeni vndk do przestrzeni nazw sphal .

Właściwości przestrzeni nazw

Nieruchomość Opis Przykład
namespace. name . isolated

Wartość logiczna wskazująca, czy linker dynamiczny powinien sprawdzać, gdzie znajduje się biblioteka współdzielona.

Jeśli isolated ma true , można załadować tylko biblioteki współdzielone, które znajdują się w jednym z katalogów search.paths (z wyłączeniem podkatalogów) lub w jednym z permitted.paths katalogów (w tym podkatalogach).

Jeśli isolated ma false (domyślnie), linker dynamiczny nie sprawdza ścieżki bibliotek współdzielonych.

namespace. sphal. isolated = true

Oznacza to, że do przestrzeni nazw sphal można załadować tylko biblioteki współdzielone znajdujące się w search.paths lub permitted.paths .

namespace. name . search.paths

Rozdzielana dwukropkami lista katalogów do wyszukiwania bibliotek współdzielonych.

Katalogi określone w search.paths są dołączane do żądanej nazwy biblioteki, jeśli wywołania funkcji dlopen() lub wpisy DT_NEEDED nie określają pełnej ścieżki. Katalog określony na początku listy ma wyższy priorytet.

Jeśli isolated ma true , biblioteki współdzielone znajdujące się w jednym z katalogów search.paths (z wyłączeniem podkatalogów) mogą być ładowane niezależnie od właściwości permitted.paths .

Na przykład, jeśli search.paths to /system/${LIB} a permitted.paths są puste, /system/${LIB}/libc.so można załadować, ale /system/${LIB}/vndk/libutils.so nie można załadować.

namespace. default. search.paths = /system/${LIB}

Oznacza to, że dynamiczny linker przeszukuje /system/${LIB} w poszukiwaniu bibliotek współdzielonych.

namespace. name . asan.search.paths

Rozdzielana dwukropkami lista katalogów, w których należy wyszukiwać biblioteki współdzielone, gdy włączony jest program AddressSanitizer (ASan) .

namespace. name . search.paths jest ignorowane, gdy włączony jest ASan .

namespace. default. asan.search.paths = /data/asan/system/${LIB}: /system/${LIB}

Oznacza to, że gdy ASan jest włączony, dynamiczny linker przeszukuje najpierw /data/asan/system/${LIB} a następnie /system/${LIB} .

namespace. name . permitted.paths

Rozdzielana dwukropkami lista katalogów (w tym podkatalogów), z których dynamiczny linker może załadować biblioteki współdzielone (oprócz search.paths ), gdy isolated , ma true .

Można także załadować biblioteki współdzielone znajdujące się w podkatalogach permitted.paths . Na przykład, jeśli permitted.paths jest /system/${LIB} , można załadować zarówno /system/${LIB}/libc.so , jak i /system/${LIB}/vndk/libutils.so .

Jeśli isolated ma false , permitted.paths są ignorowane i emitowane jest ostrzeżenie.

namespace. default. permitted.paths = /system/${LIB}/hw

Oznacza to, że biblioteki współdzielone z /system/${LIB}/hw można załadować do izolowanej default przestrzeni nazw.

Na przykład bez permitted.paths libaudiohal.so nie może załadować /system/${LIB}/hw/audio.a2dp.default.so do default przestrzeni nazw.

namespace. name . asan.permitted.paths

Rozdzielana dwukropkami lista katalogów, w których dynamiczny linker może załadować biblioteki współdzielone, gdy włączony jest ASan .

namespace. name . permitted.paths jest ignorowany, gdy włączona jest opcja ASan .

namespace. default. asan.permitted.paths = /data/asan/system/${LIB}/hw: /system/${LIB}/hw

Oznacza to, że gdy włączony jest ASan , biblioteki współdzielone w /data/asan/system/${LIB}/hw lub /system/${LIB}/hw mogą zostać załadowane do izolowanej default przestrzeni nazw.

namespace. name . visible

Wartość logiczna wskazująca, czy program (inny niż libc ) może uzyskać uchwyt przestrzeni nazw linkera za pomocą android_get_exported_namespace() i otworzyć bibliotekę współdzieloną w przestrzeni nazw linkera, przekazując uchwyt do android_dlopen_ext() .

Jeśli visible ma true , android_get_exported_namespace() zawsze zwraca uchwyt, jeśli przestrzeń nazw istnieje.

Jeśli visible ma false (domyślnie), android_get_exported_namespace() zawsze zwraca NULL niezależnie od obecności przestrzeni nazw. Biblioteki współdzielone można załadować do tej przestrzeni nazw tylko wtedy, gdy (1) zażąda ich inna przestrzeń nazw konsolidatora, która ma zastępczy link do tej przestrzeni nazw, lub (2) zażądają ich inne biblioteki współdzielone lub pliki wykonywalne w tej przestrzeni nazw.

namespace. sphal. visible = true

Oznacza to, że android_get_exported_namespace("sphal") może zwrócić prawidłowy uchwyt przestrzeni nazw linkera.

Tworzenie przestrzeni nazw linkera

W Androidzie 11 konfiguracja linkera jest tworzona w czasie wykonywania w /linkerconfig zamiast używać zwykłych plików tekstowych w ${android-src}/system/core/rootdir/etc . Konfiguracja jest generowana podczas uruchamiania systemu na podstawie środowiska wykonawczego, które obejmuje następujące elementy:

  • Jeśli urządzenie obsługuje VNDK
  • Docelowa wersja VNDK partycji dostawcy
  • Wersja VNDK partycji produktu
  • Zainstalowane moduły APEX

Konfiguracja linkera jest tworzona poprzez rozwiązanie zależności pomiędzy przestrzeniami nazw linkera. Na przykład, jeśli istnieją jakieś aktualizacje modułów APEX, które obejmują aktualizacje zależności, generowana jest konfiguracja linkera odzwierciedlająca te zmiany. Więcej szczegółów na temat tworzenia konfiguracji linkera można znaleźć w ${android-src}/system/linkerconfig .

Izolacja przestrzeni nazw linkera

Istnieją trzy typy konfiguracji. W zależności od wartości PRODUCT_TREBLE_LINKER_NAMESPACES i BOARD_VNDK_VERSION w BoardConfig.mk , podczas rozruchu generowana jest odpowiednia konfiguracja.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Wybrana konfiguracja Wymóg VTS
true current VNDK Obowiązkowe w przypadku urządzeń z systemem Android 9 lub nowszym
Pusty VNDK Lite Obowiązkowe dla urządzeń z systemem Android 8.x
false Pusty Legacy Dla urządzeń innych niż Treble

Konfiguracja VNDK Lite izoluje współdzielone biblioteki SP-HAL i VNDK-SP. W systemie Android 8.0 musi to być plik konfiguracyjny dynamicznego linkera, jeśli PRODUCT_TREBLE_LINKER_NAMESPACES ma true .

Konfiguracja VNDK izoluje także biblioteki współdzielone SP-HAL i VNDK-SP. Dodatkowo ta konfiguracja zapewnia pełną dynamiczną izolację linkera. Zapewnia to, że moduły w partycji systemowej nie będą zależne od bibliotek współdzielonych w partycjach dostawcy i odwrotnie.

W systemie Android 8.1 lub nowszym konfiguracja VNDK jest konfiguracją domyślną i zdecydowanie zaleca się włączenie pełnej dynamicznej izolacji linkera poprzez ustawienie BOARD_VNDK_VERSION na current .

Konfiguracja VNDK

Konfiguracja VNDK izoluje zależności bibliotek współdzielonych pomiędzy partycją systemową a partycjami dostawcy. W porównaniu z konfiguracjami wspomnianymi w poprzednim podrozdziale różnice przedstawiono w następujący sposób:

  • Procesy ramowe

    • tworzone są przestrzenie nazw default , vndk , sphal i rs .
    • Wszystkie przestrzenie nazw są izolowane.
    • Systemowe biblioteki współdzielone są ładowane do default przestrzeni nazw.
    • SP-HAL są ładowane do przestrzeni nazw sphal .
    • Biblioteki współdzielone VNDK-SP załadowane do przestrzeni nazw vndk .
  • Procesy dostawców

    • tworzone są default przestrzenie nazw, vndk i system .
    • default przestrzeń nazw jest izolowana.
    • Biblioteki współdzielone dostawcy są ładowane do default przestrzeni nazw.
    • Biblioteki współdzielone VNDK i VNDK-SP są ładowane do przestrzeni nazw vndk .
    • LL-NDK i jego zależności są ładowane do system przestrzeni nazw.

Poniżej zilustrowano relację pomiędzy przestrzeniami nazw linkerów.

Wykres przestrzeni nazw linkera opisany w konfiguracji VNDK
Rysunek 1. Izolacja przestrzeni nazw linkera (konfiguracja VNDK)

Na powyższym obrazku LL-NDK i VNDK-SP oznaczają następujące biblioteki współdzielone:

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libGLESv3.so
    • libandroid_net.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libneuralnetworks.so
    • libsync.so
    • libvndksupport.so
    • libvulkan.so
  • VNDK-SP
    • android.hardware.graphics.common@1.0.so
    • android.hardware.graphics.mapper@2.0.so
    • android.hardware.renderscript@1.0.so
    • android.hidl.memory@1.0.so
    • libRSCpuRef.so
    • libRSDriver.so
    • libRS_internal.so
    • libbase.so
    • libbcinfo.so
    • libc++.so
    • libcutils.so
    • libhardware.so
    • libhidlbase.so
    • libhidlmemory.so
    • libhidltransport.so
    • libhwbinder.so
    • libion.so
    • libutils.so
    • libz.so

Więcej szczegółów można znaleźć w /linkerconfig/ld.config.txt z urządzenia.

Konfiguracja VNDK Lite

Począwszy od wersji Androida 8.0, dynamiczny linker jest skonfigurowany tak, aby izolować biblioteki współdzielone SP-HAL i VNDK-SP, tak aby ich symbole nie kolidowały z innymi bibliotekami współdzielonymi platformy. Poniżej pokazano relację pomiędzy przestrzeniami nazw linkera.

Wykres przestrzeni nazw linkera opisany w konfiguracji VNDK Lite
Rysunek 2. Izolacja przestrzeni nazw linkera (konfiguracja VNDK Lite)

LL-NDK i VNDK-SP oznaczają następujące biblioteki współdzielone:

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libstdc++.so (nie w konfiguracji)
    • libsync.so
    • libvndksupport.so
    • libz.so (przeniesiony do VNDK-SP w konfiguracji)
  • VNDK-SP
    • android.hardware.graphics.common@1.0.so
    • android.hardware.graphics.mapper@2.0.so
    • android.hardware.renderscript@1.0.so
    • android.hidl.memory@1.0.so
    • libbase.so
    • libc++.so
    • libcutils.so
    • libhardware.so
    • libhidlbase.so
    • libhidlmemory.so
    • libhidltransport.so
    • libhwbinder.so
    • libion.so
    • libutils.so

Poniższa tabela zawiera konfigurację przestrzeni nazw dla procesów frameworkowych, która została zaczerpnięta z sekcji [system] w konfiguracji VNDK Lite.

Przestrzeń nazw Nieruchomość Wartość
default search.paths /system/${LIB}
/odm/${LIB}
/vendor/${LIB}
/product/${LIB}
isolated false
sphal search.paths /odm/${LIB}
/vendor/${LIB}
permitted.paths /odm/${LIB}
/vendor/${LIB}
isolated true
visible true
links default,vndk,rs
link.default.shared_libs LL-NDK
link.vndk.shared_libs VNDK-SP
link.rs.shared_libs libRS_internal.so
vndk (dla VNDK-SP) search.paths /odm/${LIB}/vndk-sp
/vendor/${LIB}/vndk-sp
/system/${LIB}/vndk-sp-${VER}
permitted.paths /odm/${LIB}/hw
/odm/${LIB}/egl
/vendor/${LIB}/hw
/vendor/${LIB}/egl
/system/${LIB}/vndk-sp-${VER}/hw
isolated true
visible true
links default
link.default.shared_libs LL-NDK
rs (dla RenderScript) search.paths /odm/${LIB}/vndk-sp
/vendor/${LIB}/vndk-sp
/system/${LIB}/vndk-sp-${VER}
/odm/${LIB}
/vendor/${LIB}
permitted.paths /odm/${LIB}
/vendor/${LIB}
/data (dla skompilowanego jądra RS)
isolated true
visible true
links default,vndk
link.default.shared_libs LL-NDK
libmediandk.so
libft2.so
link.vndk.shared_libs VNDK-SP

Poniższa tabela przedstawia konfigurację przestrzeni nazw dla procesów dostawców, która została zaczerpnięta z sekcji [vendor] w konfiguracji VNDK Lite.

Przestrzeń nazw Nieruchomość Wartość
default search.paths /odm/${LIB}
/odm/${LIB}/vndk
/odm/${LIB}/vndk-sp
/vendor/${LIB}
/vendor/${LIB}/vndk
/vendor/${LIB}/vndk-sp
/system/${LIB}/vndk-${VER}
/system/${LIB}/vndk-sp-${VER}
/system/${LIB} (przestarzałe)
/product/${LIB} (przestarzałe)
isolated false

Więcej szczegółów można znaleźć w /linkerconfig/ld.config.txt z urządzenia.

Historia dokumentu

Zmiany w Androidzie 11

  • W systemie Android 11 statyczne pliki ld.config.*.txt są usuwane z bazy kodu, a zamiast tego LinkerConfig generuje je w czasie wykonywania.

Zmiany w Androidzie 9

  • W systemie Android 9 przestrzeń nazw konsolidatora vndk jest dodawana do procesów dostawcy, a biblioteki współdzielone VNDK są izolowane od domyślnej przestrzeni nazw konsolidatora.
  • Zastąp PRODUCT_FULL_TREBLE bardziej szczegółowym PRODUCT_TREBLE_LINKER_NAMESPACES .
  • Android 9 zmienia nazwy następujących plików konfiguracyjnych dynamicznego linkera.
    Android 8.x Androida 9 Opis
    ld.config.txt.in ld.config.txt Dla urządzeń z izolacją przestrzeni nazw konsolidatora środowiska wykonawczego
    ld.config.txt ld.config.vndk_lite.txt Dla urządzeń z izolacją przestrzeni nazw linkera VNDK-SP
    ld.config.legacy.txt ld.config.legacy.txt Dla starszych urządzeń z systemem Android 7.x lub starszym
  • Usuń android.hardware.graphics.allocator@2.0.so .
  • dodawane są partycje product i odm .