Controllo di accesso discrezionale (DAC)

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

Le versioni precedenti di Android (Android 7.xe precedenti) estendevano il meccanismo degli AID utilizzando un file android_filesystem_config.h specifico del dispositivo per specificare le capacità del filesystem e/o gli AID OEM personalizzati. Tuttavia, questo sistema non era intuitivo in quanto non supportava l'uso di bei nomi per gli AID OEM, richiedendo di specificare il valore numerico grezzo 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 capacità del filesystem. Questo nuovo metodo supporta quanto segue:

  • Posizioni di origine multiple per i file di configurazione (consente configurazioni di build estensibili).
  • Controllo dell'integrità in fase di costruzione dei valori AID OEM.
  • Generazione di un'intestazione OEM AID personalizzata che può essere utilizzata nei file di origine secondo necessità.
  • Associazione di un nome descrittivo con il valore AID OEM effettivo. Supporta argomenti di stringa non numerici per utente e gruppo, ad esempio "pippo" 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 un array generato completamente privato, con accessor tramite getpwnam() e getgrnam() . (Ciò ha l'effetto collaterale di produrre binari stabili quando 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[] 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 corrispondente AID_* viene prelevata dall'utensileria e * diventa il nome minuscolo.

Ad esempio, in private/android_filesystem_config.h :

#define AID_SYSTEM 1000

diventa:

  • Nome descrittivo: sistema
  • id: 1000
  • gid: 1000

Per aggiungere un nuovo AID core AOSP, aggiungi semplicemente #define al file di intestazione android_filesystem_config.h . L'AID verrà generato in fase di compilazione e reso disponibile alle interfacce che utilizzano argomenti utente e gruppo. La strumentazione convalida il nuovo AID non rientra nelle gamme APP o OEM; rispetta anche le modifiche a tali intervalli e dovrebbe riconfigurarsi automaticamente in base alle modifiche o ai nuovi intervalli riservati dagli OEM.

Configurazione degli AID

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

Per convenzione, i file di configurazione usano il nome config.fs , ma in pratica puoi usare qualsiasi nome. I file config.fs sono nel formato Python ConfigParser ini e includono una sezione caps (per la configurazione delle funzionalità del file system) e una sezione AIDs (per la configurazione degli AID OEM).

Configurazione della sezione tappi

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

Poiché l'esecuzione di un servizio stabile come root in Android provoca un errore di Compatibility Test Suite (CTS) , i requisiti precedenti per il mantenimento di una funzionalità durante l'esecuzione di un processo o servizio prevedevano la configurazione delle funzionalità e l'utilizzo di setuid / setgid su un AID appropriato per l'esecuzione. Con i caps, puoi saltare questi requisiti e fare in modo che il kernel lo faccia 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 maiuscole utilizza la seguente sintassi:

Sezione Valore Definizione
[path] Il percorso del filesystem 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 sovrascrivono la sezione precedente; in Python 3.2, è impostato in modalità rigorosa.
mode Modalità file ottale Una modalità file ottale valida di almeno 3 cifre. Se viene specificato 3, viene preceduto da 0, altrimenti la modalità viene utilizzata così com'è.
user AIUTO_<utente> O la define C per un AID valido o il nome descrittivo (ad es. sia AID_RADIO che radio sono accettabili). Per definire un AID personalizzato, vedere la sezione Configurazione dell'AID .
group AIUTO_<gruppo> Uguale all'utente.
caps berretto* Il nome dichiarato in bionic/libc/kernel/uapi/linux/capability.h senza CAP_ . Caso misto consentito. I tappi possono anche essere grezzi:
  • binario (0b0101)
  • ottale (0455)
  • int (42)
  • esadecimale (0xFF)
Separa più maiuscole usando gli spazi bianchi.

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

Configurazione della sezione AIUTI

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

Sezione Valore Definizione
[AID_<name>] Il <name> può contenere caratteri nel set di lettere maiuscole, numeri e trattini bassi. La versione minuscola 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 assicurarsi che non sia in conflitto con origini diverse.
value <numero> Una stringa di numeri di stile C valida (esadecimale, ottale, binario 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 dei relativi intervalli è definito 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 di nomi AID OEM e Utilizzo di AID OEM .

Esempi di utilizzo

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

Definizione dei nomi degli AID OEM

Per definire un OEM AID, creare un file config.fs e impostare il valore AID. Ad esempio, in device/x/y/config.fs , impostare 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 ora può essere utilizzato dal sistema in generale su una nuova build.

Utilizzo di 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 stai utilizzando un file Android.mk , aggiungi quanto segue:

LOCAL_HEADER_LIBRARIES := oemaids_headers

Usare 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 al valore effettivo dell'AID OEM. È 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 AID OEM , Android 8.x richiedeva l'uso di oem_#### con getpwnam e funzioni simili, nonché in luoghi che gestiscono le ricerche tramite getpwnam (come gli script init ). In Android 9, puoi utilizzare getpwnam e getgrnam friends 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 il servizio vendor_ foo viene eseguito, inizia con le funzionalità CAP_SYS_ADMIN e CAP_SYS_NICE senza chiamate setuid e setgid . Inoltre, la politica SELinux del servizio vendor_ foo non necessita più di capacità setuid e setgid e può essere eliminata.

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

Android 6.0 ha trasferito fs_config e le definizioni delle strutture associate ( system/core/include/private/android_filesystem_config.h ) in system/core/libcutils/fs_config.c dove potrebbero essere aggiornate o sovrascritte da 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 runtime di directory e file, ma l'host poteva utilizzare gli stessi file durante la fase di compilazione per costruire immagini del filesystem come ${OUT}/system/etc/fs_config_dirs e ${OUT}/system/etc/fs_config_files .

Sebbene il metodo di sovrascrittura dell'estensione del filesystem sia stato sostituito dal sistema di configurazione modulare introdotto in Android 8.0, puoi comunque utilizzare il vecchio metodo se lo desideri. Le sezioni seguenti descrivono in dettaglio come generare e includere file di sostituzione 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 della libreria libcutils ( fs_config_generate() ) per gestire i requisiti DAC in un buffer e definisce le regole per un file include per istituzionalizzare le regole DAC.

Per utilizzarlo, crea un file include in device/ vendor / device /android_filesystem_config.h che funge da override. Il file deve utilizzare il formato della 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, usa android _device _dirs[] .
  • Per i file, usa android _device _files[] .

Quando non usi 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 sotto). Puoi anche specificare il file di override utilizzando TARGET_ANDROID_FILESYSTEM_CONFIG_H nella configurazione della scheda, con un nome di base forzato di android_filesystem_config.h .

Compresi i file di sostituzione

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 build cerca android_filesystem_config.h personalizzato 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 filesystem

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 del wakelock nella directory device/ vendor / device . Tieni a mente quanto segue:

  • Ogni voce della struttura è la modalità, l'uid, il gid, le capacità 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 sostituzioni 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 migra i filesystem da Android 5.x e versioni precedenti, tenere presente che Android 6.x

  • Rimuove alcune inclusioni, strutture e definizioni inline.
  • 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 aggiuntivo su target esistenti da spostare su device/ vendor / device /android_filesystem_config.h .
  • Si riserva il diritto di applicare SELinux Mandatory Access Controls (MAC) ai file di configurazione sul sistema di destinazione, le implementazioni che includono eseguibili di destinazione personalizzati che utilizzano fs_config() devono garantire l'accesso.