كتابة سياسة SELinux

يوفر مشروع Android مفتوح المصدر (AOSP) سياسة قاعدة صلبة للتطبيقات والخدمات الشائعة عبر جميع أجهزة Android. يقوم المساهمون في AOSP بتنقيح هذه السياسة بانتظام. من المتوقع أن تشكل السياسة الأساسية حوالي 90-95٪ من السياسة النهائية على الجهاز مع التخصيصات الخاصة بالجهاز والتي تشكل النسبة المتبقية 5-10٪. تركز هذه المقالة على هذه التخصيصات الخاصة بالجهاز ، وكيفية كتابة سياسة خاصة بالجهاز ، وبعض المخاطر التي يجب تجنبها على طول الطريق.

إحضار الجهاز

أثناء كتابة سياسة خاصة بالجهاز ، اتبع هذه الخطوات.

تشغيل في الوضع المتساهل

عندما يكون الجهاز في الوضع المسموح به ، يتم تسجيل حالات الرفض ولكن لا يتم فرضها. الوضع المتسامح مهم لسببين:

  • يضمن الوضع المسموح به ألا يؤدي عرض السياسة إلى تأخير مهام إحضار الجهاز المبكرة الأخرى.
  • قد يؤدي الرفض القسري إلى إخفاء حالات إنكار أخرى. على سبيل المثال ، يستلزم الوصول إلى الملف عادةً البحث في الدليل ، وفتح الملف ، ثم قراءة الملف. في وضع الفرض ، سيحدث رفض بحث الدليل فقط. يضمن الوضع المتسامح رؤية جميع حالات الرفض.

إن أبسط طريقة لوضع جهاز في الوضع المسموح به هي استخدام سطر أوامر kernel . يمكن إضافة هذا إلى ملف BoardConfig.mk الخاص بالجهاز: platform/device/<vendor>/<target>/BoardConfig.mk . بعد تعديل سطر الأوامر ، قم بإجراء make clean ، ثم make bootimage ، ووميض صورة التمهيد الجديدة.

بعد ذلك ، قم بتأكيد الوضع المسموح به باستخدام:

adb shell getenforce

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

فرض مبكرًا

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

إزالة أو حذف السياسة الحالية

هناك عدد من الأسباب الوجيهة لإنشاء سياسة خاصة بالجهاز من البداية على جهاز جديد ، والتي تشمل:

معالجة رفض الخدمات الأساسية

عادة ما يتم التعامل مع حالات الرفض التي تم إنشاؤها بواسطة الخدمات الأساسية عن طريق تصنيف الملفات. فمثلا:

avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0”
dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0
tclass=chr_file permissive=1
avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs"
scontext=u:r:mediaserver:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

تتم معالجتها بالكامل عن طريق وضع العلامات /dev/kgsl-3d0 بشكل صحيح. في هذا المثال ، tcontext هو device . يمثل هذا سياقًا افتراضيًا حيث يتلقى كل شيء في /dev تصنيف " الجهاز " ما لم يتم تعيين تسمية أكثر تحديدًا. إن مجرد قبول الناتج من Audit2allow هنا سيؤدي إلى قاعدة غير صحيحة ومفرطة في التساهل.

لحل هذا النوع من المشاكل ، امنح الملف تسمية أكثر تحديدًا ، وهي في هذه الحالة gpu_device . ليست هناك حاجة إلى مزيد من الأذونات لأن الخادم الوسيط لديه بالفعل الأذونات اللازمة في السياسة الأساسية للوصول إلى gpu_device.

الملفات الأخرى الخاصة بالجهاز والتي يجب تصنيفها بأنواع محددة مسبقًا في السياسة الأساسية:

بشكل عام ، منح الأذونات للتسميات الافتراضية أمر خاطئ. العديد من هذه الأذونات ممنوعة من خلال قواعد لا تسمح مطلقًا ، ولكن حتى في حالة عدم السماح بها صراحةً ، فإن أفضل الممارسات هي توفير تصنيف محدد.

تسمية الخدمات الجديدة والعناوين المرفوضة

الخدمات التي تم إطلاقها مبدئيًا مطلوبة للتشغيل في نطاقات SELinux الخاصة بها. المثال التالي يضع الخدمة "foo" في نطاق SELinux الخاص بها ويمنحها أذونات.

تم إطلاق الخدمة في جهازنا init. device .rc ملف init. device .rc كـ:

service foo /system/bin/foo
    class core
  1. إنشاء مجال جديد "foo"

    قم بإنشاء ملف device/ manufacturer / device-name /sepolicy/foo.te بالمحتويات التالية:

    # foo service
    type foo, domain;
    type foo_exec, exec_type, file_type;
    
    init_daemon_domain(foo)
    

    هذا هو النموذج الأولي لنطاق foo SELinux ، والذي يمكنك إضافة قواعد إليه بناءً على العمليات المحددة التي يقوم بها هذا الملف القابل للتنفيذ.

  2. الملصق /system/bin/foo

    أضف ما يلي إلى device/ manufacturer / device-name /sepolicy/file_contexts :

    /system/bin/foo   u:object_r:foo_exec:s0
    

    هذا يضمن تسمية الملف التنفيذي بشكل صحيح حتى يقوم SELinux بتشغيل الخدمة في المجال المناسب.

  3. بناء وفلاش التمهيد وصورة النظام.
  4. قم بتحسين قواعد SELinux للمجال.

    استخدم الرفض لتحديد الأذونات المطلوبة. توفر أداة Audit2allow إرشادات جيدة ، ولكن لا تستخدمها إلا للإبلاغ عن كتابة السياسة. لا تقم فقط بنسخ الإخراج.

عد إلى وضع الفرض

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

الأخطاء الشائعة

فيما يلي بعض الحلول للأخطاء الشائعة التي تحدث عند كتابة سياسات خاصة بالجهاز.

الإفراط في النفي

قاعدة المثال التالية تشبه قفل الباب الأمامي مع ترك النوافذ مفتوحة:

allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms

القصد واضح: يمكن للجميع ، باستثناء تطبيقات الجهات الخارجية ، الوصول إلى جهاز التصحيح.

القاعدة معيبة من نواحٍ قليلة. يعد استبعاد التطبيق غير untrusted_app به أمرًا تافهًا للتغلب عليه نظرًا لأن جميع التطبيقات قد تعمل اختياريًا على تشغيل الخدمات في مجال isolated_app . وبالمثل ، إذا تمت إضافة مجالات جديدة لتطبيقات الجهات الخارجية إلى AOSP ، فسيكون بإمكانهم أيضًا الوصول إلى scary_debug_device . القاعدة مفرطة في التساهل. لن تستفيد معظم المجالات من الوصول إلى أداة التصحيح هذه. يجب كتابة القاعدة للسماح فقط للمجالات التي تتطلب الوصول.

ميزات التصحيح في الإنتاج

يجب ألا تكون ميزات التصحيح موجودة في عمليات إنشاء الإنتاج ولا يجب أن تكون سياستها.

أبسط بديل هو السماح لميزة تصحيح الأخطاء فقط عندما يتم تعطيل SELinux في أبنية eng / userdebug ، مثل adb adb root و adb shell setenforce 0 .

بديل آمن آخر هو إرفاق أذونات التصحيح في عبارة userdebug_or_eng .

انفجار حجم السياسة

يصف توصيف سياسات SEAndroid in the Wild اتجاهًا مقلقًا في نمو تخصيصات سياسة الجهاز. يجب أن تمثل السياسة الخاصة بالجهاز 5-10٪ من السياسة العامة التي يتم تشغيلها على الجهاز. من شبه المؤكد أن التخصيصات في النطاق 20٪ + تحتوي على أكثر من المجالات المميزة والسياسة الميتة.

سياسة كبيرة غير ضرورية:

  • يحقق نجاحًا مضاعفًا في الذاكرة حيث يتم وضع السياسة في ramdisk ويتم تحميلها أيضًا في ذاكرة kernel.
  • يهدر مساحة القرص بالحاجة إلى إقلاع أكبر.
  • يؤثر على أوقات البحث في سياسة وقت التشغيل.

يوضح المثال التالي جهازين شكّلت فيهما السياسة الخاصة بالشركة المصنّعة 50٪ و 40٪ من السياسة على الجهاز. أسفرت إعادة كتابة السياسة عن تحسينات أمنية كبيرة مع عدم فقدان الوظائف ، كما هو موضح أدناه. (تم تضمين أجهزة AOSP Shamu و Flounder للمقارنة.)

الشكل 1: مقارنة حجم السياسة الخاصة بالجهاز بعد تدقيق الأمان.

الشكل 1 . مقارنة حجم السياسة الخاصة بالجهاز بعد تدقيق الأمان.

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

منح القدرة dac_override

يعني رفض dac_override أن العملية المخالفة تحاول الوصول إلى ملف بأذونات مستخدم / مجموعة / عالمية غير صحيحة لنظام unix. الحل المناسب هو عدم منح إذن dac_override . بدلاً من ذلك ، قم بتغيير أذونات unix في الملف أو العملية . تحتاج بعض المجالات مثل init و vold و installd حقًا إلى القدرة على تجاوز أذونات ملف unix للوصول إلى ملفات العمليات الأخرى. راجع مدونة Dan Walsh للحصول على شرح أكثر تفصيلاً.