تهيئة البائع

تتمتع عملية init بأذونات غير مقيدة تقريبًا وتستخدم برامج نصية للإدخال من كل من أقسام النظام والبائعين لتهيئة النظام أثناء عملية التمهيد. يتسبب هذا الوصول في حدوث فجوة كبيرة في تقسيم نظام Treble/البائع، حيث قد تقوم البرامج النصية للمورد بتوجيه init للوصول إلى الملفات والخصائص وما إلى ذلك التي لا تشكل جزءًا من الواجهة الثنائية المستقرة لتطبيق النظام والبائع (ABI).

تم تصميم Vendor init لإغلاق هذه الثغرة باستخدام مجال Linux (SELinux) منفصل محسّن الأمان vendor_init لتشغيل الأوامر الموجودة في /vendor بأذونات خاصة بالمورد.

آلية

يقوم Vendor init بتفرع عملية فرعية من init مبكرًا في عملية التمهيد باستخدام سياق SELinux u:r:vendor_init:s0 . يحتوي سياق SELinux هذا على أذونات أقل بكثير من سياق init الافتراضي ويقتصر الوصول إليه على الملفات والخصائص وما إلى ذلك التي تكون إما خاصة بالمورد أو جزءًا من ABI المستقر لبائع النظام.

يتحقق Init من كل برنامج نصي يقوم بتحميله لمعرفة ما إذا كان مساره يبدأ بـ /vendor وإذا كان الأمر كذلك، يضع علامة عليه مع الإشارة إلى أنه يجب تشغيل أوامره في سياق المورد init. يتم وضع تعليقات توضيحية على كل وحدة init مدمجة بقيمة منطقية تحدد ما إذا كان يجب تشغيل الأمر في عملية init الفرعية للمورد أم لا:

  • يتم شرح معظم الأوامر التي تصل إلى نظام الملفات للتشغيل في العملية الفرعية للمورد init وبالتالي تخضع لسياسة البائع init SEPolicy.
  • يتم تشغيل معظم الأوامر التي تؤثر على حالة init الداخلية (على سبيل المثال، بدء الخدمات وإيقافها) ضمن عملية init العادية. يتم إعلام هذه الأوامر بأن البرنامج النصي الخاص بالمورد يدعوها للقيام بمعالجة الأذونات الخاصة بها بخلاف SELinux.

تحتوي حلقة المعالجة الرئيسية لـ init على فحص أنه إذا تم إضافة تعليق توضيحي للأمر ليتم تشغيله في العملية الفرعية للمورد ونشأ من برنامج نصي للمورد، فسيتم إرسال هذا الأمر عبر الاتصال بين العمليات (IPC) إلى العملية الفرعية للمورد، والتي تقوم بتشغيل الأمر ويرسل النتيجة مرة أخرى إلى الحرف الأول.

استخدام Init المورد

يتم تمكين Vendor init بشكل افتراضي وتنطبق قيوده على كافة البرامج النصية init الموجودة في القسم /vendor . يجب أن يكون Vendor init شفافًا بالنسبة للبائعين الذين لا تصل نصوصهم البرمجية بالفعل إلى ملفات النظام وخصائصه وما إلى ذلك.

ومع ذلك، إذا كانت الأوامر الموجودة في برنامج نصي محدد للمورد تنتهك قيود init الخاصة بالمورد، فستفشل الأوامر. تحتوي الأوامر الفاشلة على سطر في سجل kernel (مرئي باستخدام dmesg) من init يشير إلى الفشل. تصاحب عملية تدقيق SELinux أي أمر فاشل فشل بسبب سياسة SELinux. مثال على الفشل بما في ذلك تدقيق SELinux:

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

إذا فشل الأمر، هناك خياران:

  • إذا فشل الأمر بسبب تقييد مقصود (على سبيل المثال، إذا كان الأمر يصل إلى ملف نظام أو خاصية)، فيجب إعادة تنفيذ الأمر بطريقة صديقة لـ Treble، من خلال الواجهات المستقرة فقط. تمنع قواعد Neverallow إضافة أذونات للوصول إلى ملفات النظام التي لا تشكل جزءًا من ABI المستقر لمورد النظام.
  • إذا كانت تسمية SELinux جديدة ولم يتم منحها أذونات بالفعل في النظام vendor_init.te أو أذونات مستبعدة عبر قواعد Neverallow، فقد يتم منح التسمية الجديدة أذونات في vendor_init.te الخاص بالجهاز.

بالنسبة للأجهزة التي يتم تشغيلها قبل Android 9، قد يتم تجاوز قواعد Neverallows عن طريق إضافة سمة النوع data_between_core_and_vendor_violators إلى ملف vendor_init.te الخاص بالجهاز.

مواقع الكود

الجزء الأكبر من المنطق الخاص بالمورد init IPC موجود في system/core/init/subcontext.cpp .

يوجد جدول الأوامر في فئة BuiltinFunctionMap في system/core/init/builtins.cpp ويتضمن تعليقات توضيحية تشير إلى ما إذا كان يجب تشغيل الأمر في العملية الفرعية للمورد.

يتم تقسيم سياسة SEPolicy الخاصة بالمورد init عبر الدلائل الخاصة ( system/sepolicy/private/vendor_init.te ) والعامة ( system/sepolicy/public/vendor_init.te ) في system/sepolicy.