Controllo dell'accesso discrezionale (DAC)

Gli oggetti e i servizi del file system aggiunti alla build spesso richiedono ID univoci separati, noti come ID Android (AID). Attualmente, molte risorse come file e servizi utilizzano inutilmente AID di base (definiti da Android); in molti casi puoi utilizzare invece AID OEM (definiti dall'OEM).

Le versioni precedenti di Android (Android 7.x e precedenti) estendevano il meccanismo AID utilizzando un file android_filesystem_config.h specifico del dispositivo per specificare le funzionalità del file system e/o gli AID OEM personalizzati. Tuttavia, questo sistema non era intuitivo perché non supportava l'utilizzo di nomi descrittivi per gli AID OEM, richiedendo di specificare il valore numerico non elaborato per i campi utente e gruppo senza un modo per associare un nome descrittivo all'AID numerico.

Le versioni più recenti di Android (Android 8.0 e versioni successive) supportano un nuovo metodo per estendere le funzionalità del file system. Questo nuovo metodo supporta quanto segue:

  • Più posizioni di origine per i file di configurazione (consente configurazioni di compilazione estensibili).
  • Controllo di integrità in fase di compilazione dei valori AID OEM.
  • Generazione di un'intestazione AID OEM personalizzata che può essere utilizzata nei file di origine in base alle necessità.
  • Associazione di un nome descrittivo al valore AID OEM effettivo. Supporta argomenti stringa non numerici per utente e gruppo, ad es. "foo" anziché "2901".

Altri miglioramenti includono la rimozione dell'array android_ids[] da system/core/libcutils/include/private/android_filesystem_config.h. Questo array ora esiste in Bionic come array generato completamente privato, con funzioni di accesso con getpwnam() e getgrnam(). (Ciò ha l'effetto collaterale di produrre binari stabili man mano che gli AID principali vengono modificati.) Per strumenti e un file README con maggiori dettagli, consulta build/make/tools/fs_config.

Aggiungere ID Android (AID)

Android 8.0 ha rimosso l'array android_ids[] da Android Open Source Project (AOSP). Tutti i nomi compatibili con AID vengono invece generati dal file di intestazione system/core/libcutils/include/private/android_filesystem_config.h durante la generazione dell'array Bionic android_ids[]. Qualsiasi define corrispondenza AID_* viene rilevata dagli strumenti e * diventa il nome in minuscolo.

Ad esempio, in private/android_filesystem_config.h:

#define AID_SYSTEM 1000

Diventa:

  • Nome descrittivo: sistema
  • uid: 1000
  • gid: 1000

Per aggiungere un nuovo AID core AOSP, aggiungi semplicemente #define al file di intestazione android_filesystem_config.h. L'ID utente viene generato durante la compilazione e reso disponibile alle interfacce che utilizzano argomenti di utenti e gruppi. Gli strumenti convalidano che il nuovo ID app non rientri negli intervalli APP o OEM; rispettano anche le modifiche a questi intervalli e devono riconfigurarsi automaticamente in caso di modifiche o nuovi intervalli riservati agli OEM.

Configurare gli ID app

Per attivare il nuovo meccanismo di ID pubblicità, imposta TARGET_FS_CONFIG_GEN nel file BoardConfig.mk. Questa variabile contiene un elenco di file di configurazione, che ti consente di aggiungere file in base alle esigenze.

Per convenzione, i file di configurazione utilizzano il nome config.fs, ma in pratica puoi utilizzare qualsiasi nome. I file config.fs sono nel formato ini ConfigParser di Python e includono una sezione caps (per configurare le funzionalità del file system) e una sezione AIDs (per configurare gli AID OEM).

Configurare la sezione dei limiti

La sezione delle funzionalità supporta l'impostazione delle funzionalità di sistema dei file sugli oggetti del file system all'interno della build (anche il file system stesso deve supportare questa funzionalità).

Poiché l'esecuzione di un servizio stabile come root in Android causa un errore di Compatibility Test Suite (CTS), i requisiti precedenti per mantenere una funzionalità durante l'esecuzione di un processo o servizio prevedevano la configurazione delle funzionalità e l'utilizzo di setuid/setgid per l'esecuzione di un AID appropriato. Con i limiti, puoi saltare questi requisiti e lasciare che il kernel lo faccia per te. Quando il controllo viene trasferito a main(), il tuo processo dispone già delle funzionalità necessarie perché il tuo servizio possa utilizzare un utente e un gruppo non root (questo è il modo preferito per avviare servizi con privilegi).

La sezione dei limiti utilizza la seguente sintassi:

Sezione Valore Definizione
[path] Il percorso del file system da configurare. Un percorso che termina con / è considerato una directory, altrimenti è un file.

È un errore specificare più sezioni con lo stesso [path] in file diversi. Nelle versioni di Python <= 3.2, lo stesso file può contenere sezioni che sostituiscono la sezione precedente; in Python 3.2, è impostata la modalità rigida.
mode Modalità file ottale Una modalità file ottale valida di almeno 3 cifre. Se viene specificato 3, viene anteposto uno 0, altrimenti la modalità viene utilizzata così com'è.
user AID_<user> Il C define per un AID valido o il nome descrittivo (ad esempio, sono accettabili sia AID_RADIO che radio). Per definire un AID personalizzato, vedi Configurazione della sezione AID.
group AID_<group> Uguale a Utente.
caps cap* Il nome come dichiarato in bionic/libc/kernel/uapi/linux/capability.h senza il prefisso CAP_. È consentita la combinazione di maiuscole e minuscole. I sottotitoli codificati possono anche essere i sottotitoli grezzi:
  • binario (0b0101)
  • ottale (0455)
  • int (42)
  • esadecimale (0xFF)
Separa più limiti utilizzando gli spazi vuoti.

Per un esempio di utilizzo, vedi Utilizzo delle funzionalità del file system.

Configurare la sezione AID

La sezione AID contiene gli AID OEM e utilizza la seguente sintassi:

Sezione Valore Definizione
[AID_<name>] <name> può contenere caratteri del set maiuscole, numeri e trattini bassi. La versione in minuscolo viene utilizzata come nome descrittivo. Il file di intestazione generato per l'inclusione del codice utilizza l'esatto AID_<name>.

È un errore specificare più sezioni con lo stesso AID_<name> (senza distinzione tra maiuscole e minuscole con gli stessi vincoli di [path]).

<name> deve iniziare con un nome di partizione per garantire che non entri in conflitto con origini diverse.
value <number> Una stringa numerica valida in stile C (esadecimale, ottale, binario e decimale).

È un errore specificare più sezioni con la stessa opzione di valore.

Le opzioni di valore devono essere specificate nell'intervallo corrispondente alla partizione utilizzata in <name>. L'elenco delle partizioni valide e dei relativi intervalli è definito in system/core/libcutils/include/private/android_filesystem_config.h. Le opzioni sono:
  • Partizione fornitore
    • AID_OEM_RESERVED_START(2900) - AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000) - AID_OEM_RESERVED_2_END(5999)
  • Partizione di sistema
    • AID_SYSTEM_RESERVED_START(6000) - AID_SYSTEM_RESERVED_END(6499)
  • Partizione ODM
    • AID_ODM_RESERVED_START(6500) - AID_ODM_RESERVED_END(6999)
  • Partizione prodotto
    • AID_PRODUCT_RESERVED_START(7000) - AID_PRODUCT_RESERVED_END(7499)
  • Partizione system_ext
    • AID_SYSTEM_EXT_RESERVED_START(7500) - AID_SYSTEM_EXT_RESERVED_END(7999)

Per esempi di utilizzo, vedi Definizione dei nomi AID OEM e Utilizzo degli AID OEM.

Esempi di utilizzo

Gli esempi seguenti mostrano in dettaglio come definire e utilizzare un AID OEM e come attivare le funzionalità del file system. I nomi AID OEM ([AID_name]) devono iniziare con un nome di partizione come "vendor_" per evitare conflitti con futuri nomi AOSP o altre partizioni.

Definisci i nomi AID OEM

Per definire un AID OEM, crea un file config.fs e imposta il valore dell'AID. Ad esempio, in device/x/y/config.fs, imposta quanto segue:

[AID_VENDOR_FOO]
value: 2900

Dopo aver creato il file, imposta la variabile TARGET_FS_CONFIG_GEN e puntala in BoardConfig.mk. Ad esempio, in device/x/y/BoardConfig.mk, imposta quanto segue:

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

Il tuo AID personalizzato ora può essere utilizzato dal sistema nel suo complesso in una nuova build.

Utilizzare gli AID OEM

Per utilizzare un AID OEM, nel codice C includi oemaids_headers nel Makefile associato e aggiungi #include "generated_oem_aid.h", quindi inizia a utilizzare gli identificatori dichiarati. Ad esempio, in my_file.c, aggiungi quanto segue:

#include "generated_oem_aid.h"


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

Nel file Android.bp associato, aggiungi quanto segue:

header_libs: ["oemaids_headers"],

Se utilizzi un file Android.mk, aggiungi quanto segue:

LOCAL_HEADER_LIBRARIES := oemaids_headers

Utilizzare nomi descrittivi

In Android 9, puoi utilizzare il nome descrittivo per qualsiasi interfaccia che supporta i nomi AID. Ad esempio:

  • In un comando chown in some/init.rc:
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • In un service in some/init.rc:
    service vendor_foo /vendor/bin/foo_service
        user vendor_foo
        group vendor_foo
    

Poiché la mappatura interna dal nome descrittivo all'UID viene eseguita da /vendor/etc/passwd e /vendor/etc/group, la partizione del fornitore deve essere montata.

Associare nomi descrittivi

Android 9 include il supporto per l'associazione di un nome descrittivo al valore AID OEM effettivo. Puoi utilizzare argomenti stringa non numerici per utente e gruppo, ad esempio "vendor_foo" anziché "2901".

Convertire gli ID pubblicità in nomi descrittivi

Per OEM AIDs, Android 8.x richiedeva l'utilizzo di oem_#### con getpwnam e funzioni simili, nonché nei punti in cui vengono gestite le ricerche con getpwnam (ad esempio gli script init). In Android 9, puoi utilizzare gli amici getpwnam e getgrnam in Bionic per convertire gli ID Android (AID) in nomi descrittivi e viceversa.

Utilizzare le funzionalità del file system

Per attivare le funzionalità del file system, crea una sezione caps nel file config.fs. Ad esempio, in device/x/y/config.fs, aggiungi la seguente sezione:

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

Dopo aver creato il file, imposta TARGET_FS_CONFIG_GEN in modo che punti a questo file in BoardConfig.mk. Ad esempio, in device/x/y/BoardConfig.mk, imposta quanto segue:

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

Quando viene eseguito il servizio vendor_foo, inizia con le funzionalità CAP_SYS_ADMIN e CAP_SYS_NICE senza chiamate setuid e setgid. Inoltre, la policy SELinux del servizio vendor_foo non richiede più le funzionalità setuid e setgid e può essere eliminata.

Configura gli override (Android 6.x-7.x)

Android 6.0 ha spostato fs_config e le definizioni della struttura associate (system/core/include/private/android_filesystem_config.h) in system/core/libcutils/fs_config.c, dove possono essere aggiornate o ignorate dai file binari installati in /system/etc/fs_config_dirs e /system/etc/fs_config_files. L'utilizzo di regole di corrispondenza e analisi separate per directory e file (che potrebbero utilizzare espressioni glob aggiuntive) ha consentito ad Android di gestire directory e file in due tabelle diverse. Le definizioni della struttura in system/core/libcutils/fs_config.c non solo consentivano la lettura in fase di runtime di directory e file, ma l'host poteva utilizzare gli stessi file durante la fase di build per costruire immagini del file system come ${OUT}/system/etc/fs_config_dirs e ${OUT}/system/etc/fs_config_files.

Sebbene il metodo di override per estendere il file system sia stato sostituito dal sistema di configurazione modulare introdotto in Android 8.0, puoi comunque utilizzare il vecchio metodo, se vuoi. Le sezioni seguenti descrivono in dettaglio come generare e includere file di override e configurare il file system.

Generare file di override

Puoi generare i file binari allineati /system/etc/fs_config_dirs e /system/etc/fs_config_files utilizzando lo strumento fs_config_generate in build/tools/fs_config. Lo strumento utilizza una funzione di libreria libcutils (fs_config_generate()) per gestire i requisiti DAC in un buffer e definisce le regole per un file di inclusione per istituzionalizzare le regole DAC.

Per utilizzarlo, crea un file di inclusione in device/vendor/device/android_filesystem_config.h che funge da override. Il file deve utilizzare il formato structure fs_path_config definito in system/core/include/private/android_filesystem_config.h con le seguenti inizializzazioni della struttura per i simboli di directory e file:

  • Per le directory, utilizza android_device_dirs[].
  • Per i file, utilizza android_device_files[].

Quando non utilizzi android_device_dirs[] e android_device_files[], puoi definire NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS e NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (vedi l'esempio di seguito). Puoi anche specificare il file di override utilizzando TARGET_ANDROID_FILESYSTEM_CONFIG_H nella configurazione della scheda, con un nome base forzato di android_filesystem_config.h.

Includi file di override

Per includere i file, assicurati che PRODUCT_PACKAGES includa fs_config_dirs e/o fs_config_files in modo che possa installarli rispettivamente in /system/etc/fs_config_dirs e /system/etc/fs_config_files. Il sistema di compilazione cerca android_filesystem_config.h personalizzati in $(TARGET_DEVICE_DIR), dove esiste BoardConfig.mk. Se questo file esiste altrove, imposta la variabile di configurazione della scheda TARGET_ANDROID_FILESYSTEM_CONFIG_H in modo che punti a quella posizione.

Configura il file system

Per configurare il file system in Android 6.0 e versioni successive:

  1. Crea il file $(TARGET_DEVICE_DIR)/android_filesystem_config.h.
  2. Aggiungi fs_config_dirs e/o fs_config_files a PRODUCT_PACKAGES nel file di configurazione della scheda (ad es. $(TARGET_DEVICE_DIR)/device.mk).

Esempio di override

Questo esempio mostra una patch per l'override del daemon system/bin/glgps per aggiungere il supporto del wake lock nella directory device/vendor/device. Tieni presente quanto segue:

  • Ogni voce della struttura è la modalità, l'uid, il gid, le funzionalità e il nome. system/core/include/private/android_filesystem_config.h è incluso automaticamente per fornire le definizioni del manifest (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND).
  • La sezione android_device_files[] include un'azione per impedire l'accesso a system/etc/fs_config_dirs quando non specificato, che funge da protezione DAC aggiuntiva per la mancanza di contenuti per gli override della directory. Tuttavia, questa è una protezione debole: se qualcuno ha il controllo di /system, in genere può fare quello che vuole.
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)

Eseguire la migrazione dei file system dalle release precedenti

Quando esegui la migrazione dei file system da Android 5.x e versioni precedenti, tieni presente che Android 6.x

  • Rimuove alcuni include, strutture e definizioni inline.
  • Richiede un riferimento a libcutils anziché l'esecuzione diretta da system/core/include/private/android_filesystem_config.h. Gli eseguibili privati del produttore del dispositivo che dipendono da system/code/include/private_filesystem_config.h per il file o le strutture di directory o fs_config devono aggiungere le dipendenze della libreria libcutils.
  • Richiede copie private del ramo del produttore del dispositivo di system/core/include/private/android_filesystem_config.h con contenuti aggiuntivi sui target esistenti da spostare su device/vendor/device/android_filesystem_config.h.
  • Si riserva il diritto di applicare i controlli di accesso obbligatori (MAC) di SELinux ai file di configurazione sul sistema di destinazione. Le implementazioni che includono eseguibili di destinazione personalizzati che utilizzano fs_config() devono garantire l'accesso.