Dyskrecjonalna kontrola dostępu (DAC)

Obiekty i usługi systemu plików dodawane do kompilacji często wymagają oddzielnych, unikalnych identyfikatorów, zwanych identyfikatorami Androida (AID). Obecnie wiele zasobów, takich jak pliki i usługi, niepotrzebnie używa podstawowych identyfikatorów AID (zdefiniowanych przez Androida). W wielu przypadkach możesz zamiast nich używać identyfikatorów AID OEM (zdefiniowanych przez producenta OEM).

Wcześniejsze wersje Androida (Android 7.x i starsze) rozszerzały mechanizm identyfikatorów AID za pomocą pliku android_filesystem_config.h specyficznego dla urządzenia, aby określić możliwości systemu plików lub niestandardowe identyfikatory AID OEM. Ten system był jednak mało intuicyjny, ponieważ nie obsługiwał używania przyjaznych nazw identyfikatorów AID OEM. Wymagał podania surowej wartości liczbowej w polach 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 te funkcje:

  • Wiele lokalizacji źródłowych plików konfiguracji (umożliwia rozszerzalne konfiguracje kompilacji).
  • Sprawdzanie poprawności wartości identyfikatorów AID OEM podczas kompilacji.
  • Generowanie niestandardowego nagłówka identyfikatora AID OEM, którego można używać w plikach źródłowych w razie potrzeby.
  • Powiązanie przyjaznej nazwy z rzeczywistą wartością identyfikatora AID OEM. Obsługuje argumenty ciągów nienumerycznych dla użytkownika i grupy, np. "foo" zamiast "2901".

Dodatkowe ulepszenia obejmują usunięcie tablicy android_ids[] z system/core/libcutils/include/private/android_filesystem_config.h. Ta tablica znajduje się teraz w Bionic jako w pełni prywatna wygenerowana tablica z akcesorami getpwnam() i getgrnam(). (Ma to dodatkowy efekt w postaci stabilnych plików binarnych, ponieważ podstawowe identyfikatory AID są modyfikowane). Więcej informacji o narzędziach i pliku README znajdziesz w build/make/tools/fs_config.

Dodawanie identyfikatorów Androida (AID)

W Androidzie 8.0 usunięto tablicę android_ids[] z projektu Android Open Source Project (AOSP). Wszystkie przyjazne nazwy identyfikatorów AID są generowane z pliku nagłówkowego system/core/libcutils/include/private/android_filesystem_config.h podczas generowania tablicy android_ids[] w Bionic. Każdy define pasujący do AID_* jest wykrywany przez narzędzie a * staje się nazwą w małych literach.

Na przykład w private/android_filesystem_config.h:

#define AID_SYSTEM 1000

Staje się:

  • Przyjazna nazwa: system
  • uid: 1000
  • gid: 1000

Aby dodać nowy podstawowy identyfikator AID AOSP, po prostu dodaj #define do android_filesystem_config.h pliku nagłówkowego. Identyfikator AID jest generowany podczas kompilacji i udostępniany interfejsom, które używają argumentów użytkownika i grupy. Narzędzie sprawdza, czy nowy identyfikator AID nie znajduje się w zakresach aplikacji ani OEM . Uwzględnia też zmiany w tych zakresach i powinno automatycznie skonfigurować się ponownie w przypadku zmian lub nowych zakresów zarezerwowanych przez OEM.

Konfigurowanie identyfikatorów AID

Aby włączyć nowy mechanizm identyfikatorów AID, ustaw TARGET_FS_CONFIG_GEN w pliku BoardConfig.mk. Ta zmienna zawiera listę plików konfiguracji, dzięki czemu możesz dodawać pliki w razie potrzeby.

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

Konfigurowanie sekcji caps

Sekcja caps obsługuje ustawianie możliwości systemu plików w obiektach systemu plików w kompilacji (sam system plików musi też obsługiwać tę funkcję).

Ponieważ uruchamianie stabilnej usługi jako root w Androidzie powoduje niepowodzenie testu Compatibility Test Suite (CTS) , poprzednie wymagania dotyczące zachowania możliwości podczas uruchamiania procesu lub usługi obejmowały skonfigurowanie możliwości, a następnie użycie setuid/setgid do odpowiedniego identyfikatora AID. Dzięki możliwościom możesz pominąć te wymagania i pozwolić jądru na wykonanie tych czynności. Gdy sterowanie zostanie przekazane do main(), Twój proces będzie już miał potrzebne możliwości, dzięki czemu usługa będzie mogła używać użytkownika i grupy innych niż root (jest to preferowany sposób uruchamiania usług z uprawnieniami).

Sekcja caps używa tej składni:

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

Określenie w różnych plikach wielu sekcji z tą samą wartością [path] jest błędem. W Pythonie w wersji <= 3.2 ten sam plik może zawierać sekcje, które zastępują poprzednią sekcję. W Pythonie 3.2 jest ustawiony tryb ścisły.
mode Ósemkowy tryb pliku Prawidłowy ósemkowy tryb pliku składający się z co najmniej 3 cyfr. Jeśli określono 3, jest on poprzedzony cyfrą 0, w przeciwnym razie tryb jest używany w takiej postaci.
user AID_<user> Albo C define dla prawidłowego identyfikatora AID, albo przyjazna nazwa (np. akceptowane są zarówno AID_RADIO, jak i radio). Aby zdefiniować niestandardowy identyfikator AID, przeczytaj sekcję Konfigurowanie sekcji AID.
group AID_<group> Tak samo jak w przypadku użytkownika.
caps cap* Nazwa zadeklarowana w bionic/libc/kernel/uapi/linux/capability.h bez początkowego CAP_. Dozwolone są wielkie i małe litery. Możliwości mogą też być surowe:
  • binarne (0b0101)
  • ósemkowe (0455)
  • liczba całkowita (42)
  • szesnastkowe (0xFF)
Poszczególne możliwości oddzielaj spacjami.

Przykład użycia znajdziesz w artykule Korzystanie z możliwości systemu plików.

Konfigurowanie sekcji AID

Sekcja AID zawiera identyfikatory AID OEM i używa tej składni:

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

Określenie w różnych plikach wielu sekcji z tą samą wartością AID_<name> (bez uwzględniania wielkości liter i z tymi samymi ograniczeniami co [path]) jest błędem.

<name> musi zaczynać się od nazwy partycji, aby uniknąć konfliktu z różnymi źródłami.
value <number> Prawidłowy ciąg znaków liczbowych w stylu C (szesnastkowy, ósemkowy, binarny i dziesiętny).

Określenie w różnych plikach wielu sekcji z tą samą opcją value jest błędem.

Opcje value muszą być określone w zakresie odpowiadającym partycji używanej 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:
  • 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)

Przykłady użycia znajdziesz w artykułach Definiowanie identyfikatorów AID OEM i Korzystanie z identyfikatorów AID OEM.

Przykłady użycia

Poniższe przykłady pokazują, jak zdefiniować i używać identyfikatora AID OEM oraz jak włączyć możliwości systemu plików. Nazwy identyfikatorów AID OEM ([AID_name]) muszą zaczynać się od nazwy partycji, np. „vendor_”, aby nie powodować konfliktu z przyszłymi nazwami AOSP ani innymi partycjami.

Definiowanie nazw identyfikatorów AID OEM

Aby zdefiniować identyfikator AID OEM, utwórz plik config.fs i ustaw wartość identyfikatora AID. Na przykład w device/x/y/config.fs ustaw te wartości:

[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 te wartości:

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

Twój niestandardowy identyfikator AID może być teraz używany przez system w nowej kompilacji.

Korzystanie z identyfikatorów AID OEM

Aby użyć identyfikatora AID OEM, w kodzie C uwzględnij 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 te wartości:

#include "generated_oem_aid.h"


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

W powiązanym pliku Android.bp dodaj te wartości:

header_libs: ["oemaids_headers"],

Jeśli używasz pliku Android.mk, dodaj te wartości:

LOCAL_HEADER_LIBRARIES := oemaids_headers

Korzystanie z przyjaznych nazw

W Androidzie 9 możesz używać przyjaznej nazwy w przypadku każdego interfejsu, który obsługuje nazwy identyfikatorów AID. 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 z przyjaznej nazwy na uid jest wykonywane przez /vendor/etc/passwd i /vendor/etc/group, partycja dostawcy musi być zamontowana.

Powiązywanie przyjaznych nazw

Android 9 obsługuje powiązywanie przyjaznej nazwy z rzeczywistą wartością identyfikatora AID OEM. Możesz używać argumentów ciągów nienumerycznych dla użytkownika i grupy, czyli "vendor_foo" zamiast "2901".

Konwertowanie identyfikatorów AID na przyjazne nazwy

W przypadku identyfikatorów AID OEM Android 8.x wymagał używania oem_#### z getpwnam i podobnymi funkcjami, a także w miejscach, które obsługują wyszukiwanie za pomocą getpwnam (np. init skrypty). W Androidzie 9 możesz używać funkcji getpwnam i getgrnam w Bionic do konwertowania 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 tę 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 te wartości:

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

Gdy usługa vendor_foo jest wykonywana, zaczyna się od możliwości CAP_SYS_ADMIN i CAP_SYS_NICE bez wywołań setuid i setgid. Ponadto zasady SELinux usługi vendor_foo nie wymagają już możliwości setuid i setgid i można je usunąć.

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

W Androidzie 6.0 przeniesiono fs_config i powiązane definicje struktury (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żywanie oddzielnych reguł dopasowywania i analizowania dla katalogów i plików (które mogą używać dodatkowych wyrażeń glob) umożliwiło Androidowi obsługę katalogów i plików w 2 różnych tabelach. Definicje struktury w system/core/libcutils/fs_config.c umożliwiały nie tylko odczytywanie katalogów i plików w czasie działania, ale też host mógł używać tych samych plików podczas kompilacji do tworzenia obrazów systemu plików jako ${OUT}/system/etc/fs_config_dirs i ${OUT}/system/etc/fs_config_files.

Metoda zastępowania rozszerzania systemu plików została zastąpiona przez modułowy system konfiguracji wprowadzony w Androidzie 8.0, ale w razie potrzeby możesz nadal używać starej metody. W kolejnych sekcjach opisujemy, jak generować i uwzględniać pliki zastępowania oraz jak konfigurować system plików.

Generowanie plików zastępowania

Wyrównane pliki binarne /system/etc/fs_config_dirs i /system/etc/fs_config_files możesz wygenerować za pomocą narzędzia fs_config_generate w build/tools/fs_config. Narzędzie używa funkcji biblioteki libcutils (fs_config_generate()) do zarządzania wymaganiami DAC w buforze i definiuje reguły dla pliku dołączanego, aby zinstytucjonalizować reguły DAC.

Aby użyć, utwórz plik dołączany w device/vendor/device/android_filesystem_config.h , który będzie działać jako zastąpienie. Plik musi używać formatu structure fs_path_config zdefiniowanego w system/core/include/private/android_filesystem_config.h z tymi inicjalizacjami 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 (zobacz przykład poniżej). Możesz też określić plik zastępowania za pomocą TARGET_ANDROID_FILESYSTEM_CONFIG_H w konfiguracji płyty, z wymuszoną nazwą podstawową android_filesystem_config.h.

Uwzględnianie plików zastępowania

Aby uwzględnić pliki, upewnij się, że PRODUCT_PACKAGES zawiera fs_config_dirs lub fs_config_files, aby można było je zainstalować odpowiednio w /system/etc/fs_config_dirs i /system/etc/fs_config_files. System kompilacji szuka niestandardowego pliku android_filesystem_config.h w $(TARGET_DEVICE_DIR), gdzie znajduje się BoardConfig.mk. Jeśli ten plik znajduje się w innym miejscu, ustaw zmienną konfiguracji płyty TARGET_ANDROID_FILESYSTEM_CONFIG_H tak, aby wskazywała tę lokalizację.

Konfigurowanie systemu plików

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

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

Przykład zastąpienia

Ten przykład pokazuje poprawkę zastępującą demona system/bin/glgps , aby dodać obsługę blokady uśpienia w device/vendor/device katalogu. Pamiętaj o tych kwestiach:

  • Każdy wpis struktury to tryb, uid, gid, możliwości i nazwa. system/core/include/private/android_filesystem_config.h jest uwzględniany automatycznie, aby udostępnić manifest #defines (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND).
  • Sekcja android_device_files[] zawiera działanie, które blokuje dostęp do system/etc/fs_config_dirs gdy nie jest określony, co stanowi dodatkowe zabezpieczenie DAC w przypadku braku treści do zastąpienia katalogu. Jest to jednak słaba ochrona. Jeśli ktoś ma kontrolę nad /system, zwykle może zrobić wszystko.
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)

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

Podczas migracji systemów plików z Androida 5.x i starszych wersji pamiętaj, że Android 6.x

  • usuwa niektóre dołączane pliki, struktury i definicje wbudowane;
  • wymaga odwołania do libcutils zamiast bezpośredniego uruchamiania 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 w przypadku struktur plików lub katalogów albo od fs_config muszą dodać libcutils zależności biblioteki.
  • wymaga prywatnych kopii gałęzi producenta urządzenia system/core/include/private/android_filesystem_config.h z dodatkową treścią w istniejących celach, aby przenieść je do device/vendor/device/android_filesystem_config.h.
  • zastrzega sobie prawo do stosowania obowiązkowych kontroli dostępu SELinux (MAC) do plików konfiguracji w systemie docelowym. Implementacje, które obejmują niestandardowe pliki wykonywalne docelowe używające fs_config(), muszą zapewnić dostęp.