تنفيذ SELinux

تم إعداد SELinux للرفض التلقائي، ما يعني أنّه يجب أن تسمح السياسة صراحةً بكل عملية وصول تتضمن ربطًا في النواة. ويعني ذلك أنّ ملف السياسة يتألف من كمية كبيرة من المعلومات المتعلّقة بالقواعد والأنواع والفئات والأذونات وغير ذلك. اعتبار كامل لنظام SELinux يقع خارج نطاق هذه الوثيقة، ولكن فهم كيفية كتابة أصبحت قواعد السياسات ضرورية الآن عند إنشاء أجهزة Android جديدة. تتوفّر حاليًا الكثير من المعلومات حول SELinux. راجع الدعم للمراجع المقترَحة.

الملفات الأساسية

لتفعيل SELinux، عليك دمج أحدث ملف لنظام التشغيل Android ثم دمج الملفات المتوفّرة في الدليل system/sepolicy . عند تجميعها، تتكون هذه الملفات من أمان نواة SELinux وتغطي الإصدارات الرئيسية لنظام التشغيل Android.

بوجه عام، يجب عدم تعديل ملفات system/sepolicy بشكل مباشر. يمكنك بدلاً من ذلك إضافة ملفات السياسات الخاصة بجهازك أو تعديلها في /device/manufacturer/device-name/sepolicy الدليل. في الإصدار Android 8.0 والإصدارات الأحدث، يجب ضبط التغييرات التي تجريها على هذه الملفات تؤثر فقط على السياسة في دليل البائعين. لمزيد من التفاصيل حول فصل سياسة الأمان العامة في Android 8.0 والإصدارات الأحدث، يُرجى الاطّلاع على مقالة تخصيص سياسة الأمان في Android 8.0 والإصدارات الأحدث. بغض النظر عن إصدار Android، سيظلّ بإمكانك تعديل الملفات التالية:

ملفات السياسات

الملفات التي تنتهي بـ *.te هي ملفات مصدر لسياسة SELinux، والتي تحدد المجالات وتسمياتها. قد تحتاج إلى إنشاء ملفات سياسات جديدة في /device/manufacturer/device-name/sepolicy، ولكن عليك محاولة تعديل الملفات الحالية كلما أمكن ذلك.

ملفات السياق

ملفات السياق هي المكان الذي تحدد فيه تصنيفات للكائنات.

  • يحدِّد file_contexts تصنيفات للملفات ويستخدمها مختلف مكوّنات مساحة المستخدم. أثناء إنشاء سياسات جديدة، أنشئ هذا الملف أو عدِّله لتحديد تصنيفات جديدة للملفات. لتطبيق نوع file_contexts الجديد، يُرجى اتّباع الخطوات التالية: يجب إعادة إنشاء صورة نظام الملفات أو تشغيل restorecon على الملف ستتم إعادة تصنيفه. عند إجراء الترقيات، ستكون التغييرات على "file_contexts": تطبيقها تلقائيًا على أقسام النظام وuserdata كجزء من الترقية. يمكن أيضًا تطبيق التغييرات تلقائيًا عند الترقية إلى غيرها من الأقسام من خلال إضافة طلبات restorecon_recursive إلىملف init.board.rc بعد تركيب القسم بالقراءة والكتابة.
  • يعيّن genfs_contexts تصنيفات لأنظمة الملفات، مثل تم تمديد proc أو vfat التي لا تتوافق ذات الصلة. يتم تحميل هذا الإعداد كجزء من سياسة kernel، ولكن قد لا تسري التغييرات على ملفات البيانات في kernel، ما يتطلّب إعادة تشغيل الجهاز أو إزالة تثبيت نظام الملفات وإعادة تثبيته لتطبيق التغيير بالكامل. قد يتم أيضًا تعيين تصنيفات محدّدة إلى قواعد تثبيت معيّنة، مثل يمكنك vfat باستخدام الخيار context=mount.
  • يعيّن property_contexts تصنيفات لخصائص نظام Android إلى والتحكم في العمليات التي يمكن أن تضعها. تتم قراءة هذه الإعدادات بواسطة init أثناء بدء التشغيل.
  • يحدد service_contexts تصنيفات لخدمات ربط Android في التحكم في العمليات التي يمكن إضافتها (تسجيل) والعثور على (البحث) عن مجلد مرجع للخدمة. تقرأ عملية servicemanager هذا الإعداد أثناء بدء التشغيل.
  • يحدِّد seapp_contexts تصنيفات لعمليات التطبيقات وملفّات /data/data. تتم قراءة هذه الإعدادات بواسطة عملية zygote في كل عملية تشغيل للتطبيق بحلول installd أثناء بدء التشغيل.
  • mac_permissions.xml تُسنِد علامة seinfo إلى التطبيقات استنادًا إلى توقيعها واسم حِزمها اختياريًا. تشير رسالة الأشكال البيانية يمكن بعد ذلك استخدام العلامة seinfo كمفتاح في ملف واحد (seapp_contexts) لتحديد تصنيف معيّن لجميع التطبيقات التي تحتوي على العلامة seinfo هذه. تقرأ system_server هذه الإعدادات أثناء بدء التشغيل.
  • تعيِّن keystore2_key_contexts تصنيفات إلى مساحات الاسم في Keystore 2.0. يتم فرض مساحات الأسماء هذه من خلال الخادم الخفي keystore2. دائمًا ما حافظ ملف تخزين المفاتيح تم توفير مساحات الاسم المستندة إلى المعرّف الفريد العام (UID) أو المعرّف الفريد للمنتج (AID). يدعم الإصدار 2.0 من Keystore 2.0 أيضًا سياسة sepolicy ومساحات الاسم المحددة. يمكنك الاطّلاع على وصف تفصيلي لتنسيق هذا الملف ومخطّطاته هنا.

ملف makefile BoardConfig.mk

بعد تعديل ملفات السياسة والسياق أو إضافتها، عدِّلملف /device/manufacturer/device-name/BoardConfig.mk makefile للإشارة إلى الدليل الفرعي sepolicy وكل ملف سياسة جديد. لمزيد من المعلومات عن متغيّرات BOARD_SEPOLICY، يمكنك الاطّلاع على ملف system/sepolicy/README.

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

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

عند تثبيت ملفات السياسة الجديدة وتحديثات BoardConfig.mk، يتم تلقائيًا دمج إعدادات السياسة الجديدة في ملف سياسة kernel النهائي. لمزيد من المعلومات حول كيفية إنشاء سياسة الأمان على الجهاز، يُرجى الاطّلاع على مقالة إنشاء سياسة الأمان.

التنفيذ

لبدء استخدام SELinux:

  1. فعِّل SELinux في النواة: CONFIG_SECURITY_SELINUX=y
  2. غيِّر مَعلمة kernel_cmdline أو bootconfig لكي:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    أو
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    هذا الإجراء مخصّص فقط للتطوير الأولي للسياسة على الجهاز. بعد سياسة تمهيد أولي، أزِل هذه المعلمة حتى يصبح أو أنه أخفق في CTS.
  3. شغِّل النظام متساهلًا وتحقَّق من عمليات الرفض التي تحدث أثناء التشغيل:
    على نظام التشغيل Ubuntu 14.04 أو إصدار أحدث:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    على نظام التشغيل Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. تقييم مخرجات التحذيرات التي تشبه init: Warning! Service name needs a SELinux domain defined; please fix! (الاطّلاع على) التحقق من صحة التعليمات والأدوات.
  5. تحديد الأجهزة والملفات الجديدة الأخرى التي تحتاج إلى تصنيف
  6. استخدِم تصنيفات حالية أو جديدة للكائنات. اطّلِع على ملفات *_contexts لمعرفة كيفية تصنيف العناصر في السابق واستخدِم معلوماتك عن معاني التصنيفات لتحديد تصنيف جديد. من الناحية المثالية، هذا تصنيف موجود يتناسب مع السياسة، ولكن في بعض الأحيان يلزم تسمية جديدة، وقواعد الوصول إلى ذلك التصنيف احتاجت. أضِف تصنيفاتك إلى ملفات السياق المناسبة.
  7. حدد النطاقات/العمليات التي ينبغي أن يكون لها نطاقات أمان خاصة بها. قد تحتاج على الأرجح إلى كتابة سياسة جديدة تمامًا لكل شركة. على سبيل المثال، يجب أن يكون لكل الخدمات التي تم إنشاؤها من init خاص بها. تساعد الأوامر التالية في الكشف عن الخدمات التي لا تزال قيد التشغيل (ولكن تحتاج جميع الخدمات إلى معالجة مماثلة):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. راجِع init.device.rc لتحديد أي نطاقات ليس لديها نوع نطاق. امنحهم نطاقًا مبكرًا في عملية التطوير لتجنُّب إضافة قواعد إلى init أو الخلط بين أذونات الوصول إلى init وأذونات الوصول المُدرَجة في سياستهم الخاصة.
  9. إعداد BOARD_CONFIG.mk لاستخدام متغيّرات BOARD_SEPOLICY_* اطّلِع على ملف README في system/sepolicy لمعرفة تفاصيل حول إعداد هذا الإجراء.
  10. افحص ملف init.device.rc وfstab.device و تأكّد من أن كل استخدام لـ mount يتوافق مع التي تحمل علامة أو أن الخيار context= mount المحددة.
  11. راجِع كلّ رفض وأنشئ سياسة SELinux للتعامل مع كلّ منها بشكلٍ صحيح. اطّلِع على الأمثلة في التخصيص.

يجب أن تبدأ بالسياسات في AOSP ثم تعتمد عليها التخصيصات الخاصة بك. لمزيد من المعلومات حول استراتيجية السياسة ومحاولة الاطّلاع عن كثب على بعض هذه الخطوات، اطّلِع على مقالة كتابة سياسة SELinux.

حالات الاستخدام

في ما يلي أمثلة محدّدة على عمليات الاستيلاء التي يجب أخذها في الاعتبار عند إنشاء البرامج وسياسات SELinux المرتبطة بها:

الروابط الرمزية: نظرًا لأن الروابط الرمزية تظهر كملفات، فإنها غالبًا ما تكون قراءتها كملفات، مما قد يؤدي إلى عمليات استغلال. على سبيل المثال، قد تكون بعض مثل init، تتيح تغيير أذونات بعض الملفات، وأحيانًا يكون منفتحًا بشكل مفرط.

وقد يستبدل المهاجمون بعد ذلك هذه الملفات بروابط رمزية تؤدي إلى الرموز التي يتحكمون فيها، مما يسمح للمهاجم بإعادة كتابة ملفات عشوائية. ولكن إذا كنت تعرف أنّ تطبيقك لا ينتقل أبدًا إلى رابط رمزي، يمكنك منعه من إجراء ذلك باستخدام SELinux.

ملفات النظام: ضع في الاعتبار فئة ملفات النظام التي يجب تعديله من خلال خادم النظام فقط. ومع ذلك، منذ netd، يعمل init وvold كجذر، ويمكن لهما الوصول ملفات النظام هذه. وبالتالي، إذا تم اختراق netd، يمكن أن يؤدي ذلك إلى اختراق هذه الملفات وربما خادم النظام نفسه.

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

بيانات التطبيق: مثال آخر هو فئة الدوال التي يجب تشغيلها بصفتها مشرفًا ولكن لا يُسمح لها بالوصول إلى بيانات التطبيق. وهذا مفيد للغاية، لأنّه يمكن إجراء تأكيدات واسعة النطاق، مثل حظر الوصول إلى الإنترنت لنطاقات معيّنة غير مرتبطة ببيانات التطبيق.

setattr: بالنسبة إلى أوامر مثل chmod و chown، يمكنك تحديد مجموعة الملفات التي يمكن للملف المرتبط بالنطاق تنفيذ setattr فيها. ويمكن أن يتم منع أي شيء خارج هذا النطاق من إجراء هذه التغييرات، حتى من خلال حساب الجذر. وبالتالي، قد يُجري التطبيق اختبارات chmod وchown على التطبيقات المصنّفة app_data_files ولكن ليس shell_data_files أو system_data_files.