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 Probleme 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 Verknüpfungs-Namespaces geladen, sodass Framework-Module von /system/lib[64]/libcutils.so abhängen können und gemeinsam genutzte SP-HAL-Bibliotheken von /system/lib[64]/vndk-sp-${VER}/libcutils.so abhängig sind.

/system/lib[64]/libc.so hingegen ist ein Beispiel für eine öffentliche Bibliothek, die von einem Verknüpfungs-Namespace exportiert und in viele Verknüpfungs-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 die dynamische Verknüpfung die gemeinsam genutzte Bibliothek nicht in den angegebenen Linker-Namespace laden kann, werden beim verknüpften Verknüpfungs-Namespace exportierte freigegebene Bibliotheken angefordert.

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 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 (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, für das der Abschnitt [name] gilt.

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.

Beziehungsattribute

Attribut Beschreibung Verwendungsbeispiele
additional.namespaces

Eine durch Kommas getrennte Liste mit zusätzlichen 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 am Anfang der Liste angegebene Namespace 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

Dieses Attribut 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 den Wert true hat, können nur die gemeinsam genutzten Bibliotheken geladen werden, die sich in einem der search.paths-Verzeichnisse (mit Ausnahme von Unterverzeichnissen) oder in einem der permitted.paths-Verzeichnisse (einschließlich Unterverzeichnisse) befinden.

Wenn isolated den Wert false (Standardeinstellung) hat, prüft die dynamische Verknüpfung den Pfad gemeinsam genutzter 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.

Beispiel: Wenn search.paths den Wert /system/${LIB} hat und permitted.paths leer ist, kann /system/${LIB}/libc.so geladen werden, aber nicht /system/${LIB}/vndk/libutils.so.

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 in den Unterverzeichnissen von permitted.paths 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 die dynamische Verknüpfung die gemeinsam genutzten 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.

Linker-Namespace erstellen

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:

  • Wenn das Gerät VNDK unterstützt
  • Ziel-VNDK-Version der Anbieterpartition
  • VNDK-Version der Produktpartition
  • 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 Linkerkonfiguration generiert, die diese Änderungen widerspiegelt. Weitere Informationen zum Erstellen einer Linker-Konfiguration finden Sie unter ${android-src}/system/linkerconfig.

Isolation des Linker-Namespace

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

PRODUCT_TREBLE_
LINKER_NAMESPACES
BOARD_VNDK_
VERSION
Ausgewählte Konfiguration VTS-Anforderung
true current VNDK Obligatorisch für Geräte mit Android 9 oder höher
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 SP-HAL- und VNDK-SP-Bibliotheken isoliert. In Android 8.0 muss dies die Konfigurationsdatei für dynamische Verknüpfung sein, wenn PRODUCT_TREBLE_LINKER_NAMESPACES den Wert true hat.

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.

Ab Android 8.1 ist die VNDK-Konfiguration die Standardkonfiguration. Es wird dringend empfohlen, die vollständige Isolierung von dynamischen Links zu aktivieren, indem Sie BOARD_VNDK_VERSION auf current setzen.

VNDK-Konfiguration

Die VNDK-Konfiguration isoliert die Abhängigkeiten der freigegebenen Bibliothek zwischen der Systempartition und den Anbieterpartitionen. Im Vergleich zu den im vorherigen Unterabschnitt beschriebenen Konfigurationen sind die Unterschiede so:

  • Framework-Prozesse

    • Die Namespaces default, vndk, sphal und rs werden erstellt.
    • Alle Namespaces sind isoliert.
    • Gemeinsam genutzte Systembibliotheken werden in den Namespace default geladen.
    • SP-HALs werden in den Namespace sphal geladen.
    • In den Namespace vndk geladene freigegebene VNDK-SP-Bibliotheken.
  • Zulieferunternehmen

    • Die Namespaces default, vndk und system werden erstellt.
    • Der Namespace default ist isoliert.
    • Vom Anbieter freigegebene Bibliotheken 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 Verknüpfungs-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 Details findest du 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-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: Linker-Namespace-Isolation (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 Namespace-Konfiguration für Framework-Prozesse aufgeführt, die aus dem Abschnitt [system] der VNDK Lite-Konfiguration entnommen ist.

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.

Namensraum 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 Details findest du 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 von LinkerConfig in der Laufzeit generiert.

Änderungen bei 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 der Namespace-Isolierung zur Laufzeitverknüpfung
    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.