Dyskrecjonalna kontrola dostępu (DAC)

Obiekty systemu plików i usługi dodane do kompilacji często wymagają osobnych, 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żna zamiast nich używać identyfikatorów AID producenta OEM.

W wcześniejszych wersjach Androida (Android 7.x i starsze) mechanizm identyfikatorów AID był rozszerzony za pomocą pliku android_filesystem_config.hspecyficznego dla urządzenia, aby określić możliwości systemu plików lub niestandardowe identyfikatory AID OEM. System ten był jednak nieintuicyjny, ponieważ nie obsługiwał przyjaznych nazw identyfikatorów AID OEM. Wymagało to podania surowych wartości liczbowych w polach użytkownika i grupy bez możliwości powiązania przyjaznej nazwy z liczbowym identyfikatorem AID.

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

  • wiele źródeł plików konfiguracji (umożliwia rozszerzalne konfiguracje kompilacji);
  • Sprawdzanie wartości identyfikatorów AID OEM na etapie kompilacji.
  • Generowanie niestandardowego nagłówka OEM AID, którego można używać w plikach źródłowych w razie potrzeby.
  • Powiązanie nazwy przyjaznej z rzeczywistą wartością AID OEM. Obsługuje niearytmetyczne argumenty ciągu znaków dotyczące użytkownika i grupy, np. „foo” zamiast „2901”.

Dodatkowe ulepszenia obejmują usunięcie tablicy android_ids[] z elementu system/core/libcutils/include/private/android_filesystem_config.h. Ta tablica jest teraz dostępna w Bionic jako całkowicie prywatna generowana tablica z metodami dostępu getpwnam()getgrnam(). (efektem ubocznym jest tworzenie stabilnych plików binarnych, gdy zmieniają się podstawowe identyfikatory AID). Więcej informacji o narzędziach i pliku README znajdziesz w artykule build/make/tools/fs_config.

Dodawanie identyfikatorów Androida (AID)

W Androidzie 8.0 usunięto tablicę android_ids[] z Projektu Android Open Source (AOSP). Wszystkie nazwy zgodne z AID są zamiast tego generowane z pliku nagłówka system/core/libcutils/include/private/android_filesystem_config.h podczas generowania tablicy Bionic android_ids[]. Wszystkie define pasujące do AID_* są rozpoznawane przez narzędzia, a * staje się nazwą w małej literze.

Na przykład w private/android_filesystem_config.h:

#define AID_SYSTEM 1000

Zmiana:

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

Aby dodać nowy podstawowy identyfikator AOSP, po prostu dodaj plik #define do pliku nagłówka android_filesystem_config.h. AID jest generowany podczas kompilacji i staje się dostępny dla interfejsów, które używają argumentów użytkownika i grupy. Narzędzie sprawdza, czy nowy identyfikator AID nie mieści się w zakresie identyfikatorów APP ani OEM. Uwzględnia też zmiany w tych zakresach i powinna automatycznie przekonfigurować się po zmianach lub nowych zakresach zarezerwowanych przez OEM.

Konfigurowanie identyfikatorów AID

Aby włączyć nowy mechanizm identyfikatorów AID, ustaw wartość TARGET_FS_CONFIG_GEN w pliku BoardConfig.mk. Ta zmienna przechowuje listę plików konfiguracyjnych, co umożliwia dołączanie plików w razie potrzeby.

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

Konfigurowanie sekcji z wielkimi literami

Sekcja caps umożliwia konfigurowanie funkcji systemu plików w obiektach systemu plików w ramach kompilacji (system plików musi też obsługiwać tę funkcję).

Uruchomienie stabilnej usługi jako root na Androidzie powoduje niepowodzenie Compatibility Test Suite (CTS), więc poprzednie wymagania dotyczące zachowania możliwości podczas uruchamiania procesu lub usługi obejmowały konfigurowanie możliwości, a następnie używanie setuid/setgid do uruchamiania odpowiedniego identyfikatora AID. Dzięki temu możesz pominąć te wymagania i pozwolić jądro na wykonanie tej czynności za Ciebie. Gdy przekazanie kontroli do main(), proces ma już wymagane możliwości, aby usługa mogła używać użytkownika i grupy niebędącej użytkownikiem root (jest to preferowany sposób uruchamiania usług uprzywilejowanych).

Sekcja z wielkimi literami używa tej składni:

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

Podanie w różnych plikach kilku sekcji o tej samej nazwie [path] 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 on ustawiony na tryb ścisły.
mode Tryb pliku octal Prawidłowy octal file mode o długości co najmniej 3 cyfry. Jeśli podano wartość 3, przed nią dodawana jest litera 0, w przeciwnym razie tryb jest używany bez zmian.
user AID_<user> define dla prawidłowego identyfikatora AID lub nazwa przyjazna (np. AID_RADIOradio są akceptowane). Aby zdefiniować niestandardowy identyfikator AID, zapoznaj się z sekcją Konfigurowanie identyfikatora AID.
group AID_<group> Taki sam jak w przypadku użytkownika.
caps cap* Nazwa zadeklarowana w bionic/libc/kernel/uapi/linux/capability.h bez CAP_ na początku. Dozwolone są wielkie i małe litery. Znaki wielkie mogą też być:
  • binarne (0b0101)
  • ośmiu (0455).
  • int (42)
  • szesnastkowo (0xFF)
Oddziel poszczególne znaki za pomocą odstępów.

Przykład użycia znajdziesz w artykule Korzystanie z funkcji systemu plików.

Konfigurowanie sekcji AID

Sekcja AID zawiera identyfikatory AID OEM i korzysta z tej składni:

Sekcja Wartość Definicja
[AID_<name>] <name> może zawierać znaki z zadanego zestawu: wielkie litery, cyfry i podkreślenia. Wersja w wersji małej jest używana jako nazwa przyjazna. Wygenerowany plik nagłówka do włączania kodu używa dokładnie tego samego adresu:AID_<name>.

Podawanie wielu sekcji o tej samej nazwie AID_<name> (bez rozróżniania wielkości liter, z tymi samymi ograniczeniami co [path]) jest błędem.

Nazwa <name> musi zaczynać się od nazwy partycji, aby nie powodować konfliktów z innymi źródłami.
value <number> Prawidłowy ciąg znaków liczby w stylu języka C (szeszasta, ósemkowa, binarna i dziesiętna).

Podanie kilku 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 parasmterze <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 nazw identyfikatorów AID OEMUżywanie 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ć funkcje systemu plików. Nazwy identyfikatorów AID OEM ([AID_name]) muszą zaczynać się od nazwy partycji, np. „vendor_”, aby nie wchodziły w konflikt z przyszłościowymi nazwami AOSP ani innymi partycjami.

Definiowanie nazw identyfikatorów AID OEM

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

[AID_VENDOR_FOO]
value: 2900

Po utworzeniu pliku ustaw zmienną TARGET_FS_CONFIG_GEN i od niej odwołuj się w sekcji BoardConfig.mk. Na przykład w sekcji 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 teraz być używany przez system w ramach nowej wersji.

Korzystanie z identyfikatorów AID OEM

Aby używać identyfikatora AID OEM, w kodzie C uwzględnij w powiązanym pliku Makefile zmienną oemaids_headers i dodaj #include "generated_oem_aid.h", a następnie zacznij używać zadeklarowanych identyfikatorów. Na przykład w elemencie my_file.c dodaj te informacje:

#include "generated_oem_aid.h"


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

W powiązanym pliku Android.bp dodaj te informacje:

header_libs: ["oemaids_headers"],

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

LOCAL_HEADER_LIBRARIES := oemaids_headers

Używanie przyjaznych nazw

W Androidzie 9 możesz używać przyjaznej nazwy w dowolnym interfejsie, który obsługuje nazwy AID. Przykład:

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

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

Powiązywanie przyjaznych nazw

Android 9 obsługuje łączenie nazwy przyjaznej z rzeczywistą wartością AID OEM. W przypadku użytkownika i grupy możesz używać niearytmetycznych ciągów znaków, np. „vendor_foo” zamiast „2901”.

Konwertowanie identyfikatorów AID na nazwy przyjazne

W Androidzie 8.x w przypadku identyfikatorów OEM wymagane było używanie funkcji oem_#### z funkcją getpwnam i podobnymi, a także w miejscach, które obsługują wyszukiwanie za pomocą funkcji getpwnam (np. skrypty init). W Androidzie 9 możesz używać funkcji getpwnamgetgrnam w Bionic do konwertowania identyfikatorów Androida (AID) na przyjazne nazwy i odwrotnie.

Korzystanie z możliwości systemu plików

Aby włączyć funkcje 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 parametr TARGET_FS_CONFIG_GEN tak, aby wskazywał ten plik w pliku BoardConfig.mk. Na przykład w sekcji 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, uruchamia się z możliwościami CAP_SYS_ADMINCAP_SYS_NICE bez wywołań setuidsetgid. Ponadto zasady SELinux usługi vendor_foo nie wymagają już uprawnień setuid i setgid, więc można je usunąć.

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

W Androidzie 6.0 funkcja fs_config i powiązane z nią definicje struktury (system/core/include/private/android_filesystem_config.h) zostały przeniesione do pliku system/core/libcutils/fs_config.c, gdzie można je aktualizować lub zastępować za pomocą plików binarnych zainstalowanych w folderach /system/etc/fs_config_dirs/system/etc/fs_config_files. Korzystanie z osobnych reguł dopasowywania i analizowania katalogów i plików (które mogą używać dodatkowych wyrażeń ogólnych) 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 odczyt katalogów i plików w czasie wykonywania, ale także używanie tych samych plików podczas kompilacji do tworzenia obrazów systemu plików, tak jak w ${OUT}/system/etc/fs_config_dirs${OUT}/system/etc/fs_config_files.

Chociaż metoda zastępowania służąca do rozszerzania systemu plików została zastąpiona przez modułowy system konfiguracji wprowadzony w Androidzie 8.0, w razie potrzeby nadal możesz używać starszej metody. W następnych sekcjach znajdziesz szczegółowe informacje o generowaniu i dołączaniu plików, zastępowaniu plików i konfigurowaniu systemu plików.

Generowanie plików zastąpienia

Wyrównane pliki binarne /system/etc/fs_config_dirs/system/etc/fs_config_files możesz wygenerować za pomocą narzędzia fs_config_generatebuild/tools/fs_config. Narzędzie korzysta z funkcji biblioteki libcutils (fs_config_generate()), aby zarządzać wymaganiami DAC w buforze, oraz definiuje reguły dla pliku include, aby ustanowić reguły DAC.

Aby użyć tej funkcji, utwórz plik include w folderze device/vendor/device/android_filesystem_config.h, który będzie działać jako zastąpienie. Plik musi być w formacie structure fs_path_config zdefiniowanym w pliku system/core/include/private/android_filesystem_config.h z tymi wstępnymi wartościami struktury dla symboli katalogu i pliku:

  • W przypadku katalogów użyj elementu android_device_dirs[].
  • W przypadku plików użyj android_device_files[].

Jeśli nie używasz właściwości android_device_dirs[] i android_device_files[], możesz zdefiniować właściwości NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS i NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (patrz przykład poniżej). Możesz też określić plik zastąpienia za pomocą parametru TARGET_ANDROID_FILESYSTEM_CONFIG_H w konfiguracji karty, z wymuszonym nazwiskiem android_filesystem_config.h.

Uwzględnij pliki zastępcze

Aby uwzględnić pliki, sprawdź, czy PRODUCT_PACKAGES zawiera fs_config_dirs lub fs_config_files, aby można było zainstalować je odpowiednio w /system/etc/fs_config_dirs i /system/etc/fs_config_files. System kompilacji wyszukuje niestandardowe android_filesystem_config.h w $(TARGET_DEVICE_DIR), gdzie istnieje BoardConfig.mk. Jeśli ten plik istnieje gdzie indziej, 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 lub nowszym:

  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 planszy (np. $(TARGET_DEVICE_DIR)/device.mk).

Przykład zastąpienia

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

  • Każdy wpis struktury to tryb, identyfikator użytkownika, identyfikator grupy, możliwości i nazwa. system/core/include/private/android_filesystem_config.h jest dołączany automatycznie, aby zapewnić definicje w pliku manifestu (#defines) (AID_ROOT, AID_SHELL, CAP_BLOCK_SUSPEND).
  • Sekcja android_device_files[] zawiera działanie polegające na blokowaniu dostępu do system/etc/fs_config_dirs, gdy nie jest on określony, co stanowi dodatkową ochronę DAC w przypadku braku treści w pliku zastąpień katalogu. Jest to jednak słaba ochrona. Jeśli ktoś ma kontrolę nad /system, może zrobić wszystko, co zechce.
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 pamiętaj, że: Android 6.x

  • Usunięcie niektórych include, struktur i definicji w ciele.
  • Wymaga odwołania 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 w strukturze plików lub katalogów, lub fs_config, muszą dodać libcutils zależności biblioteki.
  • Wymaga kopii system/core/include/private/android_filesystem_config.h z dodatkowymi treściami dla istniejących celów, które należy przenieść do device/vendor/device/android_filesystem_config.h.
  • Zastrzega prawo do stosowania mechanizmów kontroli dostępu SELinux (MAC) do plików konfiguracyjnych w systemie docelowym. Wdrożenia, które obejmują niestandardowe pliki wykonywalne docelowe korzystające z fs_config(), muszą zapewnić dostęp.