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

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

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

मैकेनिज़्म

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

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

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

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

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

वेंडर init, डिफ़ॉल्ट रूप से चालू होता है. इसकी पाबंदियां, /vendor पार्टीशन में मौजूद सभी init स्क्रिप्ट पर लागू होती हैं. वेंडर init, उन वेंडर के लिए पारदर्शी होना चाहिए जिनकी स्क्रिप्ट, सिर्फ़ सिस्टम की फ़ाइलों, प्रॉपर्टी वगैरह को ऐक्सेस नहीं कर रही हैं.

हालांकि, अगर किसी वेंडर स्क्रिप्ट में मौजूद कमांड, वेंडर init की पाबंदियों का उल्लंघन करते हैं, तो वे काम नहीं करेंगे. काम न करने वाले कमांड के लिए, कर्नल लॉग में init की एक लाइन दिखती है. इसे dmesg की मदद से देखा जा सकता है. इससे पता चलता है कि कमांड काम नहीं कर रहा है. 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 नियमों को बाईपास किया जा सकता है. इसके लिए, डिवाइस के हिसाब से vendor_init.te फ़ाइल में data_between_core_and_vendor_violators टाइप एट्रिब्यूट जोड़ा जा सकता है.

कोड की जगहें

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

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

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