التحكم في الوصول التقديري (DAC)

تحتاج كائنات وخدمات نظام الملفات المضافة إلى الإصدار في كثير من الأحيان إلى معرفات منفصلة وفريدة، تُعرف باسم معرفات Android (AIDs). في الوقت الحالي، تستخدم العديد من الموارد مثل الملفات والخدمات معرفات المساعدة الأساسية (المحددة بواسطة Android) دون داعٍ؛ في العديد من الحالات، يمكنك استخدام أدوات مساعدة OEM (المحددة بواسطة OEM) بدلاً من ذلك.

قامت الإصدارات السابقة من Android (Android 7.x والإصدارات الأقدم) بتوسيع آلية AIDs باستخدام ملف android_filesystem_config.h الخاص بالجهاز لتحديد إمكانات نظام الملفات و/أو معرفات OEM المخصصة. ومع ذلك، كان هذا النظام غير بديهي لأنه لم يدعم استخدام أسماء لطيفة لمعرفات OEM AID، مما يتطلب منك تحديد الأرقام الأولية لحقول المستخدم والمجموعة بدون طريقة لربط اسم مألوف مع المعرف الرقمي.

تدعم الإصدارات الأحدث من Android (Android 8.0 والإصدارات الأحدث) طريقة جديدة لتوسيع قدرات نظام الملفات. هذه الطريقة الجديدة تدعم ما يلي:

  • مواقع مصدر متعددة لملفات التكوين (تمكن تكوينات البناء القابلة للتوسيع).
  • التحقق من سلامة وقت البناء لقيم OEM AID.
  • إنشاء رأس OEM AID مخصص يمكن استخدامه في الملفات المصدر حسب الحاجة.
  • اقتران اسم مألوف بقيمة OEM AID الفعلية. يدعم وسيطات السلسلة غير الرقمية للمستخدم والمجموعة، أي "foo" بدلاً من "2901".

تتضمن التحسينات الإضافية إزالة مصفوفة android_ids[] من system/core/libcutils/include/private/android_filesystem_config.h . هذه المصفوفة موجودة الآن في Bionic كمصفوفة خاصة بالكامل، مع الوصول إليها عبر getpwnam() و getgrnam() . (وهذا له تأثير جانبي يتمثل في إنتاج ثنائيات مستقرة حيث يتم تعديل معرفات AID الأساسية.) للحصول على الأدوات وملف README بمزيد من التفاصيل، راجع build/make/tools/fs_config .

إضافة معرفات Android (AIDs)

قام Android 8.0 بإزالة مصفوفة android_ids[] من مشروع Android مفتوح المصدر (AOSP). يتم إنشاء جميع الأسماء المتوافقة مع AID بدلاً من ذلك من ملف الرأس system/core/libcutils/include/private/android_filesystem_config.h عند إنشاء مصفوفة Bionic android_ids[] . يتم التقاط أي define مطابق لـ AID_* بواسطة الأدوات ويصبح * اسمًا صغيرًا.

على سبيل المثال، في private/android_filesystem_config.h :

#define AID_SYSTEM 1000

يصبح:

  • الاسم المألوف: النظام
  • رقم الهوية: 1000
  • معرف الموقع: 1000

لإضافة AID أساسي جديد لـ AOSP، ما عليك سوى إضافة #define إلى ملف الرأس android_filesystem_config.h . سيتم إنشاء معرف AID عند الإنشاء وإتاحته للواجهات التي تستخدم وسيطات المستخدم والمجموعة. تتحقق الأدوات من أن معرف AID الجديد ليس ضمن نطاقات APP أو OEM؛ كما أنه يحترم التغييرات التي تطرأ على تلك النطاقات ويجب إعادة تكوينها تلقائيًا عند التغييرات أو النطاقات الجديدة المحفوظة لدى OEM.

تكوين وسائل المساعدة

لتمكين آلية AIDs الجديدة، قم بتعيين TARGET_FS_CONFIG_GEN في ملف BoardConfig.mk . يحتوي هذا المتغير على قائمة ملفات التكوين، مما يتيح لك إلحاق الملفات حسب الحاجة.

تقليديًا، تستخدم ملفات التكوين الاسم config.fs ، لكن عمليًا يمكنك استخدام أي اسم. توجد ملفات config.fs بتنسيق Python ConfigParser ini وتتضمن قسم الأحرف الاستهلالية (لتكوين إمكانات نظام الملفات) وقسم AIDs (لتكوين معرفات OEM AIDs).

تكوين قسم القبعات

يدعم قسم الأحرف الكبيرة إعداد إمكانيات نظام الملفات على كائنات نظام الملفات داخل البنية (يجب أن يدعم نظام الملفات نفسه هذه الوظيفة أيضًا).

نظرًا لأن تشغيل خدمة مستقرة كجذر في Android يؤدي إلى فشل مجموعة اختبار التوافق (CTS) ، فإن المتطلبات السابقة للاحتفاظ بالقدرة أثناء تشغيل عملية أو خدمة تتضمن إعداد الإمكانات ثم استخدام setuid / setgid لمعرف AID مناسب للتشغيل. باستخدام الأحرف الاستهلالية، يمكنك تخطي هذه المتطلبات وجعل النواة تقوم بذلك نيابةً عنك. عندما يتم تسليم التحكم إلى main() ، فإن عمليتك لديها بالفعل الإمكانات التي تحتاجها حتى تتمكن خدمتك من استخدام مستخدم ومجموعة غير جذر (هذه هي الطريقة المفضلة لبدء الخدمات المميزة).

يستخدم قسم caps بناء الجملة التالي:

قسم قيمة تعريف
[path] مسار نظام الملفات المراد تكوينه. المسار المنتهي بـ / يعتبر ديرًا، وإلا فهو ملف.

من الخطأ تحديد أقسام متعددة بنفس [path] في ملفات مختلفة. في إصدارات Python <= 3.2، قد يحتوي نفس الملف على أقسام تتجاوز القسم السابق؛ في Python 3.2، تم ضبطه على الوضع الصارم.
mode وضع الملف الثماني وضع ملف ثماني صالح يتكون من 3 أرقام على الأقل. إذا تم تحديد 3، فسيتم مسبوقًا بـ 0، ويتم استخدام الوضع الآخر كما هو.
user AID_<المستخدم> إما define C لمعرف AID صالح أو الاسم المألوف (على سبيل المثال، AID_RADIO radio مقبولان). لتحديد معرف مخصص، راجع قسم تكوين AID .
group AID_<المجموعة> نفس المستخدم.
caps قبعة* الاسم كما هو مُعلن في bionic/libc/kernel/uapi/linux/capability.h بدون الحرف CAP_ البادئ. حالة مختلطة مسموح بها. يمكن أن تكون القبعات أيضًا خامًا:
  • ثنائي (0b0101)
  • ثماني (0455)
  • كثافة العمليات (42)
  • سداسي عشري (0xFF)
قم بفصل الأحرف الاستهلالية المتعددة باستخدام المسافات البيضاء.

للحصول على مثال للاستخدام، راجع استخدام إمكانيات نظام الملفات .

تكوين قسم المساعدات

يحتوي قسم AID على معرفات OEM ويستخدم بناء الجملة التالي:

قسم قيمة تعريف
[AID_<name>] يمكن أن يحتوي <name> على أحرف كبيرة وأرقام وشرطات سفلية. يتم استخدام الإصدار الصغير كاسم مألوف. يستخدم ملف الرأس الذي تم إنشاؤه لتضمين التعليمات البرمجية AID_<name> بالضبط.

من الخطأ تحديد أقسام متعددة بنفس AID_<name> (غير حساس لحالة الأحرف مع نفس القيود مثل [path] ).

<name> يجب أن يبدأ باسم قسم لضمان عدم تعارضه مع مصادر مختلفة.
value <رقم> سلسلة أرقام صالحة بنمط C (ست عشرية وثمانية وثنائية وعشرية).

من الخطأ تحديد أقسام متعددة بنفس خيار القيمة.

يجب تحديد خيارات القيمة في النطاق المطابق للقسم المستخدم في <name> . يتم تعريف قائمة الأقسام الصالحة والنطاقات المقابلة لها في system/core/libcutils/include/private/android_filesystem_config.h . الخيارات هي:
  • قسم البائع
    • AID_OEM_RESERVED_START(2900) - AID_OEM_RESERVED_END(2999)
    • AID_OEM_RESERVED_2_START(5000) - AID_OEM_RESERVED_2_END(5999)
  • قسم النظام
    • AID_SYSTEM_RESERVED_START(6000) - AID_SYSTEM_RESERVED_END(6499)
  • قسم أوديإم
    • AID_ODM_RESERVED_START(6500) - AID_ODM_RESERVED_END(6999)
  • قسم المنتج
    • AID_PRODUCT_RESERVED_START(7000) - AID_PRODUCT_RESERVED_END(7499)
  • قسم System_ext
    • AID_SYSTEM_EXT_RESERVED_START(7500) - AID_SYSTEM_EXT_RESERVED_END(7999)

للحصول على أمثلة الاستخدام، راجع تعريف أسماء معرفات OEM واستخدام معرفات OEM .

أمثلة الاستخدام

توضح الأمثلة التالية كيفية تعريف واستخدام OEM AID وكيفية تمكين إمكانيات نظام الملفات. يجب أن تبدأ أسماء معرفات OEM ( [AID_ name ] ) باسم قسم مثل " sales_ " لضمان عدم تعارضها مع أسماء AOSP المستقبلية أو الأقسام الأخرى.

تحديد أسماء مساعدات OEM

لتعريف OEM AID، قم بإنشاء ملف config.fs وقم بتعيين قيمة AID. على سبيل المثال، في device/x/y/config.fs ، قم بتعيين ما يلي:

[AID_VENDOR_FOO]
value: 2900

بعد إنشاء الملف، قم بتعيين المتغير TARGET_FS_CONFIG_GEN وأشر إليه في BoardConfig.mk . على سبيل المثال، في device/x/y/BoardConfig.mk ، قم بتعيين ما يلي:

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

يمكن الآن أن يستهلك النظام ككل معرفك المخصص في البنية الجديدة.

استخدام مساعدات OEM

لاستخدام معرف OEM AID، في كود C الخاص بك، قم بتضمين oemaids_headers في ملف Makefile المرتبط الخاص بك، وأضف #include "generated_oem_aid.h" ، ثم ابدأ في استخدام المعرفات المعلنة. على سبيل المثال، في my_file.c ، أضف ما يلي:

#include "generated_oem_aid.h"
…

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

في ملف Android.bp المرتبط، أضف ما يلي:

header_libs: ["oemaids_headers"],

إذا كنت تستخدم ملف Android.mk ، فأضف ما يلي:

LOCAL_HEADER_LIBRARIES := oemaids_headers

استخدام الأسماء المألوفة

في Android 9، يمكنك استخدام الاسم المألوف لأي واجهة تدعم أسماء AID. على سبيل المثال:

  • في أمر chown في some/init.rc :
    chown vendor_foo /vendor/some/vendor_foo/file
    
  • في service في some/init.rc :
    service vendor_foo /vendor/bin/foo_service
        user vendor_foo
        group vendor_foo
    

نظرًا لأن التعيين الداخلي من الاسم المألوف إلى uid يتم تنفيذه بواسطة /vendor/etc/passwd و /vendor/etc/group ، فيجب تثبيت قسم البائع.

ربط الأسماء المألوفة

يتضمن Android 9 دعمًا لربط اسم مألوف بقيمة OEM AID الفعلية. يمكنك استخدام وسيطات سلسلة غير رقمية للمستخدم والمجموعة، على سبيل المثال " eller_ foo" بدلاً من "2901".

التحويل من AID إلى الأسماء المألوفة

بالنسبة لمعرفات OEM AIDs ، يتطلب Android 8.x استخدام oem_#### مع getpwnam والوظائف المشابهة، وكذلك في الأماكن التي تتعامل مع عمليات البحث عبر getpwnam (مثل البرامج النصية init ). في Android 9، يمكنك استخدام getpwnam و getgrnam friends في Bionic للتحويل من معرفات Android (AIDs) إلى أسماء مألوفة والعكس صحيح.

استخدام قدرات نظام الملفات

لتمكين إمكانيات نظام الملفات، قم بإنشاء قسم caps في ملف config.fs . على سبيل المثال، في device/x/y/config.fs ، أضف القسم التالي:

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

بعد إنشاء الملف، قم بتعيين TARGET_FS_CONFIG_GEN للإشارة إلى هذا الملف في BoardConfig.mk . على سبيل المثال، في device/x/y/BoardConfig.mk ، قم بتعيين ما يلي:

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

عند تنفيذ الخدمة vendor_ foo ، فإنها تبدأ بالإمكانات CAP_SYS_ADMIN و CAP_SYS_NICE بدون استدعاءات setuid و setgid . بالإضافة إلى ذلك، لم تعد سياسة SELinux الخاصة بخدمة vendor_ foo بحاجة إلى إمكانية setuid و setgid ويمكن حذفها.

تكوين التجاوزات (Android 6.x-7.x)

قام Android 6.0 بنقل fs_config وتعريفات البنية المرتبطة به ( system/core/include/private/android_filesystem_config.h ) إلى system/core/libcutils/fs_config.c حيث يمكن تحديثها أو تجاوزها بواسطة الملفات الثنائية المثبتة في /system/etc/fs_config_dirs و /system/etc/fs_config_files . باستخدام قواعد مطابقة وتحليل منفصلة للأدلة والملفات (والتي يمكن أن تستخدم تعبيرات الكرة الأرضية الإضافية) مكّن Android من التعامل مع الدلائل والملفات في جدولين مختلفين. تعريفات البنية في system/core/libcutils/fs_config.c لا تسمح فقط بقراءة الدلائل والملفات في وقت التشغيل، ولكن يمكن للمضيف استخدام نفس الملفات أثناء وقت الإنشاء لإنشاء صور نظام الملفات مثل ${OUT}/system/etc/fs_config_dirs و ${OUT}/system/etc/fs_config_files .

على الرغم من أن طريقة التجاوز لتوسيع نظام الملفات قد تم استبدالها بنظام التكوين المعياري المقدم في Android 8.0، فلا يزال بإمكانك استخدام الطريقة القديمة إذا رغبت في ذلك. توضح الأقسام التالية بالتفصيل كيفية إنشاء ملفات التجاوز وتضمينها وتكوين نظام الملفات.

توليد ملفات التجاوز

يمكنك إنشاء الملفات الثنائية المحاذية /system/etc/fs_config_dirs و /system/etc/fs_config_files باستخدام الأداة fs_config_generate في build/tools/fs_config . تستخدم الأداة وظيفة مكتبة libcutils ( fs_config_generate() ) لإدارة متطلبات DAC في مخزن مؤقت وتحديد قواعد ملف التضمين لإضفاء الطابع المؤسسي على قواعد DAC.

للاستخدام، قم بإنشاء ملف تضمين في device/ vendor / device /android_filesystem_config.h الذي يعمل بمثابة التجاوز. يجب أن يستخدم الملف تنسيق structure fs_path_config المحدد في system/core/include/private/android_filesystem_config.h مع تهيئة البنية التالية لرموز الدليل والملف:

  • بالنسبة للأدلة، استخدم android _device _dirs[] .
  • بالنسبة للملفات، استخدم android _device _files[] .

عند عدم استخدام android_device_dirs[] و android_device_files[] ، يمكنك تحديد NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS و NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES (انظر المثال أدناه). يمكنك أيضًا تحديد ملف التجاوز باستخدام TARGET_ANDROID_FILESYSTEM_CONFIG_H في تكوين اللوحة، مع الاسم الأساسي المفروض android_filesystem_config.h .

بما في ذلك ملفات التجاوز

لتضمين الملفات، تأكد من أن PRODUCT_PACKAGES يتضمن fs_config_dirs و/أو fs_config_files حتى يتمكن من تثبيتها على /system/etc/fs_config_dirs و /system/etc/fs_config_files ، على التوالي. يبحث نظام البناء عن android_filesystem_config.h المخصص في $(TARGET_DEVICE_DIR) حيث يوجد BoardConfig.mk . إذا كان هذا الملف موجودًا في مكان آخر، فقم بتعيين متغير تكوين اللوحة TARGET_ANDROID_FILESYSTEM_CONFIG_H للإشارة إلى هذا الموقع.

تكوين نظام الملفات

لتكوين نظام الملفات في Android 6.0 والإصدارات الأحدث:

  1. قم بإنشاء الملف $(TARGET_DEVICE_DIR)/android_filesystem_config.h .
  2. قم بإضافة fs_config_dirs و/أو fs_config_files إلى PRODUCT_PACKAGES في ملف تكوين اللوحة (على سبيل المثال، $(TARGET_DEVICE_DIR)/device.mk ).

تجاوز المثال

يعرض هذا المثال تصحيحًا لتجاوز البرنامج الخفي system/bin/glgps لإضافة دعم قفل التنشيط في دليل device/ vendor / device . ضع في اعتبارك ما يلي:

  • كل إدخال للبنية هو الوضع، وuid، وgid، والقدرات، والاسم. يتم تضمين system/core/include/private/android_filesystem_config.h تلقائيًا لتوفير البيان #defines ( AID_ROOT , AID_SHELL , CAP_BLOCK_SUSPEND ).
  • يتضمن قسم android_device_files[] إجراءً لمنع الوصول إلى system/etc/fs_config_dirs عندما يكون غير محدد، والذي يعمل كحماية إضافية لـ DAC في حالة نقص المحتوى لتجاوزات الدليل. إلا أن هذه حماية ضعيفة؛ إذا كان شخص ما لديه السيطرة على /system ، فيمكنه عادةً فعل أي شيء يريده.
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)

ترحيل أنظمة الملفات من الإصدارات السابقة

عند ترحيل أنظمة الملفات من Android 5.x والإصدارات الأقدم، ضع في اعتبارك أن Android 6.x

  • يزيل بعض التضمينات والهياكل والتعريفات المضمنة.
  • يتطلب مرجعًا إلى libcutils بدلاً من التشغيل مباشرة من system/core/include/private/android_filesystem_config.h . يجب أن تضيف الملفات التنفيذية الخاصة بالشركة المصنعة للجهاز والتي تعتمد على system/code/include/private_filesystem_config.h للملف أو بنيات الدليل أو fs_config تبعيات مكتبة libcutils .
  • يتطلب نسخ فرع خاص للشركة المصنعة للجهاز من system/core/include/private/android_filesystem_config.h مع محتوى إضافي على الأهداف الحالية للانتقال إلى device/ vendor / device /android_filesystem_config.h .
  • يحتفظ بالحق في تطبيق عناصر التحكم في الوصول الإلزامية (MAC) لـ SELinux على ملفات التكوين الموجودة على النظام الهدف، ويجب أن تضمن التطبيقات التي تتضمن الملفات التنفيذية المستهدفة المخصصة باستخدام fs_config() الوصول.