Controllo accessi discrezionale (DAC)

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

Le versioni precedenti di Android (Android 7.x e precedenti) estendevano il meccanismo degli 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 in quanto non supportava l'utilizzo di nomi piacevoli per gli AID OEM, richiedendo di specificare il valore numerico non elaborato per i campi utente e gruppo senza la possibilità di associare un nome descrittivo all'AID numerico.

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

  • Posizioni di origine multiple per i file di configurazione (abilita configurazioni di build estensibili).
  • Controllo dell'integrità in fase di compilazione dei valori OEM AID.
  • Generazione di un'intestazione OEM AID personalizzata che può essere utilizzata nei file di origine secondo necessità.
  • Associazione di un nome descrittivo con l'effettivo valore OEM AID. Supporta argomenti di stringa non numerici per utente e gruppo, ad esempio "foo" invece di "2901".

Ulteriori 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 tramite getpwnam() e getgrnam() . (Ciò ha l'effetto collaterale di produrre file binari stabili man mano che gli AID principali vengono modificati.) Per gli strumenti e un file README con maggiori dettagli, fare riferimento a build/make/tools/fs_config .

Aggiunta di ID Android (AID)

Android 8.0 ha rimosso l'array android_ids[] dal progetto Android Open Source (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 AID_* corrispondente viene rilevata dallo strumento e * diventa il nome in minuscolo.

Ad esempio, in private/android_filesystem_config.h :

#define AID_SYSTEM 1000

Diventa:

  • Nome descrittivo: sistema
  • uido: 1000
  • già: 1000

Per aggiungere un nuovo AOSP core AID, aggiungi semplicemente #define al file di intestazione android_filesystem_config.h . L'AID verrà generato durante la compilazione e reso disponibile alle interfacce che utilizzano argomenti utente e gruppo. Gli strumenti convalidano che il nuovo AID non rientra negli intervalli APP o OEM; rispetta inoltre le modifiche a tali gamme e dovrebbe riconfigurarsi automaticamente in caso di modifiche o nuove gamme riservate agli OEM.

Configurazione degli aiuti

Per abilitare il nuovo meccanismo AID, impostare TARGET_FS_CONFIG_GEN nel file BoardConfig.mk . Questa variabile contiene un elenco di file di configurazione, consentendoti di aggiungere file secondo necessità.

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

Configurazione della sezione tappi

La sezione caps supporta l'impostazione delle funzionalità del file system 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 provoca un errore CTS (Compatibility Test Suite) , i requisiti precedenti per mantenere una funzionalità durante l'esecuzione di un processo o servizio prevedevano la configurazione di funzionalità e quindi l'utilizzo di setuid / setgid per un AID appropriato da eseguire. Con i caps, puoi saltare questi requisiti e lasciare che sia il kernel a farlo per te. Quando il controllo viene passato a main() , il tuo processo ha già le capacità di cui ha bisogno in modo che il tuo servizio possa utilizzare un utente e un gruppo non root (questo è il modo preferito per avviare servizi privilegiati).

La sezione caps 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 Python <= 3.2, lo stesso file può contenere sezioni che sovrascrivono la sezione precedente; in Python 3.2, è impostato sulla modalità rigorosa.
mode Modalità file ottale Una modalità file ottale valida di almeno 3 cifre. Se viene specificato 3, viene preceduto da uno 0, altrimenti la modalità viene utilizzata così com'è.
user AID_<utente> O il C define un AID valido o il nome descrittivo (ad esempio, sono accettabili sia AID_RADIO che radio ). Per definire un AID personalizzato, vedere la sezione Configurazione dell'AID .
group AID_<gruppo> Uguale all'utente.
caps berretto* Il nome dichiarato in bionic/libc/kernel/uapi/linux/capability.h senza CAP_ iniziale. Sono ammessi casi misti. I tappi possono anche essere crudi:
  • binario (0b0101)
  • ottale (0455)
  • intero (42)
  • esadecimale (0xFF)
Separa più maiuscole utilizzando gli spazi bianchi.

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

Configurazione della sezione AIUTI

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

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

È un errore specificare più sezioni con lo stesso AID_<name> (senza distinzione tra maiuscole e minuscole e 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 <numero> Una stringa numerica in stile C valida (esadecimale, ottale, binaria e decimale).

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

Le opzioni del valore devono essere specificate nell'intervallo corrispondente alla partizione utilizzata in <name> . L'elenco delle partizioni valide e i relativi intervalli corrispondenti sono definiti in system/core/libcutils/include/private/android_filesystem_config.h . Le opzioni sono:
  • Partizione del 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 del 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, vedere Definizione dei nomi degli aiuti OEM e Utilizzo degli aiuti OEM .

Esempi di utilizzo

I seguenti esempi descrivono in dettaglio come definire e utilizzare un OEM AID e come abilitare le funzionalità del file system. I nomi AID OEM ( [AID_ name ] ) devono iniziare con un nome di partizione come " vendor_ " per garantire che non siano in conflitto con futuri nomi AOSP o altre partizioni.

Definizione dei nomi degli aiuti OEM

Per definire un AID OEM, creare un file config.fs e impostare il valore 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 punta ad essa 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 può ora essere utilizzato dal sistema in generale in una nuova build.

Utilizzo degli aiuti OEM

Per utilizzare un OEM AID, nel tuo codice C, includi oemaids_headers nel tuo 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

Utilizzando nomi amichevoli

In Android 9, puoi utilizzare il nome descrittivo per qualsiasi interfaccia che supporti i nomi AID. Per 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.

Associazione di nomi amichevoli

Android 9 include il supporto per associare un nome descrittivo all'effettivo valore OEM AID. È possibile utilizzare argomenti di stringa non numerici per utente e gruppo, ad esempio " vendor_ foo" invece di "2901".

Conversione da AID a nomi amichevoli

Per gli OEM AID , Android 8.x richiedeva l'uso di oem_#### con getpwnam e funzioni simili, nonché in posizioni che gestiscono le ricerche tramite getpwnam (come gli script init ). In Android 9, puoi utilizzare gli amici getpwnam e getgrnam in Bionic per convertire da ID Android (AID) a nomi descrittivi e viceversa.

Utilizzo delle funzionalità del file system

Per abilitare le funzionalità del filesystem, creare 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 quel 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 necessita più delle funzionalità setuid e setgid e può essere eliminata.

Configurazione delle sostituzioni (Android 6.x-7.x)

Android 6.0 ha spostato fs_config e le definizioni della struttura associata ( system/core/include/private/android_filesystem_config.h ) su system/core/libcutils/fs_config.c dove potrebbero essere aggiornati o sovrascritti 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 esecuzione di directory e file, ma l'host poteva utilizzare gli stessi file durante la compilazione per costruire immagini del filesystem come ${OUT}/system/etc/fs_config_dirs e ${OUT}/system/etc/fs_config_files .

Anche se il metodo di override per estendere il filesystem è stato sostituito dal sistema di configurazione modulare introdotto in Android 8.0, se lo desideri puoi comunque utilizzare il vecchio metodo. Le sezioni seguenti descrivono in dettaglio come generare e includere file di override e configurare il filesystem.

Generazione di file di sostituzione

È possibile 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, utilizzare android _device _dirs[] .
  • Per i file, utilizzare android _device _files[] .

Quando non si utilizza android_device_dirs[] e android_device_files[] , è possibile definire NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS e NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (vedere l' esempio seguente). Puoi anche specificare il file di override utilizzando TARGET_ANDROID_FILESYSTEM_CONFIG_H nella configurazione della scheda, con un nome base applicato di android_filesystem_config.h .

Inclusi i file di sostituzione

Per includere 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 custom android_filesystem_config.h 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.

Configurazione del file system

Per configurare il filesystem 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 esempio, $(TARGET_DEVICE_DIR)/device.mk ).

Sostituisci esempio

Questo esempio mostra una patch per sovrascrivere il demone system/bin/glgps per aggiungere il supporto per il wakelock nella directory device/ vendor / device . Tieni presente quanto segue:

  • Ogni voce della struttura rappresenta la modalità, l'uid, il gid, le funzionalità e il nome. system/core/include/private/android_filesystem_config.h viene incluso automaticamente per fornire il manifest #defines ( AID_ROOT , AID_SHELL , CAP_BLOCK_SUSPEND ).
  • La sezione android_device_files[] include un'azione per sopprimere l'accesso a system/etc/fs_config_dirs quando non specificato, che funge da protezione DAC aggiuntiva per la mancanza di contenuto per le sovrascritture delle directory. Tuttavia, questa è una protezione debole; se qualcuno ha il controllo su /system , in genere può fare tutto ciò 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 filesystem
+** 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)

Migrazione di filesystem da versioni precedenti

Quando si esegue la migrazione dei file system da Android 5.x e versioni precedenti, tenere presente che Android 6.x

  • Rimuove alcune inclusioni, strutture e definizioni in linea.
  • Richiede un riferimento a libcutils invece di essere eseguito direttamente 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 le strutture di file o directory o fs_config devono aggiungere le dipendenze della libreria libcutils .
  • Richiede copie del ramo privato del produttore del dispositivo di system/core/include/private/android_filesystem_config.h con contenuto extra sulle destinazioni esistenti da spostare su device/ vendor / device /android_filesystem_config.h .
  • Si riserva il diritto di applicare i controlli di accesso obbligatori di SELinux (MAC) ai file di configurazione sul sistema di destinazione, le implementazioni che includono eseguibili di destinazione personalizzati utilizzando fs_config() devono garantire l'accesso.