این مقاله توضیح میدهد که Android چگونه مشکلات سازگاری خطمشی را با OTAهای پلتفرم مدیریت میکند، جایی که تنظیمات SELinux پلتفرم جدید ممکن است با تنظیمات SELinux فروشنده قدیمی متفاوت باشد.
طراحی خط مشی SELinux مبتنی بر سه گانه، تمایز دودویی بین خط مشی پلت فرم و فروشنده را در نظر می گیرد. اگر پارتیشنهای فروشنده وابستگیهایی مانند platform
< vendor
< oem
ایجاد کنند، این طرح پیچیدهتر میشود.
در اندروید 8.0 و بالاتر، سیاست جهانی SELinux به دو بخش خصوصی و عمومی تقسیم می شود. مؤلفههای عمومی شامل خطمشی و زیرساختهای مرتبط هستند که تضمین میشوند برای نسخه پلتفرم در دسترس هستند. این خطمشی در معرض نویسندگان خطمشی فروشنده قرار میگیرد تا فروشندگان بتوانند یک فایل خطمشی فروشنده بسازند، که وقتی با خطمشی ارائهشده توسط پلتفرم ترکیب شود، منجر به یک خطمشی کاملاً کاربردی برای دستگاه میشود.
- برای نسخهسازی، خطمشی عمومی پلتفرم صادر شده بهعنوان ویژگی نوشته میشود.
- برای سهولت در نوشتن خط مشی، انواع صادر شده به عنوان بخشی از فرآیند ساخت خط مشی به ویژگی های نسخه شده تبدیل می شوند. انواع عمومی همچنین ممکن است مستقیماً در تصمیمات برچسبگذاری ارائه شده توسط فایلهای زمینه فروشنده استفاده شوند.
Android یک نقشه بین انواع بتن صادر شده در خط مشی پلت فرم و ویژگی های نسخه شده مربوطه برای هر نسخه پلت فرم را حفظ می کند. این تضمین می کند که وقتی اشیا با یک نوع برچسب گذاری می شوند، رفتار تضمین شده توسط خط مشی عمومی پلتفرم در نسخه قبلی را نقض نمی کند. این نگاشت با به روز نگه داشتن یک فایل نقشه برداری برای هر نسخه پلتفرم ، که اطلاعات عضویت ویژگی را برای هر نوع صادر شده در خط مشی عمومی حفظ می کند، حفظ می شود.
مالکیت اشیا و برچسب گذاری
هنگام سفارشیسازی خطمشی در Android نسخه 8.0 و بالاتر، مالکیت باید به وضوح برای هر شیء تعریف شود تا خطمشی پلت فرم و فروشنده جدا بماند. به عنوان مثال، اگر فروشنده /dev/foo
و پلتفرم سپس /dev/foo
را در OTA بعدی برچسب گذاری کند، رفتار نامشخصی وجود خواهد داشت. برای SELinux، این به عنوان یک برخورد برچسب نشان می دهد. گره دستگاه می تواند تنها یک برچسب داشته باشد که به هر برچسبی که آخرین بار اعمال می شود، حل می شود. در نتیجه:
- فرآیندهایی که نیاز به دسترسی به برچسب ناموفق اعمال شده دارند، دسترسی به منبع را از دست خواهند داد.
- فرآیندهایی که به فایل دسترسی پیدا می کنند ممکن است به دلیل ایجاد گره دستگاه اشتباه شکسته شوند.
ویژگیهای سیستم همچنین دارای پتانسیل نامگذاری برخوردهایی هستند که میتوانند منجر به رفتار نامشخص در سیستم شوند (و همچنین برای برچسبگذاری SELinux). برخورد بین برچسبهای پلتفرم و فروشنده میتواند برای هر شی که دارای برچسب SELinux باشد، از جمله ویژگیها، سرویسها، فرآیندها، فایلها و سوکتها رخ دهد. برای جلوگیری از این مسائل، مالکیت این اشیاء را به وضوح تعریف کنید.
علاوه بر برخورد برچسبها، نامهای نوع/ویژگی SELinux نیز ممکن است با هم برخورد کنند. برخورد نام نوع/ویژگی همیشه منجر به خطای کامپایلر خط مشی می شود.
فاصله نام تایپ/ویژگی
SELinux چندین اعلان از یک نوع/ویژگی را مجاز نمیداند. خطمشی با اعلانهای تکراری در تدوین ناموفق خواهد بود. برای جلوگیری از تداخل نام نوع و ویژگی، همه اعلانهای فروشنده باید با vendor_
شروع شوند.
type foo, domain; → type vendor_foo, domain;
مالکیت دارایی سیستم و برچسب گذاری فرآیند
اجتناب از برخورد برچسبها با استفاده از فضاهای نام ویژگی بهتر حل میشود. برای شناسایی آسان ویژگیهای پلتفرم و جلوگیری از تداخل نام هنگام تغییر نام یا افزودن ویژگیهای پلتفرم صادر شده، مطمئن شوید که همه ویژگیهای فروشنده پیشوندهای خاص خود را دارند:
نوع ملک | پیشوندهای قابل قبول |
---|---|
خواص کنترلی | ctl.vendor. ctl.start$vendor. ctl.stop$vendor. init.svc.vendor. |
قابل خواندن | vendor. |
فقط خواندنی | ro.vendor. ro.boot. ro.hardware. |
مداوم | persist.vendor. |
فروشندگان می توانند به استفاده از ro.boot.*
(که از cmdline هسته می آید) و ro.hardware.*
(یک ویژگی واضح مرتبط با سخت افزار) ادامه دهند.
تمام سرویس های فروشنده در فایل های init rc باید دارای vendor.
برای سرویس های موجود در فایل های init rc پارتیشن های غیر سیستمی. قوانین مشابهی برای برچسب های SELinux برای ویژگی های فروشنده ( vendor_
برای ویژگی های فروشنده) اعمال می شود.
مالکیت فایل
جلوگیری از برخورد برای فایلها چالش برانگیز است زیرا پلتفرم و سیاست فروشنده هر دو معمولاً برچسبهایی را برای همه سیستمهای فایل ارائه میکنند. بر خلاف نامگذاری نوع، فاصله نام فایل ها عملی نیست زیرا بسیاری از آنها توسط هسته ایجاد می شوند. برای جلوگیری از این برخوردها، راهنمای نامگذاری فایل سیستم ها را در این بخش دنبال کنید. برای اندروید 8.0، اینها توصیه هایی بدون اعمال فنی هستند. در آینده، این توصیهها توسط مجموعه تست فروشنده (VTS) اعمال خواهند شد.
سیستم (/سیستم)
فقط تصویر سیستم باید از طریق file_contexts
، service_contexts
و غیره برچسبهایی را برای اجزای /system
از طریق file_contexts، سرویس_contexts و غیره ارائه کند. اگر برچسبهایی برای اجزای /system
در سیاست /vendor
اضافه شود، ممکن است بهروزرسانی OTA فقط چارچوبی امکانپذیر نباشد.
فروشنده (/فروشنده)
خطمشی AOSP SELinux قبلاً قسمتهایی از پارتیشن vendor
را که پلتفرم با آن تعامل دارد برچسبگذاری میکند، که نوشتن قوانین SELinux را برای فرآیندهای پلتفرم قادر میسازد تا بتوانند صحبت کنند و/یا به بخشهایی از پارتیشن vendor
دسترسی داشته باشند. مثال ها:
/vendor | برچسب ارائه شده توسط پلتفرم | فرآیندهای پلت فرم بسته به برچسب |
---|---|---|
/vendor(/. * )? | vendor_file | همه کلاینت های HAL در فریم ورک، ueventd و غیره. |
/vendor/framework(/. * )? | vendor_framework_file | dex2oat ، appdomain و غیره |
/vendor/app(/. * )? | vendor_app_file | dex2oat ، installd ، idmap و غیره. |
/vendor/overlay(/. * ) | vendor_overlay_file | system_server ، zygote ، idmap و غیره |
در نتیجه، هنگام برچسب زدن فایلهای اضافی در پارتیشن vendor
، قوانین خاصی باید دنبال شوند (از طریق neverallows
اجرا میشوند):
-
vendor_file
باید برچسب پیشفرض برای همه فایلهای پارتیشنvendor
باشد. خط مشی پلتفرم به این نیاز دارد تا به پیاده سازی های HAL از طریق عبور دسترسی داشته باشد. - همه
exec_types
جدید اضافه شده در پارتیشنvendor
از طریق فروشنده SEPolicy باید ویژگیvendor_file_type
داشته باشند. این از طریق neverallows اجرا می شود. - برای جلوگیری از تداخل با بهروزرسانیهای پلتفرم/چارچوب آینده، از برچسبگذاری فایلهای غیر از
exec_types
در پارتیشنvendor
خودداری کنید. - همه وابستگیهای کتابخانه برای HALهای فرآیندی شناساییشده توسط AOSP باید بهعنوان
same_process_hal_file.
Procfs (/proc)
فایلهای موجود در /proc
را میتوان تنها با استفاده از برچسب genfscon
برچسبگذاری کرد. در Android 7.0، هم پلتفرم و هم خطمشی فروشنده از genfscon
برای برچسبگذاری فایلها در procfs
استفاده میکردند.
توصیه: فقط برچسبهای خط مشی پلتفرم /proc
. اگر فرآیندهای vendor
نیاز به دسترسی به فایلهایی در /proc
دارند که در حال حاضر با برچسب پیشفرض ( proc
) برچسبگذاری شدهاند، خطمشی فروشنده نباید بهصراحت آنها را برچسبگذاری کند و در عوض باید از نوع proc
عمومی برای افزودن قوانین برای دامنههای فروشنده استفاده کند. این به بهروزرسانیهای پلتفرم اجازه میدهد تا رابطهای هسته آینده را که از طریق procfs
در معرض دید قرار میگیرند، تطبیق دهد و آنها را به صراحت در صورت نیاز برچسبگذاری کند.
اشکال زدایی (/sys/kernel/debug)
Debugfs
می توان هم در file_contexts
و هم genfscon
برچسب گذاری کرد. در اندروید 7.0 تا اندروید 10، هم پلتفرم و هم برچسب فروشنده debugfs
.
در اندروید 11، debugfs
قابل دسترسی نیست یا روی دستگاه های تولیدی نصب می شود. سازندگان دستگاه باید debugfs
حذف کنند.
Tracefs (/sys/kernel/debug/tracing)
Tracefs
می توان هم در file_contexts
و هم genfscon
برچسب گذاری کرد. در Android 7.0، فقط پلتفرم tracefs
برچسب گذاری می کند.
توصیه: فقط پلتفرم میتواند tracefs
برچسبگذاری کند.
Sysfs (/sys)
فایلهای موجود در /sys
ممکن است با استفاده از file_contexts
و genfscon
برچسبگذاری شوند. در Android 7.0، هم پلتفرم و هم فروشنده از genfscon
برای برچسب زدن فایلها در sysfs
استفاده میکنند.
توصیه: پلتفرم ممکن است گرههای sysfs
را که مختص دستگاه نیستند برچسبگذاری کند. در غیر این صورت، فقط فروشنده می تواند فایل ها را برچسب گذاری کند.
tmpfs (/dev)
فایلهای موجود در /dev
ممکن است در file_contexts
برچسبگذاری شوند. در Android 7.0، فایلهای برچسب پلتفرم و فروشنده در اینجا هستند.
توصیه: فروشنده ممکن است فقط فایلها را در /dev/vendor
برچسب بزند (به عنوان مثال، /dev/vendor/foo
، /dev/vendor/socket/bar
).
Rootfs (/)
فایل های موجود در /
ممکن است در file_contexts
برچسب گذاری شوند. در Android 7.0، فایلهای برچسب پلتفرم و فروشنده در اینجا هستند.
توصیه: فقط سیستم میتواند فایلها را در /
برچسبگذاری کند.
داده (/داده)
داده ها از طریق ترکیبی از file_contexts
و seapp_contexts
برچسب گذاری می شوند.
توصیه: برچسبگذاری فروشنده خارج از /data/vendor
را ممنوع کنید. فقط پلتفرم میتواند سایر بخشهای /data
را برچسبگذاری کند.
نسخه برچسب های Genfs
با شروع API فروشنده 202504، برچسبهای SELinux جدیدتر که با genfscon
در system/sepolicy/compat/plat_sepolicy_genfs_{ver}.cil
اختصاص داده شدهاند، برای پارتیشنهای فروشنده قدیمیتر اختیاری هستند. این به پارتیشن های فروشنده قدیمی اجازه می دهد تا اجرای SEPolicy موجود خود را حفظ کنند. این توسط متغیر Makefile BOARD_GENFS_LABELS_VERSION
کنترل می شود که در /vendor/etc/selinux/genfs_labels_version.txt
ذخیره می شود.
مثال:
- در فروشنده API سطح 202404، گره
/sys/class/udc
به طور پیشفرض برچسبsysfs
دارد. - با شروع API فروشنده 202504،
/sys/class/udc
دارای برچسبsysfs_udc
است.
با این حال، /sys/class/udc
ممکن است توسط پارتیشنهای فروشنده با استفاده از سطح API 202404، چه با برچسب sysfs
پیشفرض یا یک برچسب خاص فروشنده، استفاده شود. برچسب زدن بدون قید و شرط /sys/class/udc
به عنوان sysfs_udc
می تواند سازگاری با این پارتیشن های فروشنده را از بین ببرد. با علامت زدن BOARD_GENFS_LABELS_VERSION
، پلتفرم همچنان از برچسبها و مجوزهای قبلی برای پارتیشنهای فروشنده قدیمی استفاده میکند.
BOARD_GENFS_LABELS_VERSION
می تواند بزرگتر یا مساوی سطح API فروشنده باشد. به عنوان مثال، پارتیشنهای فروشنده با استفاده از سطح API 202404 میتوانند BOARD_GENFS_LABELS_VERSION
روی 202504 تنظیم کنند تا برچسبهای جدیدی را که در سال 202504 معرفی شدهاند، بپذیرند. فهرست برچسبهای genfs خاص 202504 را ببینید.
هنگام برچسبگذاری گرههای genfscon
، پلتفرم باید پارتیشنهای فروشنده قدیمیتر را در نظر بگیرد و مکانیسمهای بازگشتی را برای سازگاری در صورت نیاز پیادهسازی کند. این پلتفرم میتواند از کتابخانههای فقط پلتفرم برای استعلام نسخه genfs labels استفاده کند.
- در بومی، از
libgenfslabelsversion
استفاده کنید. برای فایل هدرlibgenfslabelsversion
بهgenfslabelsversion.h
مراجعه کنید. - در جاوا، از
android.os.SELinux.getGenfsLabelsVersion()
استفاده کنید.
ویژگی های سازگاری
خط مشی SELinux یک تعامل بین انواع منبع و هدف برای کلاسها و مجوزهای شی خاص است. هر شی (فرآیندها، فایلها و غیره) تحت تأثیر سیاست SELinux ممکن است فقط یک نوع داشته باشد، اما آن نوع ممکن است چندین ویژگی داشته باشد.
سیاست بیشتر بر اساس انواع موجود نوشته شده است:
allow source_type target_type:target_class permission(s);
این کار به این دلیل کار می کند که خط مشی با آگاهی از همه نوع نوشته شده است. با این حال، اگر خطمشی فروشنده و خطمشی پلت فرم از انواع خاصی استفاده میکند و برچسب یک شی خاص فقط در یکی از آن خطمشیها تغییر میکند، دیگری ممکن است حاوی خطمشی باشد که قبلاً به آن اعتماد کرده بود یا دسترسی را از دست داده است. به عنوان مثال:
File_contexts: /sys/A u:object_r:sysfs:s0 Platform: allow p_domain sysfs:class perm; Vendor: allow v_domain sysfs:class perm;
قابل تغییر به:
File_contexts: /sys/A u:object_r:sysfs_A:s0
اگرچه خط مشی فروشنده یکسان باقی می ماند، اما v_domain
به دلیل عدم وجود خط مشی برای نوع جدید sysfs_A
، دسترسی خود را از دست می دهد.
با تعریف یک خط مشی بر حسب ویژگی ها، می توانیم به شی زیربنایی نوعی بدهیم که دارای ویژگی مربوط به خط مشی هم برای پلتفرم و هم برای کد فروشنده باشد. این را می توان برای همه انواع انجام داد تا به طور مؤثر یک خط مشی ویژگی ایجاد شود که در آن انواع بتن هرگز استفاده نمی شود. در عمل، این فقط برای بخشهایی از خطمشی که بین پلتفرم و فروشنده همپوشانی دارند، که بهعنوان خطمشی عمومی پلتفرمی که بهعنوان بخشی از خطمشی فروشنده ایجاد میشود، تعریف و ارائه میشوند، لازم است.
تعریف خط مشی عمومی به عنوان ویژگی های نسخه شده دو هدف سازگاری خط مشی را برآورده می کند:
- اطمینان حاصل کنید که کد فروشنده پس از بهروزرسانی پلتفرم به کار خود ادامه میدهد. با افزودن ویژگیها به انواع بتن برای اشیاء مربوط به مواردی که کد فروشنده بر آنها تکیه دارد و دسترسی را حفظ میکند، به دست میآید.
- توانایی منسوخ کردن سیاست. با مشخص کردن واضح مجموعههای خطمشی به ویژگیهایی که میتوانند به محض اینکه نسخهای که با آن مطابقت دارند دیگر پشتیبانی نشود حذف شوند، به دست میآید. توسعه میتواند در پلتفرم ادامه یابد، با دانستن اینکه خطمشی قدیمی همچنان در خطمشی فروشنده وجود دارد و در صورت ارتقاء آن بهطور خودکار حذف میشود.
قابلیت نوشتن خط مشی
برای دستیابی به هدف عدم نیاز به دانش تغییرات نسخه خاص برای توسعه خط مشی، Android 8.0 شامل نقشه برداری بین انواع خط مشی عمومی پلت فرم و ویژگی های آنها است. نوع foo
به ویژگی foo_v N
نگاشت شده است، جایی که N
نسخه مورد نظر است. vN
مربوط به متغیر ساخت PLATFORM_SEPOLICY_VERSION
است و به شکل MM.NN
است، که در آن MM
مربوط به شماره SDK پلتفرم است و NN
یک نسخه خاص پلت فرم است.
ویژگیها در خطمشی عمومی نسخهبندی نشدهاند، بلکه بیشتر بهعنوان یک API وجود دارند که پلتفرم و خطمشی فروشنده میتوانند روی آن ایجاد کنند تا رابط بین دو پارتیشن پایدار بماند. هم نویسندگان خط مشی پلت فرم و هم فروشنده می توانند به نوشتن خط مشی همانطور که امروز نوشته می شود ادامه دهند.
خط مشی عمومی پلتفرم به عنوان allow source_foo target_bar: class perm ;
به عنوان بخشی از سیاست فروشنده گنجانده شده است. در طول کامپایل (که شامل نسخه مربوطه میشود) به خطمشی تبدیل میشود که به بخش فروشنده دستگاه میرود (نشان داده شده در زبان میانی رایج تغییر یافته (CIL)):
(allow source_foo_vN target_bar_vN (class (perm)))
از آنجایی که سیاست فروشنده هرگز جلوتر از پلتفرم نیست، نباید نگران نسخه های قبلی باشد. با این حال، خطمشی پلتفرم باید بداند خطمشی فروشنده چقدر عقب است، ویژگیهایی را در انواع آن لحاظ کند و خطمشی مربوط به ویژگیهای نسخهشده را تنظیم کند.
سیاست متفاوت است
ایجاد خودکار ویژگی ها با افزودن _v N
به انتهای هر نوع، بدون نگاشت ویژگی ها به انواع در بین تفاوت های نسخه، کاری انجام نمی دهد. اندروید یک نگاشت بین نسخه ها برای ویژگی ها و یک نگاشت انواع به آن ویژگی ها را حفظ می کند. این کار در فایل های نگاشت فوق با عباراتی مانند (CIL) انجام می شود:
(typeattributeset foo_vN (foo))
ارتقاء پلتفرم
بخش زیر سناریوهای ارتقاء پلتفرم را شرح می دهد.
انواع مشابه
این سناریو زمانی اتفاق میافتد که یک شی برچسبها را در نسخههای خطمشی تغییر نمیدهد. این برای انواع منبع و هدف یکسان است و با /dev/binder
قابل مشاهده است که در همه نسخهها برچسب binder_device
دارد. در خط مشی تغییر یافته به صورت زیر نمایش داده می شود:
binder_device_v1 … binder_device_vN
هنگام ارتقاء از v1
→ v2
، خط مشی پلتفرم باید شامل موارد زیر باشد:
type binder_device; -> (type binder_device) (in CIL)
در فایل نگاشت v1 (CIL):
(typeattributeset binder_device_v1 (binder_device))
در فایل نگاشت v2 (CIL):
(typeattributeset binder_device_v2 (binder_device))
در خط مشی فروشنده v1 (CIL):
(typeattribute binder_device_v1) (allow binder_device_v1 …)
در خط مشی فروشنده v2 (CIL):
(typeattribute binder_device_v2) (allow binder_device_v2 …)
انواع جدید
این سناریو زمانی اتفاق میافتد که پلتفرم نوع جدیدی را اضافه کرده باشد، که میتواند هنگام افزودن ویژگیهای جدید یا در حین سختسازی سیاست اتفاق بیفتد.
- ویژگی جدید. هنگامی که این نوع شیئی را برچسب گذاری می کند که قبلاً وجود نداشته است (مانند فرآیند سرویس جدید)، کد فروشنده قبلاً مستقیماً با آن تعامل نداشته است، بنابراین هیچ خط مشی مربوطه وجود ندارد. ویژگی جدید مربوط به نوع در نسخه قبلی دارای ویژگی نیست و بنابراین نیازی به ورودی در فایل نقشه برداری که آن نسخه را هدف قرار می دهد نخواهد بود.
- سخت شدن سیاست. وقتی نوع نشان دهنده سخت شدن خط مشی است، ویژگی نوع جدید باید به زنجیره ای از ویژگی های مربوط به قبلی مرتبط شود (مشابه با مثال قبلی که
/sys/A
را ازsysfs
بهsysfs_A
تغییر داد). کد فروشنده متکی به قاعدهای است که دسترسی بهsysfs
را امکانپذیر میکند و باید آن قانون را به عنوان یک ویژگی از نوع جدید درج کند.
هنگام ارتقاء از v1
→ v2
، خط مشی پلتفرم باید شامل موارد زیر باشد:
type sysfs_A; -> (type sysfs_A) (in CIL) type sysfs; (type sysfs) (in CIL)
در فایل نگاشت v1 (CIL):
(typeattributeset sysfs_v1 (sysfs sysfs_A))
در فایل نگاشت v2 (CIL):
(typeattributeset sysfs_v2 (sysfs)) (typeattributeset sysfs_A_v2 (sysfs_A))
در خط مشی فروشنده v1 (CIL):
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
در خط مشی فروشنده v2 (CIL):
(typeattribute sysfs_A_v2) (allow … sysfs_A_v2 …) (typeattribute sysfs_v2) (allow … sysfs_v2 …)
انواع حذف شده
این سناریو (نادر) زمانی رخ میدهد که یک نوع حذف شود، که میتواند زمانی اتفاق بیفتد که شی زیرین:
- باقی می ماند اما برچسب متفاوتی می گیرد.
- توسط پلت فرم حذف می شود.
در طول شل کردن خط مشی، یک نوع حذف میشود و به شی برچسبگذاری شده با آن نوع، یک برچسب متفاوت و از قبل موجود داده میشود. این نشاندهنده ادغام نگاشت ویژگیها است: کد فروشنده هنوز باید بتواند به شی زیربنایی با ویژگیای که قبلاً داشت، دسترسی داشته باشد، اما بقیه سیستم اکنون باید بتوانند با ویژگی جدید خود به آن دسترسی داشته باشند.
اگر مشخصه ای که به آن سوئیچ شده است جدید باشد، برچسب گذاری مجدد مانند مورد نوع جدید است، با این تفاوت که وقتی از یک برچسب موجود استفاده می شود، افزودن ویژگی قدیمی نوع جدید باعث می شود اشیا دیگری نیز با این نوع برچسب گذاری شوند. تازه در دسترس بودن این اساساً کاری است که توسط پلتفرم انجام می شود و به عنوان یک معامله قابل قبول برای حفظ سازگاری تلقی می شود.
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
نمونه نسخه 1: انواع در حال جمع شدن (حذف sysfs_A)
هنگام ارتقاء از v1
→ v2
، خط مشی پلتفرم باید شامل موارد زیر باشد:
type sysfs; (type sysfs) (in CIL)
در فایل نگاشت v1 (CIL):
(typeattributeset sysfs_v1 (sysfs)) (type sysfs_A) # in case vendors used the sysfs_A label on objects (typeattributeset sysfs_A_v1 (sysfs sysfs_A))
در فایل نگاشت v2 (CIL):
(typeattributeset sysfs_v2 (sysfs))
در خط مشی فروشنده v1 (CIL):
(typeattribute sysfs_A_v1) (allow … sysfs_A_v1 …) (typeattribute sysfs_v1) (allow … sysfs_v1 …)
در خط مشی فروشنده v2 (CIL):
(typeattribute sysfs_v2) (allow … sysfs_v2 …)
نمونه نسخه 2: حذف کامل (نوع foo)
هنگام ارتقاء از v1
→ v2
، خط مشی پلتفرم باید شامل موارد زیر باشد:
# nothing - we got rid of the type
در فایل نگاشت v1 (CIL):
(type foo) #needed in case vendors used the foo label on objects (typeattributeset foo_v1 (foo))
در فایل نگاشت v2 (CIL):
# nothing - get rid of it
در خط مشی فروشنده v1 (CIL):
(typeattribute foo_v1) (allow foo …) (typeattribute sysfs_v1) (allow sysfs_v1 …)
در خط مشی فروشنده v2 (CIL):
(typeattribute sysfs_v2) (allow sysfs_v2 …)
کلاس/مجوزهای جدید
این سناریو زمانی اتفاق میافتد که ارتقاء پلتفرم مؤلفههای سیاست جدیدی را معرفی میکند که در نسخههای قبلی وجود ندارند. به عنوان مثال، زمانی که Android مدیر شی servicemanager
را اضافه کرد که مجوزهای افزودن، یافتن و لیست را ایجاد کرد، شیاطین فروشنده که میخواهند با servicemanager
ثبت نام کنند به مجوزهایی نیاز داشتند که در دسترس نبود. در Android 8.0، فقط خطمشی پلتفرم ممکن است کلاسها و مجوزهای جدیدی اضافه کند.
برای اجازه دادن به همه دامنههایی که میتوانستند توسط خطمشی فروشنده ایجاد یا گسترش یافته باشند تا از کلاس جدید بدون مانع استفاده کنند، خطمشی پلتفرم باید شامل قانون مشابهی باشد:
allow {domain -coredomain} *:new_class perm;
حتی ممکن است به خط مشی اجازه دسترسی برای همه انواع رابط (خط مشی عمومی) نیاز داشته باشد تا مطمئن شوید که تصویر فروشنده دسترسی پیدا می کند. اگر این منجر به سیاست امنیتی غیرقابل قبولی شود (همانطور که ممکن است با تغییرات مدیر سرویس باشد)، ممکن است به طور بالقوه ارتقاء فروشنده اجباری شود.
کلاس/مجوزها حذف شد
این سناریو زمانی اتفاق میافتد که یک مدیر شی حذف میشود (مانند مدیر شی ZygoteConnection
) و نباید مشکلی ایجاد کند. کلاس مدیر شی و مجوزها می توانند در خط مشی تعریف شده باقی بمانند تا زمانی که نسخه فروشنده دیگر از آن استفاده نکند. این کار با افزودن تعاریف به فایل نگاشت مربوطه انجام می شود.
سفارشی سازی فروشنده برای انواع جدید/برچسب شده
انواع فروشنده جدید هسته اصلی توسعه سیاست فروشنده هستند زیرا برای توصیف فرآیندهای جدید، باینری ها، دستگاه ها، زیرسیستم ها و داده های ذخیره شده مورد نیاز هستند. به این ترتیب، اجازه ایجاد انواع تعریف شده توسط فروشنده ضروری است.
از آنجایی که خطمشی فروشنده همیشه قدیمیترین خطمشی دستگاه است، نیازی به تبدیل خودکار همه انواع فروشنده به ویژگیهای موجود در خطمشی وجود ندارد. پلتفرم به چیزی که در خطمشی فروشنده برچسبگذاری شده است متکی نیست زیرا پلتفرم از آن اطلاعی ندارد. با این حال، پلتفرم ویژگیها و انواع عمومی را که برای تعامل با اشیاء برچسبگذاری شده با این انواع استفاده میکند (مانند domain
، sysfs_type
و غیره) ارائه میکند. برای اینکه پلتفرم به تعامل صحیح با این اشیاء ادامه دهد، ویژگی ها و انواع باید به طور مناسب اعمال شوند و ممکن است نیاز باشد قوانین خاصی به دامنه های قابل تنظیم (مانند init
) اضافه شود.
تغییرات ویژگی برای اندروید 9
دستگاه هایی که به اندروید 9 ارتقا می یابند می توانند از ویژگی های زیر استفاده کنند، اما دستگاه هایی که با اندروید 9 راه اندازی می شوند نباید.
صفات ناقض
Android 9 شامل این ویژگی های مرتبط با دامنه است:
-
data_between_core_and_vendor_violators
. مشخصه برای همه دامنههایی که الزام به اشتراکگذاری نکردن فایلها از طریق مسیر بینvendor
وcoredomains
را نقض میکنند. فرآیندهای پلت فرم و فروشنده نباید از فایل های روی دیسک برای برقراری ارتباط استفاده کنند (ABI ناپایدار). توصیه:- کد فروشنده باید از
/data/vendor
استفاده کند. - سیستم نباید از
/data/vendor
استفاده کند.
- کد فروشنده باید از
-
system_executes_vendor_violators
. مشخصه برای همه دامنههای سیستم (به جز دامنههایinit
وshell domains
) که الزام اجرای نکردن باینریهای فروشنده را نقض میکنند. اجرای باینری های فروشنده دارای API ناپایدار است. پلتفرم نباید باینری های فروشنده را مستقیماً اجرا کند. توصیه:- چنین وابستگی های پلتفرمی به باینری های فروشنده باید پشت HIDL HAL ها باشد.
یا
-
coredomains
که نیاز به دسترسی به باینریهای فروشنده دارند، باید به پارتیشن فروشنده منتقل شوند و بنابراین،coredomain
نیستند.
- چنین وابستگی های پلتفرمی به باینری های فروشنده باید پشت HIDL HAL ها باشد.
ویژگی های غیر قابل اعتماد
برنامههای غیرقابل اعتمادی که کد دلخواه را میزبانی میکنند، نباید به سرویسهای HwBinder دسترسی داشته باشند، به جز برنامههایی که برای دسترسی از چنین برنامههایی به اندازه کافی ایمن در نظر گرفته میشوند (به سرویسهای ایمن زیر مراجعه کنید). دو دلیل اصلی برای این امر عبارتند از:
- سرورهای HwBinder احراز هویت مشتری را انجام نمی دهند زیرا HIDL در حال حاضر اطلاعات UID تماس گیرنده را نشان نمی دهد. حتی اگر HIDL چنین دادههایی را افشا کند، بسیاری از سرویسهای HwBinder یا در سطح پایینتر از برنامهها (مانند HAL) کار میکنند یا نباید برای مجوز به هویت برنامه تکیه کنند. بنابراین، برای ایمن بودن، فرض پیشفرض این است که هر سرویس HwBinder با همه مشتریان خود بهطور مساوی برای انجام عملیات ارائهشده توسط این سرویس دارای مجوز هستند.
- سرورهای HAL (زیرمجموعه ای از سرویس های HwBinder) حاوی کدهایی با نرخ بروز مشکلات امنیتی بالاتر از اجزای
system/core
هستند و به لایه های پایین پشته (تا به سخت افزار) دسترسی دارند و بنابراین فرصت های دور زدن مدل امنیتی اندروید را افزایش می دهند. .
خدمات ایمن
خدمات ایمن عبارتند از:
-
same_process_hwservice
. این سرویسها (طبق تعریف) در فرآیند مشتری اجرا میشوند و بنابراین دسترسی یکسانی به دامنه مشتری دارند که فرآیند در آن اجرا میشود. -
coredomain_hwservice
. این خدمات خطرات مرتبط با دلیل شماره 2 را ایجاد نمی کنند. -
hal_configstore_ISurfaceFlingerConfigs
. این سرویس به طور خاص برای استفاده توسط هر دامنه طراحی شده است. -
hal_graphics_allocator_hwservice
. این عملیات همچنین توسط سرویسsurfaceflinger
Binder ارائه می شود که برنامه ها مجاز به دسترسی به آن هستند. -
hal_omx_hwservice
. این یک نسخه HwBinder از سرویسmediacodec
Binder است که برنامه ها مجاز به دسترسی به آن هستند. -
hal_codec2_hwservice
. این نسخه جدیدترhal_omx_hwservice
است.
ویژگی های قابل استفاده
همه hwservices
که ایمن در نظر گرفته نمی شوند دارای ویژگی untrusted_app_visible_hwservice
هستند. سرورهای HAL مربوطه دارای ویژگی untrusted_app_visible_halserver
هستند. دستگاههایی که با Android 9 راهاندازی میشوند نباید از هیچ یک از ویژگیهای untrusted
استفاده کنند.
توصیه:
- برنامههای غیرقابل اعتماد باید در عوض با سرویس سیستمی که با فروشنده HIDL HAL صحبت میکند صحبت کنند. به عنوان مثال، برنامه ها می توانند با
binderservicedomain
صحبت کنند، سپسmediaserver
(که یکbinderservicedomain
است) به نوبه خود باhal_graphics_allocator
صحبت می کند.یا
- برنامههایی که نیاز به دسترسی مستقیم به HALهای
vendor
دارند، باید دامنه سیاستگذاری تعریفشده توسط فروشنده خود را داشته باشند.
تست های ویژگی فایل
اندروید 9 شامل تستهای زمان ساخت است که اطمینان میدهد همه فایلها در مکانهای خاص دارای ویژگیهای مناسب هستند (مانند همه فایلهای موجود در sysfs
دارای ویژگی sysfs_type
مورد نیاز هستند).
پلتفرم-سیاست عمومی
خط مشی عمومی پلتفرم هسته اصلی انطباق با مدل معماری Android 8.0 بدون حفظ اتحاد سیاست های پلت فرم از نسخه 1 و 2 است. فروشندگان در معرض زیرمجموعهای از خطمشی پلتفرم قرار میگیرند که شامل انواع و ویژگیهای قابل استفاده و قوانین مربوط به آن نوع و ویژگی است که سپس بخشی از خطمشی فروشنده میشود (یعنی vendor_sepolicy.cil
).
انواع و قوانین به طور خودکار در خطمشی تولید شده توسط فروشنده به attribute_v N
ترجمه میشوند، به طوری که همه انواع ارائهشده توسط پلتفرم، ویژگیهای نسخهبندیشده هستند (هرچند ویژگیها نسخهبندی نشدهاند). پلت فرم مسئول نگاشت انواع بتنی که ارائه می کند در ویژگی های مناسب است تا اطمینان حاصل شود که خط مشی فروشنده همچنان به کار خود ادامه می دهد و قوانین ارائه شده برای یک نسخه خاص گنجانده شده است. ترکیبی از خطمشی عمومی پلتفرم و خطمشی فروشنده، هدف مدل معماری Android 8.0 را برآورده میکند که اجازه ساخت پلتفرم و فروشنده مستقل را میدهد.
نگاشت به زنجیره های صفت
هنگام استفاده از ویژگیها برای نگاشت به نسخههای خطمشی، یک نوع به یک ویژگی یا ویژگیهای متعدد نگاشت میشود و اطمینان حاصل میکند که اشیاء برچسبگذاری شده با نوع از طریق ویژگیهای مربوط به انواع قبلیشان قابل دسترسی هستند.
حفظ هدف برای مخفی کردن اطلاعات نسخه از سیاست نویس به معنای تولید خودکار ویژگی های نسخه شده و اختصاص آنها به انواع مناسب است. در مورد رایج انواع استاتیک، این کار ساده است: type_foo
به type_foo_v1
نقشه میدهد.
برای تغییر برچسب شی مانند sysfs
→ sysfs_A
یا mediaserver
→ audioserver
، ایجاد این نگاشت بی اهمیت است (و در مثال های بالا توضیح داده شده است). نگهدارندگان خط مشی پلت فرم باید نحوه ایجاد نقشه در نقاط انتقال برای اشیا را تعیین کنند، که نیاز به درک رابطه بین اشیا و برچسب های اختصاص داده شده آنها و تعیین زمان وقوع آن دارد. برای سازگاری با عقب، این پیچیدگی باید در سمت پلتفرم مدیریت شود، که تنها پارتیشنی است که ممکن است افزایش یابد.
ارتقاء نسخه
برای سادگی، پلتفرم آندروید یک نسخه sepolicy را هنگامی که یک شاخه نسخه جدید قطع می شود منتشر می کند. همانطور که در بالا توضیح داده شد، شماره نسخه در PLATFORM_SEPOLICY_VERSION
موجود است و به شکل MM.nn
است، که در آن MM
مربوط به مقدار SDK است و nn
یک مقدار خصوصی است که در /platform/system/sepolicy.
به عنوان مثال، 19.0
برای Kitkat، 21.0
برای Lollipop، 22.0
برای Lollipop-MR1 23.0
برای Marshmallow، 24.0
برای Nougat، 25.0
برای Nougat-MR1، 26.0
برای Oreo، 27.0
برای Oreo-MR1 28.0
برای اندروید هستند. همیشه کامل اعداد به عنوان مثال، اگر یک ضربه MR به یک نسخه نیاز به تغییر ناسازگار در system/sepolicy/public
داشته باشد، اما نه یک برآمدگی API، آن نسخه sepolicy میتواند این باشد: vN.1
. نسخه موجود در یک شعبه توسعه یک دستگاه غیر قابل استفاده در حمل و نقل 10000.0
است.
ممکن است اندروید در هنگام ارتقاء، قدیمی ترین نسخه را منسوخ کند. برای اطلاعاتی درباره زمان منسوخ شدن یک نسخه، Android ممکن است تعداد دستگاههای دارای خطمشیهای فروشنده را جمعآوری کند که آن نسخه Android را اجرا میکنند و همچنان بهروزرسانیهای اصلی پلتفرم را دریافت میکنند. اگر عدد کمتر از یک آستانه خاص باشد، آن نسخه منسوخ می شود.
تأثیر عملکرد چندین ویژگی
همانطور که در https://github.com/SELinuxProject/cil/issues/9 توضیح داده شد، تعداد زیادی از ویژگی های اختصاص داده شده به یک نوع در صورت از دست رفتن حافظه پنهان سیاست، منجر به مشکلات عملکرد می شود.
تأیید شد که این مشکل در Android وجود دارد، بنابراین تغییراتی در Android 8.0 برای حذف ویژگیهای اضافه شده به خطمشی توسط کامپایلر خطمشی و همچنین حذف ویژگیهای استفاده نشده اعمال شد . این تغییرات رگرسیون عملکرد را حل کرد.
system_ext سیاست عمومی عمومی و محصول
از Android 11، پارتیشنهای system_ext
و product
مجاز هستند انواع عمومی تعیینشده خود را به پارتیشن فروشنده صادر کنند. مانند خط مشی عمومی پلتفرم، فروشنده از انواع و قوانین ترجمه شده به طور خودکار به ویژگی های نسخه شده استفاده می کند، به عنوان مثال، از type
به type_ N
، که در آن N
نسخه پلتفرمی است که پارتیشن فروشنده بر اساس آن ساخته شده است.
هنگامی که پارتیشنهای system_ext
و product
بر اساس همان پلتفرم نسخه N
هستند، سیستم ساخت فایلهای نگاشت پایه را به system_ext/etc/selinux/mapping/ N .cil
و product/etc/selinux/mapping/ N .cil
تولید میکند که حاوی هویت هستند. نگاشت از type
به type_ N
. فروشنده می تواند به type
با ویژگی نسخه شده type_ N
دسترسی پیدا کند.
در صورتی که فقط پارتیشنهای system_ext
و product
، مثلاً N
به N+1
(یا جدیدتر) بهروزرسانی شوند، در حالی که فروشنده در N
بماند، ممکن است فروشنده دسترسی به انواع پارتیشنهای system_ext
و product
را از دست بدهد. برای جلوگیری از شکستگی، پارتیشنهای system_ext
و product
باید فایلهای نقشهبرداری را از انواع بتن به ویژگیهای type_ N
ارائه دهند. هر شریک مسئولیت نگهداری فایلهای نگاشت را بر عهده دارد، اگر قرار است از N
فروشنده با N+1
(یا بالاتر) system_ext
و پارتیشنهای product
پشتیبانی کند.
برای انجام این کار، از شرکا انتظار می رود:
- فایل های نگاشت پایه ایجاد شده را از
N
system_ext
و پارتیشن هایproduct
در درخت منبع آنها کپی کنید. - فایل های نقشه برداری را در صورت نیاز اصلاح کنید.
- فایل های نگاشت را در
N+1
(یا جدیدتر)system_ext
و پارتیشن هایproduct
نصب کنید.
برای مثال، فرض کنید N
system_ext
یک نوع عمومی به نام foo_type
دارد. سپس system_ext/etc/selinux/mapping/ N .cil
در پارتیشن N
system_ext
به شکل زیر خواهد بود:
(typeattributeset foo_type_N (foo_type)) (expandtypeattribute foo_type_N true) (typeattribute foo_type_N)
اگر bar_type
به N+1
system_ext اضافه شود، و اگر bar_type
باید به foo_type
برای N
فروشنده نگاشت شود، N .cil
را می توان از
(typeattributeset foo_type_N (foo_type))
به
(typeattributeset foo_type_N (foo_type bar_type))
و سپس در پارتیشن N+1
system_ext نصب می شود. N
فروشنده می تواند به دسترسی به foo_type
و bar_type
N+1
system_ext ادامه دهد.
برچسب زدن زمینه های SELinux
برای حمایت از تمایز بین پلتفرم و سیاست فروشنده، سیستم فایلهای زمینه SELinux را متفاوت میسازد تا آنها را جدا نگه دارد.
زمینه های فایل
اندروید 8.0 تغییرات زیر را برای file_contexts
ارائه کرد:
- برای جلوگیری از سربار کامپایل اضافی روی دستگاه در هنگام بوت کردن،
file_contexts
به شکل باینری وجود ندارد. درعوض، فایل متنی با بیان منظم مانند{property, service}_contexts
(همانطور که قبل از 7.0 بودند) قابل خواندن هستند. -
file_contexts
بین دو فایل تقسیم می شود:-
plat_file_contexts
-
file_context
پلتفرم Android که هیچ برچسب مخصوص دستگاه ندارد، به جز برای برچسب زدن بخشهایی از پارتیشن/vendor
که باید دقیقاً برچسبگذاری شوند تا از عملکرد صحیح فایلهای sepolicy اطمینان حاصل شود. - باید در پارتیشن
system
در/system/etc/selinux/plat_file_contexts
روی دستگاه قرار داشته باشد و توسطinit
در ابتدا همراه با فروشندهfile_context
بارگذاری شود.
-
-
vendor_file_contexts
-
file_context
مخصوص دستگاه که با ترکیبfile_contexts
موجود در فهرستهای راهنمایBOARD_SEPOLICY_DIRS
در فایلهایBoardconfig.mk
دستگاه ساخته شده است. - باید در
/vendor/etc/selinux/vendor_file_contexts
در پارتیشنvendor
نصب شود و در ابتدا توسطinit
همراه باfile_context
پلتفرم بارگذاری شود.
-
-
زمینه های ملکی
در اندروید 8.0، property_contexts
بین دو فایل تقسیم میشود:
-
plat_property_contexts
-
property_context
پلتفرم Android که برچسب مخصوص دستگاه ندارد. - باید در پارتیشن
system
در/system/etc/selinux/plat_property_contexts
قرار داشته باشد و توسطinit
در ابتدا همراه با vendorproperty_contexts
بارگذاری شود.
-
-
vendor_property_contexts
-
property_context
مخصوص دستگاه با ترکیبproperty_contexts
یافت شده در دایرکتوری های اشاره شده توسطBOARD_SEPOLICY_DIRS
در فایل هایBoardconfig.mk
دستگاه ساخته شده است. - باید در پارتیشن
vendor
در/vendor/etc/selinux/vendor_property_contexts
قرار داشته باشد و در ابتدا توسطinit
به همراهproperty_context
پلت فرم بارگذاری شود.
-
زمینه های خدماتی
در اندروید 8.0، service_contexts
بین فایلهای زیر تقسیم میشود:
-
plat_service_contexts
-
service_context
مخصوص پلتفرم Android برایservicemanager
.service_context
هیچ برچسب مخصوص دستگاه ندارد. - باید در پارتیشن
system
در/system/etc/selinux/plat_service_contexts
قرار داشته باشد و توسطservicemanager
در ابتدا همراه با فروشندهservice_contexts
بارگیری شود.
-
-
vendor_service_contexts
-
service_context
مخصوص دستگاه که با ترکیبservice_contexts
یافت شده در دایرکتوری های اشاره شده توسطBOARD_SEPOLICY_DIRS
در فایل هایBoardconfig.mk
دستگاه ساخته شده است. - باید در پارتیشن
vendor
در/vendor/etc/selinux/vendor_service_contexts
قرار داشته باشد و توسطservicemanager
در ابتدا همراه با platformservice_contexts
بارگیری شود. - اگرچه
servicemanager
در زمان راهاندازی به دنبال این فایل میگردد، اما برای یک دستگاهTREBLE
کاملاً سازگار،vendor_service_contexts
نباید وجود داشته باشد. این به این دلیل است که تمام تعامل بینvendor
و فرآیندهایsystem
باید از طریقhwservicemanager
/hwbinder
انجام شود.
-
-
plat_hwservice_contexts
- پلتفرم Android
hwservice_context
برایhwservicemanager
که هیچ برچسب مخصوص دستگاه ندارد. - باید در پارتیشن
system
در/system/etc/selinux/plat_hwservice_contexts
قرار داشته باشد و در ابتدا توسطhwservicemanager
همراه باvendor_hwservice_contexts
بارگیری شود.
- پلتفرم Android
-
vendor_hwservice_contexts
-
hwservice_context
مخصوص دستگاه که با ترکیبhwservice_contexts
یافت شده در دایرکتوری های اشاره شده توسطBOARD_SEPOLICY_DIRS
در فایل هایBoardconfig.mk
دستگاه ساخته شده است. - باید در پارتیشن
vendor
در/vendor/etc/selinux/vendor_hwservice_contexts
قرار داشته باشد و در ابتدا توسطhwservicemanager
همراه باplat_service_contexts
بارگیری شود.
-
-
vndservice_contexts
-
service_context
مخصوص دستگاه برایvndservicemanager
ساخته شده با ترکیبvndservice_contexts
موجود در فهرستهای راهنمایBOARD_SEPOLICY_DIRS
درBoardconfig.mk
دستگاه. - این فایل باید در پارتیشن
vendor
در/vendor/etc/selinux/vndservice_contexts
قرار داشته باشد و در ابتدا توسطvndservicemanager
بارگیری شود.
-
زمینه های Seapp
در اندروید 8.0، seapp_contexts
بین دو فایل تقسیم میشود:
-
plat_seapp_contexts
- پلتفرم Android
seapp_context
که هیچ تغییری خاص دستگاه ندارد. - باید در پارتیشن
system
در/system/etc/selinux/plat_seapp_contexts.
- پلتفرم Android
-
vendor_seapp_contexts
- پسوند خاص دستگاه برای پلتفرم
seapp_context
با ترکیبseapp_contexts
موجود در فهرستهای راهنمایBOARD_SEPOLICY_DIRS
در فایلهایBoardconfig.mk
دستگاه ساخته شده است. - باید در پارتیشن
vendor
در/vendor/etc/selinux/vendor_seapp_contexts
ساکن باشد.
- پسوند خاص دستگاه برای پلتفرم
مجوزهای MAC
در Android 8.0 ، mac_permissions.xml
بین دو پرونده تقسیم می شود:
- پلتفرم
mac_permissions.xml
- سیستم عامل Android
mac_permissions.xml
که هیچ تغییری خاص دستگاه ندارد. - باید در پارتیشن
system
در/system/etc/selinux/.
- سیستم عامل Android
- غیر پلتفرم
mac_permissions.xml
- پسوند خاص دستگاه به پلتفرم
mac_permissions.xml
ساخته شده ازmac_permissions.xml
موجود در دایرکتوری های اشاره شده توسطBOARD_SEPOLICY_DIRS
در پرونده هایBoardconfig.mk
دستگاه. - باید در پارتیشن
vendor
در/vendor/etc/selinux/.
- پسوند خاص دستگاه به پلتفرم