تنفيذ SELinux

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

الملفات الرئيسية

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

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

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

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

ملفات السياق

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

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

ملف BoardConfig.mk

بعد تعديل ملفات السياسة والسياق أو إضافتها، عليك تعديل ملف /device/manufacturer/device-name/BoardConfig.mk للإشارة إلى الدليل الفرعي 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، يتم تلقائيًا إنشاء إعدادات السياسة الجديدة في ملف سياسة النواة النهائي. لمزيد من المعلومات عن كيفية إنشاء سياسة الأمان على الجهاز، يُرجى الاطّلاع على مقالة إنشاء سياسة الأمان.

التنفيذ

للبدء في استخدام 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.