Uznaniowa kontrola dostępu (DAC)

Obiekty i usługi systemu plików dodawane do kompilacji często wymagają oddzielnych, unikalnych identyfikatorów, znanych jako identyfikatory Androida (AID). Obecnie wiele zasobów, takich jak pliki i usługi, niepotrzebnie korzysta z podstawowych (zdefiniowanych w systemie Android) pomocy pomocniczych; w wielu przypadkach można zamiast tego użyć pomocy OEM (zdefiniowanych przez OEM).

Wcześniejsze wersje Androida (Android 7.x i starsze) rozszerzyły mechanizm AID za pomocą specyficznego dla urządzenia pliku android_filesystem_config.h , aby określić możliwości systemu plików i/lub niestandardowe AID OEM. Jednakże system ten był nieintuicyjny, ponieważ nie obsługiwał używania ładnych nazw dla identyfikatorów AID OEM, co wymagało określenia nieprzetworzonej wartości liczbowej dla pól użytkownika i grupy bez możliwości powiązania przyjaznej nazwy z numerycznym identyfikatorem AID.

Nowsze wersje Androida (Android 8.0 i nowsze) obsługują nową metodę rozszerzania możliwości systemu plików. Ta nowa metoda obsługuje następujące elementy:

  • Wiele lokalizacji źródłowych plików konfiguracyjnych (umożliwia rozszerzalne konfiguracje kompilacji).
  • Sprawdzanie poprawności wartości OEM AID w czasie kompilacji.
  • Generowanie niestandardowego nagłówka OEM AID, który w razie potrzeby może być używany w plikach źródłowych.
  • Powiązanie przyjaznej nazwy z rzeczywistą wartością OEM AID. Obsługuje nienumeryczne argumenty łańcuchowe dla użytkownika i grupy, tj. „foo” zamiast „2901”.

Dodatkowe ulepszenia obejmują usunięcie tablicy android_ids[] z system/core/libcutils/include/private/android_filesystem_config.h . Ta tablica istnieje teraz w Bionic jako w pełni prywatna tablica wygenerowana z akcesoriami poprzez getpwnam() i getgrnam() . (Ma to efekt uboczny polegający na tworzeniu stabilnych plików binarnych w miarę modyfikowania podstawowych identyfikatorów AID.) Informacje o narzędziach i pliku README zawierającym więcej szczegółów można znaleźć w build/make/tools/fs_config .

Dodawanie identyfikatorów Androida (AID)

Android 8.0 usunął tablicę android_ids[] z projektu Android Open Source Project (AOSP). Zamiast tego wszystkie nazwy przyjazne AID są generowane z pliku nagłówkowego system/core/libcutils/include/private/android_filesystem_config.h podczas generowania tablicy Bionic android_ids[] . Każda define pasująca do AID_* jest pobierana przez narzędzie, a * staje się nazwą małą literą.

Na przykład w private/android_filesystem_config.h :

#define AID_SYSTEM 1000

Staje się:

  • Przyjazna nazwa: system
  • identyfikator: 1000
  • gid: 1000

Aby dodać nowy podstawowy identyfikator AOSP, po prostu dodaj #define do pliku nagłówkowego android_filesystem_config.h . Identyfikator AID zostanie wygenerowany podczas kompilacji i udostępniony interfejsom korzystającym z argumentów użytkownika i grupy. Narzędzie sprawdza, czy nowy AID nie mieści się w zakresie aplikacji lub OEM; uwzględnia również zmiany w tych zakresach i powinien automatycznie dokonać ponownej konfiguracji w przypadku zmian lub nowych zakresów zastrzeżonych przez OEM.

Konfigurowanie pomocy

Aby włączyć nowy mechanizm AIDs, ustaw TARGET_FS_CONFIG_GEN w pliku BoardConfig.mk . Ta zmienna przechowuje listę plików konfiguracyjnych, umożliwiając dołączanie plików w razie potrzeby.

Zgodnie z konwencją pliki konfiguracyjne używają nazwy config.fs , ale w praktyce można użyć dowolnej nazwy. Pliki config.fs są w formacie ini Pythona ConfigParser i zawierają sekcję caps (do konfigurowania możliwości systemu plików) i sekcję AIDs (do konfigurowania OEM AID).

Konfiguracja sekcji wielkich liter

Sekcja caps obsługuje ustawianie możliwości systemu plików dla obiektów systemu plików w ramach kompilacji (sam system plików musi również obsługiwać tę funkcjonalność).

Ponieważ uruchomienie stabilnej usługi jako root w systemie Android powoduje awarię pakietu testów zgodności (CTS) , poprzednie wymagania dotyczące zachowania możliwości podczas uruchamiania procesu lub usługi wymagały skonfigurowania możliwości, a następnie użycia setuid / setgid do uruchomienia odpowiedniego identyfikatora AID. Dzięki wielkim literom możesz pominąć te wymagania i pozwolić, aby jądro zrobiło to za Ciebie. Kiedy kontrola jest przekazywana do main() , Twój proces ma już potrzebne możliwości, dzięki czemu Twoja usługa może korzystać z użytkownika i grupy innej niż root (jest to preferowany sposób uruchamiania usług uprzywilejowanych).

W sekcji caps zastosowano następującą składnię:

Sekcja Wartość Definicja
[path] Ścieżka systemu plików do skonfigurowania. Ścieżka kończąca się na / jest uważana za katalog, w przeciwnym razie jest to plik.

Określanie wielu sekcji z tą samą [path] w różnych plikach jest błędem. W wersjach Pythona <= 3.2 ten sam plik może zawierać sekcje, które zastępują poprzednią sekcję; w Pythonie 3.2 jest ustawiony na tryb ścisły.
mode Tryb pliku ósemkowego Prawidłowy tryb pliku ósemkowego składający się z co najmniej 3 cyfr. Jeśli określono wartość 3, jest ona poprzedzona cyfrą 0, w przeciwnym razie używany jest tryb bez zmian.
user AID_<użytkownik> Albo C define ważny AID, albo przyjazną nazwę (np. akceptowane są zarówno AID_RADIO jak i radio ). Aby zdefiniować niestandardowy AID, zobacz sekcję Konfigurowanie AID .
group AID_<grupa> Tak samo jak użytkownik.
caps czapka* Nazwa zadeklarowana w bionic/libc/kernel/uapi/linux/capability.h bez wiodącego CAP_ . Dozwolony przypadek mieszany. Czapki mogą być również surowe:
  • binarny (0b0101)
  • ósemkowy (0455)
  • int (42)
  • szesnastkowo (0xFF)
Oddziel wiele wielkich liter spacjami.

Aby zapoznać się z przykładem użycia, zobacz Korzystanie z możliwości systemu plików .

Konfiguracja sekcji AID

Sekcja AID zawiera identyfikatory OEM OEM i ma następującą składnię:

Sekcja Wartość Definicja
[AID_<name>] <name> może zawierać ustawione wielkie litery, cyfry i podkreślenia. Jako przyjazna nazwa używana jest wersja z małymi literami. Wygenerowany plik nagłówkowy do włączenia kodu używa dokładnego AID_<name> .

Określenie wielu sekcji z tym samym AID_<name> (wielkość liter nie jest uwzględniana przy takich samych ograniczeniach jak [path] ) jest błędem.

<name> musi zaczynać się od nazwy partycji, aby mieć pewność, że nie powoduje konfliktu z różnymi źródłami.
value <numer> Prawidłowy ciąg liczbowy w stylu C (szesnastkowy, ósemkowy, binarny i dziesiętny).

Określenie wielu sekcji z tą samą opcją wartości jest błędem.

Opcje wartości muszą być określone w zakresie odpowiadającym partycji użytej w <name> . Lista prawidłowych partycji i odpowiadających im zakresów jest zdefiniowana w system/core/libcutils/include/private/android_filesystem_config.h . Dostępne opcje to:
  • Partycja dostawcy
    • AID_OEM_RESERVED_START(2900) - AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000) - AID_OEM_RESERVED_2_END(5999)
  • Partycja systemowa
    • AID_SYSTEM_RESERVED_START(6000) - AID_SYSTEM_RESERVED_END(6499)
  • Partycja ODM
    • AID_ODM_RESERVED_START(6500) - AID_ODM_RESERVED_END(6999)
  • Podział produktu
    • AID_PRODUCT_RESERVED_START(7000) - AID_PRODUCT_RESERVED_END(7499)
  • Partycja System_ext
    • AID_SYSTEM_EXT_RESERVED_START(7500) - AID_SYSTEM_EXT_RESERVED_END(7999)

Aby zapoznać się z przykładami użycia, zobacz Definiowanie nazw OEM AID i Używanie OEM AID .

Przykłady użycia

Poniższe przykłady szczegółowo opisują sposób definiowania i używania OEM AID oraz włączania funkcji systemu plików. Nazwy OEM AID ( [ nazwa AID_ ] ) muszą zaczynać się od nazwy partycji, np. „ sprzedawca_ ”, aby mieć pewność, że nie kolidują z przyszłymi nazwami AOSP lub innymi partycjami.

Definiowanie nazw OEM AID

Aby zdefiniować AID OEM, utwórz plik config.fs i ustaw wartość AID. Na przykład w device/x/y/config.fs ustaw co następuje:

[AID_VENDOR_FOO]
value: 2900

Po utworzeniu pliku ustaw zmienną TARGET_FS_CONFIG_GEN i wskaż ją w BoardConfig.mk . Na przykład w device/x/y/BoardConfig.mk ustaw co następuje:

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

Twój niestandardowy identyfikator AID może teraz zostać wykorzystany przez cały system w nowej kompilacji.

Korzystanie z pomocy OEM

Aby użyć OEM AID, w kodzie C umieść oemaids_headers w powiązanym pliku Makefile i dodaj #include "generated_oem_aid.h" , a następnie zacznij używać zadeklarowanych identyfikatorów. Na przykład w my_file.c dodaj następujące elementy:

#include "generated_oem_aid.h"
…

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

W powiązanym pliku Android.bp dodaj następujące elementy:

header_libs: ["oemaids_headers"],

Jeśli używasz pliku Android.mk , dodaj następujące elementy:

LOCAL_HEADER_LIBRARIES := oemaids_headers

Używanie przyjaznych imion

W systemie Android 9 możesz używać przyjaznej nazwy dla dowolnego interfejsu obsługującego nazwy AID. Na przykład:

  • W poleceniu chown w some/init.rc :
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • W service w some/init.rc :
    service vendor_foo /vendor/bin/foo_service
        user vendor_foo
        group vendor_foo
    

Ponieważ wewnętrzne mapowanie przyjaznej nazwy na uid jest wykonywane przez /vendor/etc/passwd i /vendor/etc/group , partycja dostawcy musi zostać zamontowana.

Łączenie przyjaznych nazw

Android 9 obsługuje kojarzenie przyjaznej nazwy z rzeczywistą wartością AID OEM. Dla użytkownika i grupy można używać nienumerycznych argumentów w postaci łańcuchów, np. „ vendor_foo ” zamiast „2901”.

Konwersja z AID na przyjazne nazwy

W przypadku OEM AID , Android 8.x wymagał użycia oem_#### z getpwnam i podobnymi funkcjami, a także w miejscach obsługujących wyszukiwania poprzez getpwnam (takich jak skrypty init ). W systemie Android 9 możesz używać znajomych getpwnam i getgrnam w Bionic do konwersji identyfikatorów Androida (AID) na przyjazne nazwy i odwrotnie.

Korzystanie z możliwości systemu plików

Aby włączyć możliwości systemu plików, utwórz sekcję caps w pliku config.fs . Na przykład w device/x/y/config.fs dodaj następującą sekcję:

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

Po utworzeniu pliku ustaw TARGET_FS_CONFIG_GEN tak, aby wskazywał ten plik w BoardConfig.mk . Na przykład w device/x/y/BoardConfig.mk ustaw co następuje:

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

Kiedy wykonywana jest usługa vendor_ foo , zaczyna się od możliwości CAP_SYS_ADMIN i CAP_SYS_NICE bez wywołań setuid i setgid . Ponadto polityka SELinux usługi vendor_ foo nie wymaga już możliwości setuid i setgid i można ją usunąć.

Konfigurowanie zastąpień (Android 6.x-7.x)

W systemie Android 6.0 przeniesiono fs_config i powiązane definicje struktur ( system/core/include/private/android_filesystem_config.h ) do system/core/libcutils/fs_config.c gdzie można je aktualizować lub zastępować plikami binarnymi zainstalowanymi w /system/etc/fs_config_dirs i /system/etc/fs_config_files . Użycie oddzielnych reguł dopasowywania i analizowania katalogów i plików (w których można zastosować dodatkowe wyrażenia glob) umożliwiło systemowi Android obsługę katalogów i plików w dwóch różnych tabelach. Definicje struktur w system/core/libcutils/fs_config.c nie tylko umożliwiały odczytywanie katalogów i plików w czasie wykonywania, ale host mógł używać tych samych plików podczas kompilacji do konstruowania obrazów systemów plików jako ${OUT}/system/etc/fs_config_dirs i ${OUT}/system/etc/fs_config_files .

Chociaż metoda zastępowania rozszerzania systemu plików została zastąpiona modułowym systemem konfiguracji wprowadzonym w systemie Android 8.0, w razie potrzeby nadal możesz używać starej metody. Poniższe sekcje szczegółowo opisują sposób generowania i dołączania plików zastępujących oraz konfigurowania systemu plików.

Generowanie plików zastąpień

Możesz wygenerować dopasowane pliki binarne /system/etc/fs_config_dirs i /system/etc/fs_config_files za pomocą narzędzia fs_config_generate w build/tools/fs_config . Narzędzie wykorzystuje funkcję biblioteczną libcutils ( fs_config_generate() ) do zarządzania wymaganiami DAC w buforze i definiuje reguły dla pliku dołączanego w celu instytucjonalizacji reguł DAC.

Aby skorzystać, utwórz plik dołączany w device/ vendor / device /android_filesystem_config.h , który będzie pełnił funkcję zastąpienia. Plik musi mieć structure fs_path_config zdefiniowaną w system/core/include/private/android_filesystem_config.h z następującymi inicjacjami struktury dla symboli katalogów i plików:

  • W przypadku katalogów użyj android _device _dirs[] .
  • W przypadku plików użyj android _device _files[] .

Jeśli nie używasz android_device_dirs[] i android_device_files[] , możesz zdefiniować NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS i NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (patrz przykład poniżej). Możesz także określić plik zastępujący, używając TARGET_ANDROID_FILESYSTEM_CONFIG_H w konfiguracji płyty, z wymuszoną nazwą bazową android_filesystem_config.h .

Łącznie z plikami zastępującymi

Aby uwzględnić pliki, upewnij się, że PRODUCT_PACKAGES zawiera fs_config_dirs i/lub fs_config_files , co umożliwi ich zainstalowanie odpowiednio w katalogach /system/etc/fs_config_dirs i /system/etc/fs_config_files . System kompilacji wyszukuje niestandardowy android_filesystem_config.h w $(TARGET_DEVICE_DIR) , gdzie istnieje BoardConfig.mk . Jeśli ten plik istnieje gdzie indziej, ustaw zmienną konfiguracyjną płyty TARGET_ANDROID_FILESYSTEM_CONFIG_H , aby wskazywała tę lokalizację.

Konfiguracja systemu plików

Aby skonfigurować system plików w systemie Android 6.0 i nowszych wersjach:

  1. Utwórz plik $(TARGET_DEVICE_DIR)/android_filesystem_config.h .
  2. Dodaj fs_config_dirs i/lub fs_config_files do PRODUCT_PACKAGES w pliku konfiguracyjnym płyty (np. $(TARGET_DEVICE_DIR)/device.mk ).

Zastąp przykład

Ten przykład pokazuje łatkę umożliwiającą zastąpienie demona system/bin/glgps w celu dodania obsługi blokady wybudzania w katalogu device/ vendor / device . Pamiętaj o następujących kwestiach:

  • Każdy wpis struktury to tryb, uid, gid, możliwości i nazwa. system/core/include/private/android_filesystem_config.h jest dołączany automatycznie w celu dostarczenia manifestu #defines ( AID_ROOT , AID_SHELL , CAP_BLOCK_SUSPEND ).
  • Sekcja android_device_files[] zawiera akcję blokującą dostęp do system/etc/fs_config_dirs gdy nie jest określony, co służy jako dodatkowa ochrona DAC w przypadku braku treści w przypadku zastąpienia katalogów. Jest to jednak słaba ochrona; jeśli ktoś ma kontrolę nad /system , zazwyczaj może zrobić, co chce.
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)

Migracja systemów plików z wcześniejszych wersji

Podczas migracji systemów plików z Androida 5.x i wcześniejszych wersji należy pamiętać, że Android 6.x

  • Usuwa niektóre dołączenia, struktury i definicje wbudowane.
  • Wymaga odniesienia do libcutils zamiast uruchamiania bezpośrednio z system/core/include/private/android_filesystem_config.h . Prywatne pliki wykonywalne producenta urządzenia, które zależą od system/code/include/private_filesystem_config.h dla struktur plików lub katalogów albo fs_config , muszą dodać zależności biblioteki libcutils .
  • Wymaga przeniesienia kopii pliku system/core/include/private/android_filesystem_config.h producenta urządzenia z gałęzi prywatnej producenta urządzenia z dodatkową zawartością na istniejących obiektach docelowych do przeniesienia do device/ vendor / device /android_filesystem_config.h .
  • Zastrzega sobie prawo do stosowania obowiązkowej kontroli dostępu SELinux (MAC) do plików konfiguracyjnych w systemie docelowym. Implementacje zawierające niestandardowe docelowe pliki wykonywalne korzystające z fs_config() muszą zapewniać dostęp.