Benutzerdefinierte Zugriffssteuerung (Discretionary Access Control, DAC)

Dateisystemobjekte und -dienste, die dem Build hinzugefügt werden, benötigen häufig separate, eindeutige IDs, sogenannte Android-IDs (AIDs). Derzeit verwenden viele Ressourcen wie Dateien und Dienste unnötigerweise Core-AIDs (von Android definiert). In vielen Fällen können Sie stattdessen OEM-AIDs (von OEM definiert) verwenden.

In früheren Android-Versionen (Android 7.x und niedriger) wurde der AIDs -Mechanismus mit einer gerätespezifischen android_filesystem_config.h -Datei erweitert, um Dateisystemfunktionen und/oder benutzerdefinierte OEM-AIDs anzugeben. Dieses System war jedoch nicht intuitiv, da es keine benutzerfreundlichen Namen für OEM-AIDs unterstützte. Sie mussten die numerische Rohform für Nutzer- und Gruppenfelder angeben, ohne eine Möglichkeit zu haben, einen benutzerfreundlichen Namen mit der numerischen AID zu verknüpfen.

Neuere Android-Versionen (Android 8.0 und höher) unterstützen eine neue Methode zum Erweitern der Dateisystemfunktionen. Diese neue Methode unterstützt Folgendes:

  • Mehrere Quellspeicherorte für Konfigurationsdateien (ermöglicht erweiterbare Build-Konfigurationen).
  • Überprüfung der OEM-AID-Werte zur Build-Zeit.
  • Generierung eines benutzerdefinierten OEM-AID-Headers, der bei Bedarf in Quelldateien verwendet werden kann.
  • Verknüpfung eines benutzerfreundlichen Namens mit dem tatsächlichen OEM-AID-Wert. Unterstützt nicht numerische Stringargumente für Nutzer und Gruppe, z.B. „foo“ anstelle von „2901“.

Weitere Verbesserungen umfassen das Entfernen des android_ids[] Arrays aus system/core/libcutils/include/private/android_filesystem_config.h. Dieses Array ist jetzt in Bionic als vollständig privates generiertes Array mit Accessoren mit getpwnam() und getgrnam() vorhanden. (Dies hat den Nebeneffekt, dass stabile Binärdateien erzeugt werden, da Core-AIDs geändert werden.) Informationen zu Tools und eine README-Datei mit weiteren Details finden Sie unter build/make/tools/fs_config.

Android-IDs (AIDs) hinzufügen

In Android 8.0 wurde das android_ids[]-Array aus dem Open-Source-Projekt für Android (Android Open Source Project, AOSP) entfernt. Alle AID-freundlichen Namen werden stattdessen aus der system/core/libcutils/include/private/android_filesystem_config.h Headerdatei generiert, wenn das Bionic-android_ids[] Array generiert wird. Jede define die mit AID_* übereinstimmt, wird vom Tooling erfasst und * wird zum Kleinbuchstabennamen.

Beispiel in private/android_filesystem_config.h:

#define AID_SYSTEM 1000

Wird zu:

  • Benutzerfreundlicher Name: system
  • uid: 1000
  • gid: 1000

Wenn Sie eine neue AOSP-Core-AID hinzufügen möchten, fügen Sie einfach #define der android_filesystem_config.h Header-Datei hinzu. Die AID wird beim Build generiert und für Schnittstellen verfügbar gemacht, die Nutzer- und Gruppen Argumente verwenden. Das Tooling prüft, ob sich die neue AID nicht in den APP- oder OEM Bereichen befindet. Außerdem werden Änderungen an diesen Bereichen berücksichtigt und bei Änderungen oder neuen OEM-reservierten Bereichen sollte die Konfiguration automatisch neu konfiguriert werden.

AIDs konfigurieren

Wenn Sie den neuen AIDs-Mechanismus aktivieren möchten, legen Sie TARGET_FS_CONFIG_GEN in der BoardConfig.mk Datei fest. Diese Variable enthält eine Liste von Konfigurationsdateien, sodass Sie bei Bedarf Dateien anhängen können.

Konventionsgemäß verwenden Konfigurationsdateien den Namen config.fs, aber in der Praxis können Sie einen beliebigen Namen verwenden. config.fs-Dateien haben das Python ConfigParser INI-Format und enthalten einen Abschnitt für Funktionen (zum Konfigurieren von Dateisystemfunktionen) und einen Abschnitt für AIDs (zum Konfigurieren von OEM-AIDs).

Abschnitt für Funktionen konfigurieren

Im Abschnitt für Funktionen können Dateisystemfunktionen für Dateisystemobjekte im Build festgelegt werden. Das Dateisystem selbst muss diese Funktion ebenfalls unterstützen.

Da das Ausführen eines stabilen Dienstes als Root in Android zu einem Fehler in der Compatibility Test Suite (CTS) führt, mussten bisher Funktionen eingerichtet und dann setuid/setgid auf eine geeignete AID gesetzt werden, um eine Funktion beim Ausführen eines Prozesses oder Dienstes beizubehalten. Mit Funktionen können Sie diese Anforderungen überspringen und das Kernel für Sie erledigen lassen. Wenn die Steuerung an main() übergeben wird, verfügt Ihr Prozess bereits über die erforderlichen Funktionen, sodass Ihr Dienst einen Nicht-Root-Nutzer und eine Nicht-Root-Gruppe verwenden kann. Dies ist die bevorzugte Methode zum Starten privilegierter Dienste.

Der Abschnitt für Funktionen verwendet die folgende Syntax:

Bereich Wert Definition
[path] Der Dateisystempfad, der konfiguriert werden soll. Ein Pfad, der mit „/“ endet, wird als Verzeichnis betrachtet, andernfalls als Datei.

Es ist ein Fehler, mehrere Abschnitte mit demselben [path] in verschiedenen Dateien anzugeben. In Python-Versionen <= 3.2 können dieselben Dateien Abschnitte enthalten, die den vorherigen Abschnitt überschreiben. In Python 3.2 ist der strikte Modus festgelegt.
mode Oktaler Dateimodus Ein gültiger oktaler Dateimodus mit mindestens drei Ziffern. Wenn „3“ angegeben ist, wird ein „0“ vorangestellt. Andernfalls wird der Modus unverändert verwendet.
user AID_<user> Entweder die C define für eine gültige AID oder der benutzerfreundliche Name (z.B. sind sowohl AID_RADIO als auch radio zulässig). Informationen zum Definieren einer benutzerdefinierten AID finden Sie unter Abschnitt für AIDs konfigurieren.
group AID_<group> Wie Nutzer.
caps cap* Der Name, wie er deklariert ist in bionic/libc/kernel/uapi/linux/capability.h ohne das vorangestellte CAP_. Gemischte Groß-/Kleinschreibung ist zulässig. Funktionen können auch die Rohform sein:
  • Binär (0b0101)
  • Oktal (0455)
  • Ganzzahl (42)
  • Hexadezimal (0xFF)
Trennen Sie mehrere Funktionen durch Leerzeichen.

Ein Anwendungsbeispiel finden Sie unter Dateisystemfunktionen verwenden.

Abschnitt für AIDs konfigurieren

Der Abschnitt für AIDs enthält OEM-AIDs und verwendet die folgende Syntax:

Bereich Wert Definition
[AID_<name>] Das <name> kann Zeichen aus der Menge Großbuchstaben, Zahlen und Unterstriche enthalten. Die Kleinbuchstabenversion wird als der benutzerfreundliche Name verwendet. Die generierte Header-Datei für die Codeeinbindung verwendet genau AID_<name>.

Es ist ein Fehler, mehrere Abschnitte mit derselben AID_<name> anzugeben (Groß-/Kleinschreibung wird nicht berücksichtigt, mit denselben Einschränkungen wie [path]).

<name> muss mit einem Partitionierungsnamen beginnen, damit es nicht zu Konflikten mit verschiedenen Quellen kommt.
value <number> Eine gültige Zahl im C-Stil (hexadezimal, oktal, binär und dezimal).

Es ist ein Fehler, mehrere Abschnitte mit derselben Wertoption anzugeben.

Wertoptionen müssen im Bereich angegeben werden, der der in <name> verwendeten Partition entspricht. Die Liste der gültigen Partitionen und der entsprechenden Bereiche ist in system/core/libcutils/include/private/android_filesystem_config.h definiert. Die Optionen sind:
  • Anbieterpartition
    • AID_OEM_RESERVED_START(2900) – AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000) – AID_OEM_RESERVED_2_END(5999)
  • Systempartition
    • AID_SYSTEM_RESERVED_START(6000) – AID_SYSTEM_RESERVED_END(6499)
  • ODM-Partition
    • AID_ODM_RESERVED_START(6500) – AID_ODM_RESERVED_END(6999)
  • Produktaufteilung
    • AID_PRODUCT_RESERVED_START(7000) – AID_PRODUCT_RESERVED_END(7499)
  • System_ext-Partition
    • AID_SYSTEM_EXT_RESERVED_START(7500) – AID_SYSTEM_EXT_RESERVED_END(7999)

Anwendungsbeispiele finden Sie unter OEM -AID-Namen definieren und OEM-AIDs verwenden.

Anwendungsbeispiele

In den folgenden Beispielen wird beschrieben, wie Sie eine OEM-AID definieren und verwenden und wie Sie Dateisystemfunktionen aktivieren. OEM-AID-Namen ([AID_name]) müssen mit einem Partitionierungsnamen wie "vendor_" beginnen, damit sie nicht mit zukünftigen AOSP-Namen oder anderen Partitionen in Konflikt geraten.

OEM-AID-Namen definieren

Wenn Sie eine OEM-AID definieren möchten, erstellen Sie eine config.fs-Datei und legen Sie den AID-Wert fest. Legen Sie beispielsweise in device/x/y/config.fs Folgendes fest:

[AID_VENDOR_FOO]
value: 2900

Legen Sie nach dem Erstellen der Datei die Variable TARGET_FS_CONFIG_GEN fest und verweisen Sie in BoardConfig.mk darauf. Legen Sie beispielsweise in device/x/y/BoardConfig.mk, Folgendes fest:

TARGET_FS_CONFIG_GEN += device/x/y/config.fs

Ihre benutzerdefinierte AID kann jetzt in einem neuen Build vom System insgesamt verwendet werden.

OEM-AIDs verwenden

Wenn Sie eine OEM-AID in Ihrem C-Code verwenden möchten, fügen Sie die oemaids_headers in Ihre zugehörige Makefile ein und fügen Sie #include "generated_oem_aid.h" hinzu. Verwenden Sie dann die deklarierten IDs. Fügen Sie beispielsweise in my_file.c Folgendes hinzu:

#include "generated_oem_aid.h"


If (ipc->uid == AID_VENDOR_FOO) {
  // Do something
...

Fügen Sie in der zugehörigen Android.bp-Datei Folgendes hinzu:

header_libs: ["oemaids_headers"],

Wenn Sie eine Android.mk-Datei verwenden, fügen Sie Folgendes hinzu:

LOCAL_HEADER_LIBRARIES := oemaids_headers

Benutzerfreundliche Namen verwenden

In Android 9 können Sie den benutzerfreundlichen Namen für jede Schnittstelle verwenden, die AID-Namen unterstützt. Beispiel:

  • In einem chown-Befehl in some/init.rc:
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • In einem service in some/init.rc:
    service vendor_foo /vendor/bin/foo_service
        user vendor_foo
        group vendor_foo
    

Da die interne Zuordnung vom benutzerfreundlichen Namen zur UID über /vendor/etc/passwd und /vendor/etc/group erfolgt, muss die Anbieter partition bereitgestellt werden.

Benutzerfreundliche Namen zuordnen

Android 9 unterstützt die Zuordnung eines benutzerfreundlichen Namens zum tatsächlichen OEM-AID-Wert. Sie können nicht numerische String Argumente für Nutzer und Gruppe verwenden, d. h. "vendor_foo" anstelle von "2901".

Von AID zu benutzerfreundlichen Namen konvertieren

Für OEM-AIDs war in Android 8.x die Verwendung von oem_#### mit getpwnam und ähnlichen Funktionen sowie an Stellen erforderlich, an denen Suchvorgänge mit getpwnam ausgeführt werden (z. B. init-Skripts). In Android 9 können Sie die Freunde getpwnam und getgrnam in Bionic verwenden, um von Android-IDs (AIDs) zu benutzerfreundlichen Namen und umgekehrt zu konvertieren.

Dateisystemfunktionen verwenden

Wenn Sie Dateisystemfunktionen aktivieren möchten, erstellen Sie in der config.fs Datei einen Abschnitt für Funktionen. Fügen Sie beispielsweise in device/x/y/config.fs den folgenden Abschnitt hinzu:

[system/bin/foo_service]
mode: 0555
user: AID_VENDOR_FOO
group: AID_SYSTEM
caps: SYS_ADMIN | SYS_NICE

Legen Sie nach dem Erstellen der Datei TARGET_FS_CONFIG_GEN so fest, dass sie in BoardConfig.mk auf diese Datei verweist. Legen Sie beispielsweise in device/x/y/BoardConfig.mk, Folgendes fest:

TARGET_FS_CONFIG_GEN += device/x/y/config.fs

Wenn der Dienst vendor_foo ausgeführt wird, wird er mit den Funktionen CAP_SYS_ADMIN und CAP_SYS_NICE ohne setuid und setgid Aufrufe gestartet. Außerdem benötigt die SELinux-Richtlinie des Dienstes vendor_foo die Funktion setuid und setgid nicht mehr und kann gelöscht werden.

Überschreibungen konfigurieren (Android 6.x–7.x)

In Android 6.0 wurden fs_config und die zugehörigen Struktur definitionen (system/core/include/private/android_filesystem_config.h) nach system/core/libcutils/fs_config.c verschoben, wo sie durch Binärdateien aktualisiert oder überschrieben werden konnten, die in /system/etc/fs_config_dirs und /system/etc/fs_config_files installiert wurden. Durch die Verwendung separater Abgleichs- und Parsing regeln für Verzeichnisse und Dateien (die zusätzliche Glob-Ausdrücke verwenden konnten) konnten Verzeichnisse und Dateien in zwei verschiedenen Tabellen verarbeitet werden. Strukturdefinitionen in system/core/libcutils/fs_config.c ermöglichten nicht nur das Lesen von Verzeichnissen und Dateien zur Laufzeit, sondern der Host konnte dieselben Dateien auch zur Build-Zeit verwenden, um Dateisystem-Images als ${OUT}/system/etc/fs_config_dirs und ${OUT}/system/etc/fs_config_files zu erstellen.

Die Überschreibungsmethode zum Erweitern des Dateisystems wurde durch das in Android 8.0 eingeführte modulare Konfigurationssystem ersetzt. Sie können die alte Methode aber weiterhin verwenden, wenn Sie möchten. In den folgenden Abschnitten wird beschrieben, wie Sie Überschreibungsdateien generieren und einfügen und das Dateisystem konfigurieren.

Überschreibungsdateien generieren

Sie können die ausgerichteten Binärdateien /system/etc/fs_config_dirs und /system/etc/fs_config_files mit dem Tool fs_config_generate in build/tools/fs_config generieren. Das Tool verwendet eine libcutils-Bibliotheksfunktion (fs_config_generate()), um DAC-Anforderungen in einem Puffer zu verwalten, und definiert Regeln für eine Include-Datei, um die DAC-Regeln zu institutionalisieren.

Erstellen Sie dazu eine Include-Datei in device/vendor/device/android_filesystem_config.h, die als Überschreibung dient. Die Datei muss das in system/core/include/private/android_filesystem_config.h definierte Format structure fs_path_config mit den folgenden Strukturinitialisierungen für Verzeichnis- und Dateisymbole verwenden:

  • Verwenden Sie für Verzeichnisse android_device_dirs[].
  • Verwenden Sie für Dateien android_device_files[].

Wenn Sie android_device_dirs[] und android_device_files[] nicht verwenden, können Sie NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS und NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES definieren (siehe das Beispiel unten). Sie können die Überschreibungsdatei auch mit TARGET_ANDROID_FILESYSTEM_CONFIG_H in der Board-Konfiguration angeben, mit einem erzwungenen Basisnamen von android_filesystem_config.h.

Überschreibungsdateien einfügen

Wenn Sie Dateien einfügen möchten, muss PRODUCT_PACKAGES fs_config_dirs und/oder fs_config_files enthalten, damit sie in /system/etc/fs_config_dirs und /system/etc/fs_config_files installiert werden können. Das Build-System sucht nach benutzerdefinierten android_filesystem_config.h in $(TARGET_DEVICE_DIR), wo sich BoardConfig.mk befindet. Wenn sich diese Datei an einem anderen Ort befindet, legen Sie die Board-Konfigurationsvariable TARGET_ANDROID_FILESYSTEM_CONFIG_H so fest, dass sie auf diesen Speicherort verweist.

Dateisystem konfigurieren

So konfigurieren Sie das Dateisystem in Android 6.0 und höher:

  1. Erstellen Sie die Datei $(TARGET_DEVICE_DIR)/android_filesystem_config.h.
  2. Fügen Sie fs_config_dirs und/oder fs_config_files in der Board-Konfigurationsdatei (z.B. $(TARGET_DEVICE_DIR)/device.mk) zu PRODUCT_PACKAGES hinzu.

Beispiel für Überschreibung

In diesem Beispiel wird ein Patch zum Überschreiben des system/bin/glgps Daemons gezeigt, um im device/vendor/device Verzeichnis die Unterstützung für Wakelocks hinzuzufügen. Beachten Sie Folgendes:

  • Jeder Struktureintrag besteht aus Modus, UID, GID, Funktionen und Name. system/core/include/private/android_filesystem_config.h wird automatisch eingefügt, um die Manifest-Anweisungen ` #define` (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND) bereitzustellen.
  • Der Abschnitt android_device_files[] enthält eine Aktion, um den Zugriff auf system/etc/fs_config_dirs zu unterdrücken, wenn er nicht angegeben ist. Dies dient als zusätzlicher DAC-Schutz bei fehlenden Inhalten für Verzeichnisüberschreibungen. Dies ist jedoch ein schwacher Schutz. Wenn jemand die Kontrolle über /system hat, kann er in der Regel alles tun, was er möchte.
diff --git a/android_filesystem_config.h b/android_filesystem_config.h
new file mode 100644
index 0000000..874195f
--- /dev/null
+++ b/android_filesystem_config.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+/* This file is used to define the properties of the file system
+** images generated by build tools (eg: mkbootfs) and
+** by the device side of adb.
+*/
+
+#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+/* static const struct fs_path_config android_device_dirs[] = { }; */
+
+/* Rules for files.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root. Prefixes ending in * denotes wildcard
+** and will allow partial matches.
+*/
+static const struct fs_path_config android_device_files[] = {
+  { 00755, AID_ROOT, AID_SHELL, (1ULL << CAP_BLOCK_SUSPEND),
"system/bin/glgps" },
+#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+  { 00000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs" },
+#endif
+};


diff --git a/device.mk b/device.mk
index 0c71d21..235c1a7 100644
--- a/device.mk
+++ b/device.mk
@@ -18,7 +18,8 @@ PRODUCT_PACKAGES := \
     libwpa_client \
     hostapd \
     wpa_supplicant \
-    wpa_supplicant.conf
+    wpa_supplicant.conf \
+    fs_config_files

 ifeq ($(TARGET_PREBUILT_KERNEL),)
 ifeq ($(USE_SVELTE_KERNEL), true)

Dateisysteme aus früheren Versionen migrieren

Wenn Sie Dateisysteme aus Android 5.x und früheren Versionen migrieren, beachten Sie, dass in Android 6.x

  • einige Include-Anweisungen, Strukturen und Inline-Definitionen entfernt wurden.
  • ein Verweis auf libcutils erforderlich ist, anstatt direkt von system/core/include/private/android_filesystem_config.h aus ausgeführt zu werden. Private ausführbare Dateien des Geräteherstellers, die von system/code/include/private_filesystem_config.h für die Datei- oder Verzeichnisstrukturen oder fs_config abhängen, müssen libcutils Bibliotheksabhängigkeiten hinzufügen.
  • private Zweigkopien des Geräteherstellers von system/core/include/private/android_filesystem_config.h mit zusätzlichen Inhalten für vorhandene Ziele nach device/vendor/device/android_filesystem_config.h verschoben werden müssen.
  • das Recht vorbehalten ist, SELinux Mandatory Access Controls (MAC) auf Konfigurationsdateien im Zielsystem anzuwenden. Implementierungen, die benutzerdefinierte ausführbare Zieldateien mit fs_config() enthalten, müssen den Zugriff sicherstellen.