فرآیند init تقریباً مجوزهای نامحدودی دارد و از اسکریپتهای ورودی از هر دو پارتیشن سیستم و فروشنده برای مقداردهی اولیه سیستم در طول فرآیند بوت استفاده میکند. این دسترسی باعث ایجاد یک حفره بزرگ در تقسیمبندی سیستم/فروشنده Treble میشود، زیرا اسکریپتهای فروشنده ممکن است به init دستور دهند به فایلها، خواص و غیرهای دسترسی پیدا کند که بخشی از رابط دودویی برنامه پایدار سیستم-فروشنده (ABI) نیستند.
Vendor init برای بستن این حفره امنیتی طراحی شده است و از یک دامنهی مجزای لینوکس (SELinux) به نام vendor_init استفاده میکند که از نظر امنیتی ارتقا یافته است و دستورات موجود در /vendor را با مجوزهای خاص فروشنده اجرا میکند.
مکانیسم
تابع init فروشنده، در اوایل فرآیند بوت، یک زیرفرآیند از init را با زمینه SELinux به u:r:vendor_init:s0 منشعب میکند. این زمینه SELinux مجوزهای بسیار کمتری نسبت به زمینه init پیشفرض دارد و دسترسی آن محدود به فایلها، ویژگیها و غیره است که یا مختص فروشنده هستند یا بخشی از ABI پایدار فروشنده سیستم میباشند.
Init هر اسکریپتی را که بارگذاری میکند بررسی میکند تا ببیند آیا مسیر آن با /vendor شروع میشود یا خیر، و اگر چنین است، آن را با یک برچسب نشان میدهد که دستورات آن باید در زمینه vendor init اجرا شوند. هر دستور داخلی init با یک مقدار بولی حاشیهنویسی میشود که مشخص میکند آیا دستور باید در فرآیند فرعی vendor init اجرا شود یا خیر:
- بیشتر دستوراتی که به سیستم فایل دسترسی دارند، طوری حاشیهنویسی شدهاند که در زیرفرآیند vendor init اجرا شوند و بنابراین تحت سیاست SEPolicy vendor init قرار میگیرند.
- بیشتر دستوراتی که بر وضعیت init داخلی تأثیر میگذارند (مثلاً شروع و توقف سرویسها) در فرآیند init عادی اجرا میشوند. این دستورات از اینکه یک اسکریپت فروشنده آنها را برای انجام مدیریت مجوزهای غیر SELinux خود فراخوانی میکند، آگاه میشوند.
حلقه پردازش اصلی init شامل بررسی این است که اگر دستوری برای اجرا در زیرفرآیند فروشنده حاشیهنویسی شده باشد و از یک اسکریپت فروشنده سرچشمه گرفته باشد، آن دستور از طریق ارتباط بین فرآیندی (IPC) به زیرفرآیند فروشنده init ارسال میشود که دستور را اجرا کرده و نتیجه را به init ارسال میکند.
از init فروشنده استفاده کنید
تابع init فروشنده به طور پیشفرض فعال است و محدودیتهای آن برای تمام اسکریپتهای init موجود در پارتیشن /vendor اعمال میشود. تابع init فروشنده باید برای فروشندگانی که اسکریپتهای آنها از قبل به فایلهای سیستمی، ویژگیها و غیره دسترسی ندارند، شفاف باشد.
با این حال، اگر دستورات موجود در یک اسکریپت فروشندهی مشخص، محدودیتهای init فروشنده را نقض کنند، دستورات با شکست مواجه میشوند. دستورات ناموفق دارای خطی در لاگ هسته (قابل مشاهده با 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مختص دستگاه به برچسب جدید اعطا شود.
برای دستگاههایی که قبل از اندروید ۹ عرضه میشوند، میتوان با اضافه کردن ویژگی typeattribute مربوط data_between_core_and_vendor_violators به فایل vendor_init.te مخصوص دستگاه، قوانین neverallows را دور زد.
مکانهای کد
بخش عمدهای از منطق مربوط به IPC آغازگر فروشنده در system/core/init/subcontext.cpp قرار دارد.
جدول دستورات در کلاس BuiltinFunctionMap در system/core/init/builtins.cpp قرار دارد و شامل حاشیهنویسیهایی است که نشان میدهد آیا دستور باید در زیرفرآیند vendor init اجرا شود یا خیر.
SEPolicy مربوط به vendor init در دایرکتوریهای خصوصی ( system/sepolicy/private/vendor_init.te ) و عمومی ( system/sepolicy/public/vendor_init.te ) در system/sepolicy تقسیم شده است.