वेंडर के लिए शुरू करना

init प्रोसेस के पास लगभग सभी अनुमतियां होती हैं. साथ ही, यह बूट प्रोसेस के दौरान सिस्टम को शुरू करने के लिए, सिस्टम और वेंडर, दोनों के पार्टीशन से इनपुट स्क्रिप्ट का इस्तेमाल करती है. इस ऐक्सेस की वजह से, Treble सिस्टम/वेंडर स्प्लिट में एक बड़ी समस्या आ जाती है. ऐसा इसलिए, क्योंकि वेंडर स्क्रिप्ट, init को ऐसी फ़ाइलों, प्रॉपर्टी वगैरह को ऐक्सेस करने का निर्देश दे सकती हैं जो स्टेबल सिस्टम-वेंडर ऐप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) का हिस्सा नहीं हैं.

Vendor init को इस समस्या को हल करने के लिए डिज़ाइन किया गया है. इसके लिए, यह सुरक्षा को बेहतर बनाने वाले Linux (SELinux) के अलग डोमेन vendor_init का इस्तेमाल करता है. इससे /vendor में मौजूद कमांड को वेंडर के हिसाब से अनुमतियों के साथ चलाया जा सकता है.

मैकेनिज़्म

वेंडर init, बूट प्रोसेस के दौरान init की एक सबप्रोसेस को फ़ोर्क करता है. इसमें SELinux कॉन्टेक्स्ट u:r:vendor_init:s0 होता है. इस SELinux कॉन्टेक्स्ट में, डिफ़ॉल्ट init कॉन्टेक्स्ट की तुलना में काफ़ी कम अनुमतियां होती हैं. साथ ही, इसका ऐक्सेस उन फ़ाइलों, प्रॉपर्टी वगैरह तक सीमित होता है जो वेंडर के हिसाब से तय की जाती हैं या स्टेबल सिस्टम-वेंडर ABI का हिस्सा होती हैं.

Init, लोड की गई हर स्क्रिप्ट की जांच करता है. इससे यह पता चलता है कि उसका पाथ /vendor से शुरू होता है या नहीं. अगर ऐसा होता है, तो वह उसे इस बात का इंडिकेशन देता है कि उसके कमांड वेंडर के init कॉन्टेक्स्ट में चलाए जाने चाहिए. हर init बिल्ट-इन को एक बूलियन से एनोटेट किया जाता है. इससे यह तय होता है कि वेंडर init सबप्रोसेस में कमांड को चलाना ज़रूरी है या नहीं:

  • फ़ाइल सिस्टम को ऐक्सेस करने वाली ज़्यादातर कमांड को, वेंडर के init सबप्रोसेस में चलाने के लिए एनोटेट किया जाता है. इसलिए, ये वेंडर के init SEPolicy के दायरे में आती हैं.
  • इंटरनल इनिट स्टेट पर असर डालने वाले ज़्यादातर कमांड, सामान्य इनिट प्रोसेस के दौरान चलाए जाते हैं. जैसे, सेवाओं को शुरू और बंद करना. इन कमांड को यह पता होता है कि वेंडर स्क्रिप्ट, SELinux के अलावा अन्य अनुमतियों को मैनेज करने के लिए इन्हें कॉल कर रही है.

init के मुख्य प्रोसेसिंग लूप में एक जांच शामिल होती है. अगर किसी कमांड को वेंडर के सबप्रोसेस में चलाने के लिए एनोटेट किया गया है और वह वेंडर स्क्रिप्ट से शुरू होती है, तो उस कमांड को इंटर-प्रोसेस कम्यूनिकेशन (आईपीसी) के ज़रिए वेंडर के init सबप्रोसेस को भेजा जाता है. यह सबप्रोसेस कमांड को चलाता है और नतीजे को वापस init को भेजता है.

वेंडर init का इस्तेमाल करना

वेंडर के लिए, init स्क्रिप्ट डिफ़ॉल्ट रूप से चालू होती है. साथ ही, इस पर लागू होने वाली पाबंदियां, /vendor पार्टीशन में मौजूद सभी 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 नियमों के तहत, सिस्टम फ़ाइलों को ऐक्सेस करने की अनुमतियां जोड़ने से रोका जाता है. ये फ़ाइलें, सिस्टम-वेंडर के स्टेबल एबीआई का हिस्सा नहीं होती हैं.
  • अगर SELinux का लेबल नया है और सिस्टम vendor_init.te में इसे पहले से अनुमतियां नहीं दी गई हैं. साथ ही, इसे कभी अनुमति न देने के नियमों के तहत अनुमतियों से बाहर नहीं रखा गया है, तो नए लेबल को डिवाइस के हिसाब से vendor_init.te में अनुमतियां दी जा सकती हैं.

Android 9 से पहले लॉन्च किए गए डिवाइसों के लिए, neverallows नियमों को बायपास किया जा सकता है. इसके लिए, डिवाइस के हिसाब से तय की गई vendor_init.te फ़ाइल में data_between_core_and_vendor_violators typeattribute जोड़ें.

कोड की जगहें

वेंडर के शुरू किए गए आईपीसी का ज़्यादातर लॉजिक, system/core/init/subcontext.cpp में होता है.

कमांड की टेबल, system/core/init/builtins.cpp में BuiltinFunctionMap क्लास में है. इसमें ऐसे एनोटेशन शामिल हैं जिनसे पता चलता है कि कमांड को वेंडर के init सबप्रोसेस में चलाना ज़रूरी है या नहीं.

वेंडर init के लिए SEPolicy को system/sepolicy में मौजूद निजी (system/sepolicy/private/vendor_init.te) और सार्वजनिक (system/sepolicy/public/vendor_init.te) डायरेक्ट्री में बांटा गया है.