Benutzerdefinierte Zugriffssteuerung (Discretionary Access Control, DAC)

Dateisystemobjekte und Dienste, die dem Build hinzugefügt werden, benötigen häufig separate, eindeutige IDs, die als Android-IDs (AIDs) bezeichnet werden. Derzeit werden für viele Ressourcen wie Dateien und Dienste unnötigerweise von Android definierte AIDs verwendet. In vielen Fällen können Sie stattdessen von OEMs (von OEMs definierte) AIDs verwenden.

In früheren Android-Versionen (Android 7.x und niedriger) wurde der AID-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 nutzerfreundlichen Namen für OEM-AIDs unterstützte. Sie mussten also die Rohzahl für Nutzer- und Gruppenfelder angeben, ohne dass Sie der numerischen AID einen nutzerfreundlichen Namen zuweisen konnten.

Neuere Versionen von Android (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 Buildkonfigurationen)
  • Validierung der OEM-AID-Werte zur Buildzeit
  • Generieren eines benutzerdefinierten OEM-AID-Headers, der bei Bedarf in Quelldateien verwendet werden kann.
  • Verknüpfung eines nutzerfreundlichen 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 sind das Entfernen des android_ids[]-Arrays aus system/core/libcutils/include/private/android_filesystem_config.h. Dieses Array ist in Bionic jetzt als vollständig privat generiertes Array mit den Zugriffsmethoden getpwnam() und getgrnam() verfügbar. Dies hat den Nebeneffekt, dass stabile Binärdateien erzeugt werden, da die wichtigsten 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

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

Beispielsweise in private/android_filesystem_config.h:

#define AID_SYSTEM 1000

wird zu:

  • Anzeigename: system
  • uid: 1000
  • gid: 1000

Wenn Sie eine neue AOSP-Kern-AID hinzufügen möchten, fügen Sie einfach die #define in die android_filesystem_config.h-Headerdatei ein. Die AID wird beim Build generiert und für Oberflächen verfügbar gemacht, die Nutzer- und Gruppenargumente verwenden. Die Tools prüfen, ob sich die neue AID nicht in den APP- oder OEM-Bereichen befindet. Außerdem werden Änderungen an diesen Bereichen berücksichtigt und die Tools sollten bei Änderungen oder neuen vom OEM reservierten Bereichen automatisch neu konfiguriert werden.

AIDs konfigurieren

Wenn Sie den neuen AID-Mechanismus aktivieren möchten, setzen Sie in der Datei BoardConfig.mk den Wert TARGET_FS_CONFIG_GEN. Diese Variable enthält eine Liste von Konfigurationsdateien, die Sie bei Bedarf anhängen können.

Konventionsgemäß wird für Konfigurationsdateien der Name config.fs verwendet. Sie können aber auch einen anderen Namen verwenden. config.fs-Dateien sind im INI-Format von Python ConfigParser und enthalten einen Abschnitt „caps“ (zum Konfigurieren der Dateisystemfunktionen) und einen Abschnitt „AIDs“ (zum Konfigurieren von OEM-AIDs).

Bereich „Caps“ konfigurieren

Im Abschnitt „caps“ können Sie Dateisystemfunktionen für Dateisystemobjekte im Build festlegen. Das Dateisystem selbst muss diese Funktion ebenfalls unterstützen.

Da das Ausführen eines stabilen Dienstes als Root in Android zu einem CTS-Fehler (Compatibility Test Suite) führt, erforderte die bisherige Beibehaltung einer Funktion beim Ausführen eines Prozesses oder Dienstes die Einrichtung von Funktionen und die Verwendung von setuid/setgid für eine ordnungsgemäße AID. Mit Caps können Sie diese Anforderungen überspringen und den Kernel die Arbeit machen lassen. Wenn die Steuerung an main() übergeben wird, hat Ihr Prozess bereits 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 „caps“ verwendet die folgende Syntax:

Abschnitt Wert Definition
[path] Der zu konfigurierende Dateisystempfad. Ein Pfad, der auf / endet, wird als Verzeichnis betrachtet, andernfalls als Datei.

Es ist ein Fehler, in verschiedenen Dateien mehrere Abschnitte mit derselben [path] anzugeben. In Python-Versionen <= 3.2 kann dieselbe Datei Abschnitte enthalten, die den vorherigen Abschnitt überschreiben. In Python 3.2 ist der strenge Modus festgelegt.
mode Oktaler Dateimodus Ein gültiger oktaler Dateimodus mit mindestens drei Ziffern. Wenn „3“ angegeben wird, wird davor eine „0“ gesetzt. Andernfalls wird der Modus unverändert verwendet.
user AID_<user> Entweder die C define für eine gültige AID oder der Anzeigenamen (z.B. sind sowohl AID_RADIO als auch radio zulässig). Informationen zum Definieren einer benutzerdefinierten AID finden Sie im Abschnitt AID konfigurieren.
group AID_<group> Entspricht dem Nutzer.
caps cap* Der in bionic/libc/kernel/uapi/linux/capability.h deklarierte Name ohne das vorangestellte CAP_. Gemischte Groß- und Kleinschreibung ist zulässig. Großbuchstaben können auch so aussehen:
  • Binär (0b0101)
  • Oktal (0455)
  • int (42)
  • Hex (0xFF)
Trennen Sie mehrere Großbuchstaben durch Leerzeichen.

Ein Anwendungsbeispiel finden Sie unter Dateisystemfunktionen verwenden.

AID-Bereich konfigurieren

Der Abschnitt „AID“ enthält OEM-AIDs und verwendet die folgende Syntax:

Abschnitt Wert Definition
[AID_<name>] Die <name> kann Großbuchstaben, Ziffern und Unterstriche enthalten. Die Kleinbuchstabenversion wird als freundlicher Name verwendet. In der generierten Headerdatei für die Codeeinfügung wird genau diese AID_<name> verwendet.

Es ist ein Fehler, mehrere Abschnitte mit demselben AID_<name> anzugeben (ohne Berücksichtigung der Groß- und Kleinschreibung mit denselben Einschränkungen wie [path]).

<name> muss mit einem Partitionsnamen beginnen, damit es nicht zu Konflikten mit verschiedenen Quellen kommt.
value <number> Ein gültiger C-Format-Zahlenstring (Hexadezimal, Oktal, Binär und Dezimal).

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

Die Wertoptionen müssen im Bereich angegeben werden, der der in <name> verwendeten Partition entspricht. Die Liste der gültigen Partitionen und die zugehörigen Bereiche sind in system/core/libcutils/include/private/android_filesystem_config.h definiert. Folgende Optionen sind verfügbar:
  • Anbieterpartition
    • AID_OEM_RESERVED_START(2900) – AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000) bis AID_OEM_RESERVED_2_END(5999)
  • Systempartition
    • AID_SYSTEM_RESERVED_START(6000) bis AID_SYSTEM_RESERVED_END(6499)
  • ODM-Partition
    • AID_ODM_RESERVED_START(6500) bis 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)

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

Beispiele für die Verwendung

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

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

Nachdem Sie die Datei erstellt haben, legen Sie 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 Anzeigen-ID kann jetzt von dem gesamten System in einem neuen Build verwendet werden.

OEM-AIDs verwenden

Wenn Sie eine OEM-AID verwenden möchten, fügen Sie in Ihrem C-Code die oemaids_headers in das 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

Nutzerfreundliche Namen verwenden

Unter Android 9 können Sie den Alias für jede Benutzeroberfläche 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 freundlichen Namen zur UID von /vendor/etc/passwd und /vendor/etc/group durchgeführt wird, muss die Partition des Anbieters bereitgestellt werden.

Nutzerfreundliche Namen zuordnen

Android 9 unterstützt die Zuordnung eines Anzeigenamens zum tatsächlichen OEM-AID-Wert. Sie können auch nicht numerische Stringargumente für Nutzer und Gruppe verwenden, z. B. „vendor_foo“ anstelle von „2901“.

Von AID zu nutzerfreundlichen Namen konvertieren

Für OEM-AIDs war unter Android 8.x die Verwendung von oem_#### mit getpwnam und ähnlichen Funktionen erforderlich, ebenso an Stellen, an denen Suchanfragen mit getpwnam verarbeitet werden (z. B. in init-Scripts). In Android 9 können Sie die Freunde getpwnam und getgrnam in Bionic verwenden, um von Android-IDs (AIDs) zu nutzerfreundlichen Namen und umgekehrt zu konvertieren.

Dateisystemfunktionen verwenden

Wenn Sie Dateisystemfunktionen aktivieren möchten, erstellen Sie in der Datei config.fs einen Bereich „caps“. 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 Dienst vendor_foo ausgeführt wird, wird er mit den Funktionen CAP_SYS_ADMIN und CAP_SYS_NICE gestartet, ohne setuid- und setgid-Aufrufe. Außerdem sind für die SELinux-Richtlinie des vendor_foo-Dienstes die Berechtigungen setuid und setgid nicht mehr erforderlich und können gelöscht werden.

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

Unter Android 6.0 wurden fs_config und die zugehörigen Strukturdefinitionen (system/core/include/private/android_filesystem_config.h) an den Speicherort system/core/libcutils/fs_config.c verschoben, wo sie durch Binärdateien, die in /system/etc/fs_config_dirs und /system/etc/fs_config_files installiert wurden, aktualisiert oder überschrieben werden konnten. Durch separate Abgleich- und Parseregeln für Verzeichnisse und Dateien (mit zusätzlichen Glob-Ausdrücken) konnte Android Verzeichnisse und Dateien in zwei verschiedenen Tabellen verarbeiten. Strukturdefinitionen in system/core/libcutils/fs_config.c ermöglichten nicht nur das Lesen von Verzeichnissen und Dateien zur Laufzeit, sondern der Host konnte auch dieselben Dateien zur Buildzeit verwenden, um Dateisystem-Images wie ${OUT}/system/etc/fs_config_dirs und ${OUT}/system/etc/fs_config_files zu erstellen.

Die Methode zum Überschreiben der Erweiterung des Dateisystems wurde durch das modulare Konfigurationssystem ersetzt, das in Android 8.0 eingeführt wurde. Sie können die alte Methode aber bei Bedarf weiterhin verwenden. In den folgenden Abschnitten wird beschrieben, wie Sie Überschreibungsdateien generieren und einbinden 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 structure fs_path_config-Format mit den folgenden Strukturinitialisierungen für Verzeichnis- und Dateisymbole verwenden:

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

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 Beispiel unten). Sie können die Überschreibungsdatei auch mit TARGET_ANDROID_FILESYSTEM_CONFIG_H in der Boardkonfiguration mit einem erzwungenen Basisnamen von android_filesystem_config.h angeben.

Überschreibungsdateien einschließen

Wenn Sie Dateien einschließen möchten, muss PRODUCT_PACKAGES fs_config_dirs und/oder fs_config_files enthalten, damit sie in /system/etc/fs_config_dirs bzw. /system/etc/fs_config_files installiert werden können. Das Build-System sucht in $(TARGET_DEVICE_DIR) nach benutzerdefinierten android_filesystem_config.h, wo BoardConfig.mk vorhanden ist. Wenn diese Datei an einem anderen Speicherort vorhanden ist, legen Sie die Variable „TARGET_ANDROID_FILESYSTEM_CONFIG_H“ für die Boardkonfiguration so fest, dass sie auf diesen Speicherort verweist.

Dateisystem konfigurieren

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

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

Beispiel für eine Überschreibung

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

  • Jeder Struktureintrag besteht aus dem Modus, der UID, der GID, den Berechtigungen und dem Namen. system/core/include/private/android_filesystem_config.h wird automatisch eingefügt, um die Manifest-#defines (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND) bereitzustellen.
  • Der Abschnitt android_device_files[] enthält eine Aktion, mit der der Zugriff auf system/etc/fs_config_dirs unterdrückt wird, 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 will.
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 Releases migrieren

Beachten Sie bei der Migration von Dateisystemen von Android 5.x und niedriger Folgendes:

  • Entfernt einige Includes, Strukturen und Inline-Definitionen.
  • Erfordert eine Referenz auf libcutils, anstatt direkt von system/core/include/private/android_filesystem_config.h aus ausgeführt zu werden. Für private ausführbare Dateien des Geräteherstellers, die für die Datei- oder Verzeichnisstruktur auf system/code/include/private_filesystem_config.h oder fs_config angewiesen sind, müssen libcutils-Bibliotheksabhängigkeiten hinzugefügt werden.
  • Erfordert private Branch-Kopien der system/core/include/private/android_filesystem_config.h vom Gerätehersteller mit zusätzlichen Inhalten auf vorhandenen Zielen, die zu device/vendor/device/android_filesystem_config.h verschoben werden sollen.
  • Wir behalten uns das Recht vor, SELinux-MAC-Regeln (Mandatory Access Controls) auf Konfigurationsdateien auf dem Zielsystem anzuwenden. Implementierungen, die benutzerdefinierte Zielausführprogramme mit fs_config() enthalten, müssen den Zugriff ermöglichen.