Verknüpfungs-Namespace

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

  • Gemeinsam genutzte 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 Buildzeit nicht sichtbar sind und mithilfe einer statischen Analyse nur schwer zu erkennen sind.

Diese beiden Herausforderungen können mit dem Linker-Namespace gelöst werden. Dieser Mechanismus wird vom dynamischen Linker bereitgestellt. Es kann die freigegebenen Bibliotheken in verschiedenen Linker-Namespaces unterbringen, damit Bibliotheken mit demselben Bibliotheksnamen, aber unterschiedlichen Symbolen, nicht in Konflikt stehen.

Andererseits bietet der Linker-Namespace-Mechanismus die Flexibilität, dass einige freigegebene 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 ausgeblendet werden.

Beispiel: /system/lib[64]/libcutils.so und /system/lib[64]/vndk-sp-${VER}/libcutils.so sind zwei freigegebene Bibliotheken. Diese beiden Bibliotheken können unterschiedliche Symbole haben. Sie werden in verschiedene Linker-Namespaces geladen, damit Framework-Module von /system/lib[64]/libcutils.so und SP-HAL-Freigabebibliotheken 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 ein und stellt gleichzeitig die öffentlichen Schnittstellen bereit.

Funktionsweise

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

Format der Konfigurationsdatei

Das Konfigurationsdateiformat 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 Folgendes:

  • Mehrere Eigenschaften zur 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 (Graphknoten) und mehrere Fallback-Links zwischen Namespaces (Graphbögen).
    • Jeder Namespace hat eigene Einstellungen für Isolierung, Suchpfade, zulässige Pfade und Sichtbarkeit.

In den folgenden Tabellen wird die Bedeutung der einzelnen Properties ausführlich beschrieben.

Property für die Zuordnung von Verzeichnisbereichen

Attribut Beschreibung Verwendungsbeispiele

dir.name

Ein Pfad zu einem Verzeichnis, auf das der Abschnitt [name] angewendet werden soll.

Jede Eigenschaft ordnet die ausführbaren Dateien im Verzeichnis einem Konfigurationsabschnitt für Linker-Namespaces zu. Möglicherweise gibt es zwei oder mehr Properties mit derselben name, die aber 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 von /system/bin oder /system/xbin geladen werden.

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

Beziehungseigenschaften

Attribut Beschreibung Verwendungsbeispiele
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 die [system]-Konfiguration drei Namespaces (default, sphal und vndk) enthält.

namespace.name.links

Eine durch Kommas getrennte Liste von Fallback-Namespaces.

Wenn eine freigegebene Bibliothek im aktuellen Namespace nicht gefunden werden kann, versucht der dynamische Linker, die freigegebene 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 aus dem Namespace default geladen werden kann, versucht der dynamische Linker, die gemeinsam genutzte Bibliothek aus dem 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 von freigegebenen Bibliotheken, in denen nach diesen Bibliotheken gesucht werden kann, wenn sie nicht im name-Namespace gefunden werden.other

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 zulässig ist. Der dynamische Linker ignoriert die Fallback-Verknüpfung 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 freigegebenen Bibliotheken im Namespace other gesucht 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 die Fallback-Verknüpfung vom Namespace vndk zum Namespace sphal weitergeleitet werden können.

Namespace-Eigenschaften

Attribut Beschreibung Verwendungsbeispiele
namespace.name.isolated

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

Wenn isolated 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 false (Standard) ist, prüft der dynamische Linker den Pfad der freigegebenen Bibliotheken nicht.

namespace.sphal.isolated = true

Das bedeutet, dass nur die freigegebenen Bibliotheken in search.paths oder unter permitted.paths in den Namespace sphal 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 in Funktionsaufrufen zu dlopen()- oder DT_NEEDED-Einträgen kein vollständiger Pfad angegeben ist. Das Verzeichnis, das am Anfang der Liste angegeben ist, hat eine höhere Priorität.

Wenn isolated true ist, können freigegebene Bibliotheken, die sich in einem der search.paths-Verzeichnisse befinden (ausgenommen Unterverzeichnisse), 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 aktiviertem ASan zuerst /data/asan/system/${LIB} und dann /system/${LIB} sucht.

namespace.name.permitted.paths

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

Auch die gemeinsam genutzten Bibliotheken, die sich in den Unterverzeichnissen von permitted.paths befinden, können 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, wird permitted.paths ignoriert und eine Warnung ausgegeben.

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

Das bedeutet, dass die freigegebenen Bibliotheken unter /system/${LIB}/hw in den isolierten Namespace default 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

Wenn ASan aktiviert ist, können freigegebene Bibliotheken unter /data/asan/system/${LIB}/hw oder /system/${LIB}/hw in den isolierten Namespace default geladen werden.

namespace.name.visible

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

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

Wenn visible false (Standard) ist, gibt android_get_exported_namespace() unabhängig davon, ob der Namespace vorhanden ist, immer NULL zurück. Freigegebene 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 freigegebenen Bibliotheken oder ausführbaren Dateien in diesem Namespace angefordert werden.

namespace.sphal.visible = true

Das bedeutet, dass android_get_exported_namespace("sphal") einen gültigen Namespace-Handle für den Linker zurückgeben kann.

Erstellen eines Linker-Namespace

In Android 11 wird die Linkerkonfiguration zur Laufzeit unter /linkerconfig erstellt, anstatt Textdateien in ${android-src}/system/core/rootdir/etc zu verwenden. Die Konfiguration wird beim Starten basierend auf der Laufzeitumgebung generiert. Diese umfasst die folgenden Elemente:

  • Ob das Gerät VNDK unterstützt
  • Ziel-VNDK-Version der Anbieterpartition
  • VNDK-Version der Produktpartition
  • Installierte APEX-Module

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

Isolation des Link-Namespaces

Es gibt drei Konfigurationstypen. Je nach Wert von PRODUCT_TREBLE_LINKER_NAMESPACES und BOARD_VNDK_VERSION in BoardConfig.mk wird die entsprechende Konfiguration beim Start generiert.

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Ausgewählte Konfiguration VTS-Anforderung
true current VNDK Pflicht für Geräte, die mit Android 9 oder höher auf den Markt gebracht wurden
Leer VNDK Lite Erforderlich für Geräte, die mit Android 8.x auf den Markt gebracht wurden
false Leer Legacy Für Geräte ohne Treble

Bei der VNDK Lite-Konfiguration werden die freigegebenen Bibliotheken von SP-HAL und VNDK-SP voneinander getrennt. Unter 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 die SP-HAL- und VNDK-SP-gemeinsam genutzten Bibliotheken. Außerdem bietet diese Konfiguration die vollständige Isolation des dynamischen Linker. So wird sichergestellt, dass Module in der Systempartition nicht von den freigegebenen Bibliotheken in den Anbieterpartitionen abhängen und umgekehrt.

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

VNDK-Konfiguration

Die VNDK-Konfiguration isoliert die Abhängigkeiten der freigegebenen Bibliothek zwischen der Systempartition und den Anbieterpartitionen. Im Vergleich zu den im vorherigen Abschnitt erwähnten Konfigurationen sind die Unterschiede wie folgt:

  • Framework-Prozesse

    • Die Namespaces default, vndk, sphal und rs werden erstellt.
    • Alle Namespaces sind voneinander getrennt.
    • Gemeinsam genutzte Systembibliotheken werden in den Namespace default geladen.
    • SP-HALs werden in den Namespace sphal geladen.
    • VNDK-SP-gemeinsam genutzte Bibliotheken, die in den Namespace vndk geladen wurden.
  • Anbieterprozesse

    • Die Namespaces default, vndk und system werden erstellt.
    • Der default-Namespace ist isoliert.
    • Gemeinsam genutzte Bibliotheken von Anbietern werden in den Namespace default geladen.
    • VNDK- und VNDK-SP-gemeinsam genutzte 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 ist unten dargestellt.

In der VNDK-Konfiguration beschriebenes Linker-Namespace-Diagramm

Abbildung 1: Linker-Namespace-Isolation (VNDK-Konfiguration)

In der Abbildung oben stehen LL-NDK und VNDK-SP für die folgenden freigegebenen 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 findest du auf dem Gerät in /linkerconfig/ld.config.txt.

VNDK Lite-Konfiguration

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

In der VNDK Lite-Konfiguration beschriebener Linker-Namespacegraph
Abbildung 2 Isolierung des Linker-Namespaces (VNDK Lite-Konfiguration)

LL-NDK und VNDK-SP stehen für die folgenden freigegebenen 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 Namespacekonfiguration für Framework-Prozesse aufgeführt. Sie ist ein Auszug aus dem Abschnitt [system] in der VNDK Lite-Konfiguration.

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 kompilierten 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 Namespacekonfiguration für Anbieterprozesse zu sehen. 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.

Dokumentenverlauf

Änderungen bei Android 11

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

Änderungen unter Android 9

  • In Android 9 wird der vndk-Linker-Namespace zu Anbieterprozessen hinzugefügt und VNDK-gemeinsam genutzte Bibliotheken werden vom Standard-Linker-Namespace isoliert.
  • Ersetzen Sie PRODUCT_FULL_TREBLE durch einen spezifischeren Messwert PRODUCT_TREBLE_LINKER_NAMESPACES.
  • In Android 9 werden die Namen der folgenden Konfigurationsdateien des 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
  • Entfernen Sie android.hardware.graphics.allocator@2.0.so.
  • Die Partitionen product und odm werden hinzugefügt.