کنترل دسترسی اختیاری (DAC)

اشیاء سیستم فایل و سرویس‌های اضافه شده به سیستم عامل، اغلب به شناسه‌های جداگانه و منحصر به فردی نیاز دارند که به عنوان شناسه‌های اندروید (AID) شناخته می‌شوند. در حال حاضر، بسیاری از منابع مانند فایل‌ها و سرویس‌ها از AIDهای اصلی (تعریف شده توسط اندروید) به طور غیرضروری استفاده می‌کنند؛ در بسیاری از موارد، می‌توانید به جای آنها از AIDهای OEM (تعریف شده توسط OEM) استفاده کنید.

نسخه‌های اولیه اندروید (اندروید ۷.x و پایین‌تر) مکانیزم AIDها را با استفاده از یک فایل android_filesystem_config.h مخصوص دستگاه، برای مشخص کردن قابلیت‌های سیستم فایل و/یا OEM AIDهای سفارشی، گسترش دادند. با این حال، این سیستم به دلیل پشتیبانی نکردن از نام‌های زیبا برای OEM AIDها، ساده نبود و شما را ملزم می‌کرد که برای فیلدهای کاربر و گروه، عدد خام را بدون هیچ راهی برای مرتبط کردن یک نام آشنا با AID عددی، مشخص کنید.

نسخه‌های جدیدتر اندروید (اندروید ۸.۰ و بالاتر) از روش جدیدی برای گسترش قابلیت‌های سیستم فایل پشتیبانی می‌کنند. این روش جدید از موارد زیر پشتیبانی می‌کند:

  • چندین مکان منبع برای فایل‌های پیکربندی (امکان پیکربندی‌های ساخت قابل توسعه را فراهم می‌کند).
  • بررسی صحت مقادیر 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 مراجعه کنید.

افزودن شناسه‌های اندروید (AID)

اندروید ۸.۰ آرایه android_ids[] را از پروژه متن‌باز اندروید (AOSP) حذف کرد. در عوض، تمام نام‌های سازگار با AID هنگام تولید آرایه Bionic android_ids[] از فایل هدر system/core/libcutils/include/private/android_filesystem_config.h تولید می‌شوند. هر define با AID_* مطابقت داشته باشد، توسط ابزار انتخاب شده و * به نام کوچک تبدیل می‌شود.

برای مثال، در private/android_filesystem_config.h :

#define AID_SYSTEM 1000

می‌شود:

  • نام دوستانه: سیستم
  • شناسه کاربری: ۱۰۰۰
  • شناسه شبکه: ۱۰۰۰

برای افزودن یک AID هسته AOSP جدید، کافیست #define را به فایل هدر android_filesystem_config.h اضافه کنید. AID در زمان ساخت تولید می‌شود و در دسترس رابط‌هایی قرار می‌گیرد که از آرگومان‌های کاربر و گروه استفاده می‌کنند. این ابزار تأیید می‌کند که AID جدید در محدوده APP یا OEM نیست؛ همچنین تغییرات در این محدوده‌ها را در نظر می‌گیرد و باید به طور خودکار در مورد تغییرات یا محدوده‌های جدید رزرو شده توسط OEM پیکربندی مجدد شود.

پیکربندی AIDها

برای فعال کردن مکانیزم جدید AIDs، TARGET_FS_CONFIG_GEN را در فایل BoardConfig.mk تنظیم کنید. این متغیر لیستی از فایل‌های پیکربندی را در خود جای داده است و به شما امکان می‌دهد در صورت نیاز، فایل‌ها را اضافه کنید.

طبق قرارداد، فایل‌های پیکربندی از نام config.fs استفاده می‌کنند، اما در عمل می‌توانید از هر نامی استفاده کنید. فایل‌های config.fs در قالب ini پایتون ConfigParser هستند و شامل یک بخش با حروف بزرگ (برای پیکربندی قابلیت‌های سیستم فایل) و یک بخش AIDs (برای پیکربندی AIDهای OEM) می‌باشند.

بخش caps را پیکربندی کنید

بخش caps از تنظیم قابلیت‌های سیستم فایل روی اشیاء سیستم فایل در داخل ساخت پشتیبانی می‌کند (خود سیستم فایل نیز باید از این قابلیت پشتیبانی کند).

از آنجا که اجرای یک سرویس پایدار به عنوان root در اندروید باعث خرابی مجموعه تست سازگاری (CTS) می‌شود، الزامات قبلی برای حفظ یک قابلیت در حین اجرای یک فرآیند یا سرویس شامل تنظیم قابلیت‌ها و سپس استفاده از setuid / setgid به یک AID مناسب برای اجرا بود. با caps، می‌توانید از این الزامات صرف نظر کنید و هسته این کار را برای شما انجام دهد. وقتی کنترل به main() داده می‌شود، فرآیند شما از قبل قابلیت‌های مورد نیاز خود را دارد، بنابراین سرویس شما می‌تواند از یک کاربر و گروه غیر root استفاده کند (این روش ترجیحی برای شروع سرویس‌های ممتاز است).

بخش caps از سینتکس زیر استفاده می‌کند:

بخش ارزش تعریف
[path] مسیر سیستم فایل برای پیکربندی. مسیری که به / ختم می‌شود، یک دایرکتوری (dir) در نظر گرفته می‌شود، در غیر این صورت یک فایل است.

مشخص کردن چندین بخش با [path] یکسان در فایل‌های مختلف، خطا محسوب می‌شود. در نسخه‌های پایتون <= 3.2، یک فایل ممکن است شامل بخش‌هایی باشد که بخش قبلی را نادیده می‌گیرند؛ در پایتون 3.2، روی حالت strict تنظیم شده است.
mode حالت فایل هشت‌تایی یک حالت فایل هشت‌تایی معتبر با حداقل ۳ رقم. اگر عدد ۳ مشخص شود، پیشوند آن ۰ قرار می‌گیرد، در غیر این صورت حالت به همین صورت استفاده می‌شود.
user AID_<کاربر> یا define C برای یک AID معتبر استفاده کنید یا از نام دوستانه (مثلاً AID_RADIO و radio هر دو قابل قبول هستند). برای تعریف یک AID سفارشی، به بخش پیکربندی AID مراجعه کنید.
group AID_<گروه> همانند کاربر.
caps کلاه* نامی که در bionic/libc/kernel/uapi/linux/capability.h بدون CAP_ در ابتدای آن اعلام شده است. حروف بزرگ و کوچک نیز مجاز هستند. همچنین می‌توانند به صورت خام باشند:
  • دودویی (0b0101)
  • هشت تایی (0455)
  • عدد صحیح (42)
  • هگز (0xFF)
چندین حرف بزرگ را با استفاده از فاصله از هم جدا کنید.

برای مثالی از نحوه‌ی استفاده، به استفاده از قابلیت‌های سیستم فایل مراجعه کنید.

بخش AID را پیکربندی کنید

بخش AID شامل 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)
  • پارتیشن ODM
    • 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 AID و استفاده از OEM AIDها مراجعه کنید.

مثال‌های کاربرد

مثال‌های زیر نحوه تعریف و استفاده از یک شناسه نصب‌شده (OEM AID) و نحوه فعال‌سازی قابلیت‌های سیستم فایل را شرح می‌دهند. نام‌های شناسه نصب‌شده ( [ AID_name ] ) باید با نام یک پارتیشن مانند " vendor_ " شروع شوند تا اطمینان حاصل شود که با نام‌های AOSP آینده یا سایر پارتیشن‌ها تداخل ندارند.

تعریف نام‌های OEM AID

برای تعریف شناسه سازنده (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

اکنون AID سفارشی شما می‌تواند توسط سیستم در یک بیلد جدید به طور کلی مصرف شود.

از شناسه‌های کمکی 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

از نام‌های دوستانه استفاده کنید

در اندروید ۹، می‌توانید از نام دوستانه برای هر رابطی که از نام‌های 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 انجام می‌شود، پارتیشن vendor باید mount شود.

نام‌های دوستانه را به هم ربط دهید

اندروید ۹ از مرتبط کردن یک نام آشنا با مقدار واقعی OEM AID پشتیبانی می‌کند. می‌توانید از آرگومان‌های رشته‌ای غیرعددی برای کاربر و گروه استفاده کنید، یعنی به جای "۲۹۰۱"، از " vendor_foo " استفاده کنید.

تبدیل از AID به نام‌های دوستانه

برای OEM AIDها ، اندروید ۸.x استفاده از oem_#### را به همراه getpwnam و توابع مشابه، و همچنین در مکان‌هایی که جستجوها را با getpwnam مدیریت می‌کنند (مانند اسکریپت‌های init ) الزامی می‌کرد. در اندروید ۹، می‌توانید از getpwnam و getgrnam در Bionic برای تبدیل از Android IDها (AIDها) به نام‌های آشنا و برعکس استفاده کنید.

استفاده از قابلیت‌های سیستم فایل

برای فعال کردن قابلیت‌های سیستم فایل، یک بخش با حروف بزرگ (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 ندارد و می‌توان آن را حذف کرد.

پیکربندی لغوها (اندروید ۶.x تا ۷.x)

اندروید ۶.۰ 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 به‌روزرسانی یا لغو شوند. استفاده از قوانین تطبیق و تجزیه جداگانه برای دایرکتوری‌ها و فایل‌ها (که می‌توانستند از عبارات glob اضافی استفاده کنند) اندروید را قادر ساخت تا دایرکتوری‌ها و فایل‌ها را در دو جدول مختلف مدیریت کند. تعاریف ساختار در system/core/libcutils/fs_config.c نه تنها امکان خواندن دایرکتوری‌ها و فایل‌ها را در زمان اجرا فراهم می‌کرد، بلکه میزبان می‌توانست در طول زمان ساخت از همان فایل‌ها برای ساخت تصاویر سیستم فایل به عنوان ${OUT}/system/etc/fs_config_dirs و ${OUT}/system/etc/fs_config_files .

اگرچه روش لغو گسترش سیستم فایل توسط سیستم پیکربندی ماژولار معرفی شده در اندروید ۸.۰ جایگزین شده است، اما در صورت تمایل می‌توانید همچنان از روش قدیمی استفاده کنید. بخش‌های بعدی نحوه تولید و افزودن فایل‌های لغو و پیکربندی سیستم فایل را شرح می‌دهند.

ایجاد فایل‌های جایگزین

شما می‌توانید فایل‌های باینری هم‌تراز شده /system/etc/fs_config_dirs ‎ و /system/etc/fs_config_files ‎ را با استفاده از ابزار fs_config_generate در build/tools/fs_config تولید کنید. این ابزار از یک تابع کتابخانه‌ای libcutils ( fs_config_generate() ) برای مدیریت الزامات DAC در یک بافر استفاده می‌کند و قوانینی را برای یک فایل include تعریف می‌کند تا قوانین DAC را نهادینه کند.

برای استفاده، یک فایل include در device/ vendor / device /android_filesystem_config.h ایجاد کنید که به عنوان override عمل کند. این فایل باید از فرمت 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 را تعریف کنید (به مثال زیر مراجعه کنید). همچنین می‌توانید فایل override را با استفاده از 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 وجود دارد. اگر این فایل در جای دیگری وجود دارد، متغیر پیکربندی board را TARGET_ANDROID_FILESYSTEM_CONFIG_H تنظیم کنید تا به آن مکان اشاره کند.

پیکربندی سیستم فایل

برای پیکربندی سیستم فایل در اندروید ۶.۰ و بالاتر:

  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 نشان می‌دهد. موارد زیر را در نظر داشته باشید:

  • هر ورودی ساختار شامل mode، uid، gid، capabilities و name است. system/core/include/private/android_filesystem_config.h به طور خودکار برای ارائه manifest #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 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)

انتقال فایل‌های سیستمی از نسخه‌های قبلی

هنگام مهاجرت سیستم فایل از اندروید ۵.x و قبل از آن، به خاطر داشته باشید که اندروید ۶.x

  • برخی از includeها، ساختارها و تعاریف درون‌خطی را حذف می‌کند.
  • به جای اجرای مستقیم از system/core/include/private/android_filesystem_config.h ، نیاز به ارجاع به libcutils دارد. فایل‌های اجرایی خصوصی سازنده دستگاه که برای ساختار فایل یا دایرکتوری یا fs_config به system/code/include/private_filesystem_config.h وابسته هستند، باید وابستگی‌های کتابخانه libcutils اضافه کنند.
  • برای انتقال به device/vendor/device/android_filesystem_config.h، لازم است کپی‌های شاخه خصوصی سازنده دستگاه از system/core/include/private/android_filesystem_config.h به همراه محتوای اضافی روی دستگاه‌های هدف موجود، به device/ vendor / device /android_filesystem_config.h منتقل شوند.
  • حق اعمال کنترل‌های دسترسی اجباری SELinux (MAC) را برای فایل‌های پیکربندی در سیستم هدف محفوظ می‌دارد، پیاده‌سازی‌هایی که شامل فایل‌های اجرایی سفارشی هدف با استفاده از fs_config() هستند باید دسترسی را تضمین کنند.