Linker-Namespace

Der dynamische Linker löst zwei Herausforderungen im Treble-VNDK-Design:

  • SP-HAL-Bibliotheken und ihre Abhängigkeiten, einschließlich VNDK-SP-Bibliotheken, werden in Framework-Prozesse geladen. Es sollte Mechanismen geben, um Symbolkonflikte zu vermeiden.
  • dlopen() und android_dlopen_ext() können einige Laufzeitabhängigkeiten einführen, die zur Build-Zeit nicht sichtbar sind und mit statischer Analyse nur schwer zu erkennen sind.

Diese beiden Herausforderungen lassen sich mit dem Linker-Namespace-Mechanismus lösen. Dieser Mechanismus wird vom dynamischen Linker bereitgestellt. Damit können die freigegebenen Bibliotheken in verschiedenen Linker-Namespaces isoliert werden, sodass Bibliotheken mit demselben Bibliotheksnamen, aber mit unterschiedlichen Symbolen nicht in Konflikt geraten.

Andererseits bietet der Linker-Namespace-Mechanismus die Flexibilität, dass einige gemeinsam genutzte Bibliotheken von einem Linker-Namespace exportiert und von einem anderen Linker-Namespace verwendet werden können. Diese exportierten freigegebenen Bibliotheken können zu Anwendungsprogrammierschnittstellen werden, die für andere Programme öffentlich sind, während ihre Implementierungsdetails in ihren Linker-Namespaces verborgen bleiben.

/system/lib[64]/libcutils.so und /system/lib[64]/vndk-sp-${VER}/libcutils.so sind beispielsweise zwei freigegebene Bibliotheken. Diese beiden Bibliotheken können unterschiedliche Symbole haben. Sie werden in verschiedene Linker-Namespaces geladen, sodass Framework-Module von /system/lib[64]/libcutils.so und SP-HAL-Shared Libraries von /system/lib[64]/vndk-sp-${VER}/libcutils.so abhängen können.

/system/lib[64]/libc.so ist dagegen ein Beispiel für eine öffentliche Bibliothek, die von einem Linker-Namespace exportiert und in viele Linker-Namespaces importiert wird. Die Abhängigkeiten von /system/lib[64]/libc.so, z. B. libnetd_client.so, werden in den Namespace geladen, in dem sich /system/lib[64]/libc.so befindet. Andere Namespaces haben keinen Zugriff auf diese Abhängigkeiten. Dieser Mechanismus kapselt die Implementierungsdetails und stellt gleichzeitig die öffentlichen Schnittstellen bereit.

Wie funktioniert Android XR?

Der dynamische Linker ist für das Laden der in DT_NEEDED-Einträgen angegebenen gemeinsam genutzten Bibliotheken oder der gemeinsam genutzten Bibliotheken verantwortlich, die durch das Argument von dlopen() oder android_dlopen_ext() angegeben werden. In beiden Fällen sucht der dynamische Linker nach dem Linker-Namespace, in dem sich der Aufrufer befindet, und versucht, die Abhängigkeiten in denselben Linker-Namespace zu laden. Wenn der dynamische Linker die gemeinsam genutzte Bibliothek nicht in den angegebenen Linker-Namespace laden kann, fragt er den verknüpften Linker-Namespace nach exportierten gemeinsam genutzten Bibliotheken.

Format der Konfigurationsdatei

Das Format der Konfigurationsdatei basiert auf dem INI-Dateiformat. Eine typische Konfigurationsdatei sieht so aus:

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}

Die Konfigurationsdatei enthält:

  • Mehrere Eigenschaften für die Zuordnung von Verzeichnisabschnitten am Anfang, damit der dynamische Linker den effektiven Abschnitt auswählen kann.
  • Mehrere Konfigurationsabschnitte für Linker-Namespaces:
    • Jeder Abschnitt enthält mehrere Namespaces (Grafikknoten) und mehrere Fallback-Links zwischen Namespaces (Grafikbögen).
    • Jeder Namespace hat eigene Einstellungen für Isolation, Suchpfade, zulässige Pfade und Sichtbarkeit.

In den folgenden Tabellen wird die Bedeutung der einzelnen Attribute im Detail beschrieben.

Property für die Zuordnung von Verzeichnisbereichen

Attribut Beschreibung Beispiel

dir.name

Ein Pfad zu einem Verzeichnis, für das der Abschnitt [name] gilt.

Jede Eigenschaft ordnet die ausführbaren Dateien im Verzeichnis einem Linker-Namespace-Konfigurationsabschnitt zu. Möglicherweise gibt es zwei oder mehr Properties mit demselben name, die jedoch auf unterschiedliche Verzeichnisse verweisen.

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

Das bedeutet, dass die im Abschnitt [system] angegebene Konfiguration für die ausführbaren Dateien gilt, die entweder aus /system/bin oder /system/xbin geladen werden.

Die im Abschnitt [vendor] angegebene Konfiguration gilt für die ausführbaren Dateien, die aus /vendor/bin geladen werden.

Beziehungsattribute

Attribut Beschreibung Beispiel
additional.namespaces

Eine durch Kommas getrennte Liste zusätzlicher Namespaces (zusätzlich zum Namespace default) für den Abschnitt.

additional.namespaces = sphal,vndk

Das bedeutet, dass es in der [system]-Konfiguration drei Namespaces gibt: default, sphal und vndk.

namespace.name.links

Eine durch Kommas getrennte Liste von Fallback-Namespaces.

Wenn eine gemeinsam genutzte Bibliothek im aktuellen Namespace nicht gefunden werden kann, versucht der dynamische Linker, die gemeinsam genutzte Bibliothek aus den Fallback-Namespaces zu laden. Der Namespace, der am Anfang der Liste angegeben ist, hat eine höhere Priorität.

namespace.sphal.links = default,vndk

Wenn eine gemeinsam genutzte Bibliothek oder eine ausführbare Datei eine gemeinsam genutzte Bibliothek anfordert, die nicht in den Namespace sphal geladen werden kann, versucht der dynamische Linker, die gemeinsam genutzte Bibliothek aus dem Namespace default zu laden.

Wenn die gemeinsam genutzte Bibliothek auch nicht über den Namespace default geladen werden kann, versucht der dynamische Linker, sie über den Namespace vndk zu laden.

Wenn alle Versuche fehlschlagen, gibt der dynamische Linker einen Fehler zurück.

namespace.name.link.other.shared_libs

Eine durch Doppelpunkte getrennte Liste der gemeinsam genutzten Bibliotheken, die in den other-Namespaces durchsucht werden können, wenn diese Bibliotheken nicht im name-Namespace gefunden werden können.

Diese Property kann nicht mit namespace.name.link.other.allow_all_shared_libs verwendet werden.

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

Das bedeutet, dass für den Fallback-Link nur libc.so oder libm.so als angeforderter Bibliotheksname akzeptiert werden. Der dynamische Linker ignoriert den Fallback-Link vom sphal- zum default-Namespace, wenn der angeforderte Bibliotheksname nicht libc.so oder libm.so ist.

namespace.name.link.other.allow_all_shared_libs

Ein boolescher Wert, der angibt, ob alle gemeinsam genutzten Bibliotheken im Namespace other durchsucht werden können, wenn sie im Namespace name nicht gefunden werden.

Diese Property kann nicht mit namespace.name.link.other.shared_libs verwendet werden.

namespace.vndk.link.sphal.allow_all_shared_libs = true

Das bedeutet, dass alle Bibliotheksnamen über den Fallback-Link vom Namespace vndk zum Namespace sphal durchlaufen werden können.

Namespace-Eigenschaften

Attribut Beschreibung Beispiel
namespace.name.isolated

Ein boolescher Wert, der angibt, ob der dynamische Linker prüfen soll, wo sich die gemeinsam genutzte Bibliothek befindet.

Wenn isolated gleich true ist, können nur die freigegebenen Bibliotheken geladen werden, die sich in einem der search.paths-Verzeichnisse (ohne Unterverzeichnisse) oder unter einem der permitted.paths-Verzeichnisse (einschließlich Unterverzeichnisse) befinden.

Wenn isolated den Standardwert false hat, prüft der dynamische Linker den Pfad von gemeinsam genutzten Bibliotheken nicht.

namespace.sphal.isolated = true

Das bedeutet, dass nur die freigegebenen Bibliotheken in search.paths oder unter permitted.paths in den sphal-Namespace geladen werden können.

namespace.name.search.paths

Eine durch Doppelpunkte getrennte Liste von Verzeichnissen, in denen nach gemeinsam genutzten Bibliotheken gesucht werden soll.

Die in search.paths angegebenen Verzeichnisse werden dem angeforderten Bibliotheksnamen vorangestellt, wenn bei Funktionsaufrufen für dlopen()- oder DT_NEEDED-Einträge nicht der vollständige Pfad angegeben wird. Das Verzeichnis, das am Anfang der Liste angegeben ist, hat eine höhere Priorität.

Wenn isolated gleich true ist, können freigegebene Bibliotheken, die sich in einem der search.paths-Verzeichnisse (ohne Unterverzeichnisse) befinden, unabhängig von der permitted.paths-Eigenschaft geladen werden.

Wenn search.paths beispielsweise /system/${LIB} ist und permitted.paths leer ist, kann /system/${LIB}/libc.so geladen werden, /system/${LIB}/vndk/libutils.so jedoch nicht.

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

Das bedeutet, dass der dynamische Linker in /system/${LIB} nach freigegebenen Bibliotheken sucht.

namespace.name.asan.search.paths

Eine durch Doppelpunkte getrennte Liste von Verzeichnissen, in denen nach freigegebenen Bibliotheken gesucht werden soll, wenn AddressSanitizer (ASan) aktiviert ist.

namespace.name.search.paths wird ignoriert, wenn ASan aktiviert ist.

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

Das bedeutet, dass der dynamische Linker bei aktivierter ASan zuerst in /data/asan/system/${LIB} und dann in /system/${LIB} sucht.

namespace.name.permitted.paths

Eine durch Doppelpunkte getrennte Liste von Verzeichnissen (einschließlich Unterverzeichnissen), in denen der dynamische Linker die gemeinsam genutzten Bibliotheken (zusätzlich zu search.paths) laden kann, wenn isolated true ist.

Die gemeinsam genutzten Bibliotheken, die sich in den Unterverzeichnissen von permitted.paths befinden, können ebenfalls geladen werden. Wenn permitted.paths beispielsweise /system/${LIB} ist, können sowohl /system/${LIB}/libc.so als auch /system/${LIB}/vndk/libutils.so geladen werden.

Wenn isolated false ist, werden permitted.paths ignoriert und es wird eine Warnung ausgegeben.

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

Das bedeutet, dass die gemeinsam genutzten Bibliotheken unter /system/${LIB}/hw in den isolierten default-Namespace geladen werden können.

Ohne permitted.paths kann libaudiohal.so beispielsweise /system/${LIB}/hw/audio.a2dp.default.so nicht in den Namespace default laden.

namespace.name.asan.permitted.paths

Eine durch Doppelpunkte getrennte Liste von Verzeichnissen, in denen der dynamische Linker die freigegebenen Bibliotheken laden kann, wenn ASan aktiviert ist.

namespace.name.permitted.paths wird ignoriert, wenn ASan aktiviert ist.

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

Das bedeutet, dass bei aktivierter ASan-Funktion freigegebene Bibliotheken unter /data/asan/system/${LIB}/hw oder /system/${LIB}/hw in den isolierten default-Namespace geladen werden können.

namespace.name.visible

Ein boolescher Wert, der angibt, ob das Programm (außer libc) mit android_get_exported_namespace() ein Linker-Namespace-Handle abrufen und eine gemeinsam genutzte Bibliothek im Linker-Namespace öffnen kann, indem das Handle an android_dlopen_ext() übergeben wird.

Wenn visible true ist, gibt android_get_exported_namespace() immer das Handle zurück, wenn der Namespace vorhanden ist.

Wenn visible false (Standard) ist, gibt android_get_exported_namespace() immer NULL zurück, unabhängig davon, ob der Namespace vorhanden ist. Gemeinsam genutzte Bibliotheken können nur in diesen Namespace geladen werden, wenn (1) sie von einem anderen Linker-Namespace angefordert werden, der einen Fallback-Link zu diesem Namespace hat, oder (2) sie von anderen gemeinsam genutzten Bibliotheken oder ausführbaren Dateien in diesem Namespace angefordert werden.

namespace.sphal.visible = true

Das bedeutet, dass android_get_exported_namespace("sphal") ein gültiges Linker-Namespace-Handle zurückgeben kann.

Namespace für Linker erstellen

In Android 11 wird die Linker-Konfiguration zur Laufzeit unter /linkerconfig erstellt, anstatt Nur-Text-Dateien in ${android-src}/system/core/rootdir/etc zu verwenden. Die Konfiguration wird beim Booten basierend auf der Laufzeitumgebung generiert. Dazu gehören die folgenden Elemente:

  • Wenn das Gerät VNDK unterstützt
  • VNDK-Zielversion der Anbieterpartition
  • VNDK-Version der Produktaufteilung
  • Installierte APEX-Module

Die Linker-Konfiguration wird durch Auflösen von Abhängigkeiten zwischen Linker-Namespaces erstellt. Wenn es beispielsweise Updates für die APEX-Module gibt, die Abhängigkeitsupdates enthalten, wird eine Linker-Konfiguration generiert, die diese Änderungen widerspiegelt. Weitere Informationen zum Erstellen der Linker-Konfiguration finden Sie unter ${android-src}/system/linkerconfig.

Linker-Namespace-Isolation

Es gibt drei Konfigurationstypen. Abhängig vom Wert von PRODUCT_TREBLE_LINKER_NAMESPACES und BOARD_VNDK_VERSION in BoardConfig.mk wird beim Booten die entsprechende Konfiguration generiert.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Ausgewählte Konfiguration VTS-Anforderung
true current VNDK Verpflichtend für Geräte, die bei Markteinführung Android 9 oder höher nutzen
Leer VNDK Lite Erforderlich für Geräte, die bei Markteinführung Android 8.x nutzten
false Leer Legacy Für Geräte, die nicht Treble-kompatibel sind

Bei der VNDK Lite-Konfiguration werden SP-HAL- und VNDK-SP-Bibliotheken isoliert. In Android 8.0 muss dies die Konfigurationsdatei für den dynamischen Linker sein, wenn PRODUCT_TREBLE_LINKER_NAMESPACES true ist.

Die VNDK-Konfiguration isoliert auch SP-HAL- und VNDK-SP-Bibliotheken. Außerdem bietet diese Konfiguration die vollständige Isolation des dynamischen Linkers. So wird sichergestellt, dass Module in der Systempartition nicht von den freigegebenen Bibliotheken in den Anbieterpartitionen abhängen und umgekehrt.

In Android 8.1 oder höher ist die VNDK-Konfiguration die Standardkonfiguration. Es wird dringend empfohlen, die vollständige dynamische Linker-Isolation zu aktivieren, indem Sie BOARD_VNDK_VERSION auf current setzen.

VNDK-Konfiguration

Durch die VNDK-Konfiguration werden die Abhängigkeiten von gemeinsam genutzten Bibliotheken zwischen der Systempartition und den Anbieterpartitionen isoliert. Im Vergleich zu den im vorherigen Unterabschnitt erwähnten Konfigurationen sind die Unterschiede wie folgt:

  • Framework-Prozesse

    • Die Namespaces default, vndk, sphal und rs werden erstellt.
    • Alle Namespaces sind isoliert.
    • Systembibliotheken werden in den Namespace default geladen.
    • SP-HALs werden in den Namespace sphal geladen.
    • VNDK-SP-Bibliotheken, die in den Namespace vndk geladen werden.
  • Anbieterprozesse

    • Die Namespaces default, vndk und system werden erstellt.
    • Der Namespace default ist isoliert.
    • Gemeinsam genutzte Bibliotheken von Anbietern werden in den Namespace default geladen.
    • VNDK- und VNDK-SP-Bibliotheken werden in den Namespace vndk geladen.
    • LL-NDK und seine Abhängigkeiten werden in den Namespace system geladen.

Die Beziehung zwischen den Linker-Namespaces wird unten veranschaulicht.

Linker-Namespace-Diagramm, das in der VNDK-Konfiguration beschrieben wird
Abbildung 1. Linker-Namespace-Isolation (VNDK-Konfiguration)

Im obigen Bild stehen LL-NDK und VNDK-SP für die folgenden gemeinsam genutzten Bibliotheken:

  • 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

Weitere Informationen finden Sie auf dem Gerät unter /linkerconfig/ld.config.txt.

VNDK Lite-Konfiguration

Ab Android 8.0 ist der dynamische Linker so konfiguriert, dass die SP-HAL- und VNDK-SP-Bibliotheken isoliert werden, damit ihre Symbole nicht mit anderen gemeinsam genutzten Framework-Bibliotheken in Konflikt geraten. Die Beziehung zwischen den Linker-Namespaces ist unten dargestellt.

Linker-Namespace-Diagramm, das in der VNDK Lite-Konfiguration beschrieben wird
Abbildung 2: Linker-Namespace-Isolation (VNDK Lite-Konfiguration)

LL-NDK und VNDK-SP stehen für die folgenden gemeinsam genutzten Bibliotheken:

  • LL-NDK
    • libEGL.so
    • libGLESv1_CM.so
    • libGLESv2.so
    • libc.so
    • libdl.so
    • liblog.so
    • libm.so
    • libnativewindow.so
    • libstdc++.so (nicht in der Konfiguration)
    • libsync.so
    • libvndksupport.so
    • libz.so (in der Konfiguration zu VNDK-SP verschoben)
  • 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

In der folgenden Tabelle ist die Namespaces-Konfiguration für Framework-Prozesse aufgeführt, die aus dem Abschnitt [system] in der VNDK Lite-Konfiguration stammt.

Namespace Attribut Wert
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 (für 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 (für 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 (für kompilierte RS-Kernel)
isolated true
visible true
links default,vndk
link.default.shared_libs LL-NDK
libmediandk.so
libft2.so
link.vndk.shared_libs VNDK-SP

In der folgenden Tabelle ist die Namespace-Konfiguration für Anbieterprozesse aufgeführt. Sie ist ein Auszug aus dem Abschnitt [vendor] in der VNDK Lite-Konfiguration.

Namespace Attribut Wert
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} (verworfen)
/product/${LIB} (verworfen)
isolated false

Weitere Informationen finden Sie auf dem Gerät unter /linkerconfig/ld.config.txt.

Dokumentverlauf

Änderungen bei Android 11

  • In Android 11 werden die statischen ld.config.*.txt-Dateien aus der Codebasis entfernt und stattdessen zur Laufzeit von LinkerConfig generiert.

Änderungen bei Android 9

  • In Android 9 wird der Linker-Namespace vndk zu Vendor-Prozessen hinzugefügt und gemeinsam genutzte VNDK-Bibliotheken werden vom Standard-Linker-Namespace isoliert.
  • Ersetzen Sie PRODUCT_FULL_TREBLE durch eine spezifischere PRODUCT_TREBLE_LINKER_NAMESPACES.
  • In Android 9 wurden die Namen der folgenden Konfigurationsdateien für den dynamischen Linker geändert.
    Android 8.x Android 9 Beschreibung
    ld.config.txt.in ld.config.txt Für Geräte mit Laufzeit-Linker-Namespace-Isolation
    ld.config.txt ld.config.vndk_lite.txt Für Geräte mit VNDK-SP-Linker-Namespace-Isolation
    ld.config.legacy.txt ld.config.legacy.txt Für ältere Geräte mit Android 7.x oder niedriger
  • android.hardware.graphics.allocator@2.0.so entfernen
  • Die Partitionen product und odm werden hinzugefügt.