init प्रोसेस के पास, बिना किसी पाबंदी वाली अनुमतियां होती हैं. साथ ही, यह बूट प्रोसेस के दौरान सिस्टम को शुरू करने के लिए, सिस्टम और वेंडर, दोनों के पार्टीशन की इनपुट स्क्रिप्ट का इस्तेमाल करती है. इस ऐक्सेस की वजह से, Treble सिस्टम/वेंडर के बंटवारे में काफ़ी गड़बड़ी होती है. ऐसा इसलिए होता है, क्योंकि वेंडर स्क्रिप्ट, init को ऐसी फ़ाइलों, प्रॉपर्टी वगैरह को ऐक्सेस करने का निर्देश दे सकती हैं जो सिस्टम-वेंडर के ऐप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) का हिस्सा नहीं हैं.
वेंडर init को इस खाते को बंद करने के लिए डिज़ाइन किया गया है. इसके लिए, /vendor
में मौजूद निर्देशों को चलाने के लिए, बेहतर सुरक्षा वाले Linux (SELinux) डोमेन vendor_init
का इस्तेमाल किया जाता है. साथ ही, वेंडर के हिसाब से अनुमतियां भी दी जाती हैं.
मैकेनिज़्म
वेंडर 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
partition में मौजूद सभी 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 के हिसाब से फिर से लागू करना होगा. इसके लिए, सिर्फ़ स्टेबल इंटरफ़ेस का इस्तेमाल करें. जैसे, अगर निर्देश किसी सिस्टम फ़ाइल या प्रॉपर्टी को ऐक्सेस कर रहा है. 'कभी अनुमति न दें' नियम, सिस्टम की उन फ़ाइलों को ऐक्सेस करने की अनुमतियां जोड़ने से रोकते हैं जो सिस्टम-वेंडर के एबीआई (ऑब्जेक्ट बाइंडिंग इंटरफ़ेस) का हिस्सा नहीं हैं.
- अगर SELinux लेबल नया है और उसे पहले से ही सिस्टम
vendor_init.te
में अनुमतियां नहीं दी गई हैं या उसे कभी अनुमति न दें नियमों के तहत अनुमतियां नहीं दी गई हैं, तो नए लेबल को डिवाइस के हिसाब सेvendor_init.te
में अनुमतियां दी जा सकती हैं.
Android 9 से पहले लॉन्च होने वाले डिवाइसों के लिए, कभी अनुमति न देने वाले नियमों को बायपास किया जा सकता है. इसके लिए, डिवाइस के हिसाब से बनाई गई vendor_init.te
फ़ाइल में data_between_core_and_vendor_violators
type एट्रिब्यूट जोड़ें.
कोड की जगहें
वेंडर init IPC के लिए ज़्यादातर लॉजिक, system/core/init/subcontext.cpp में मौजूद है.
निर्देशों की टेबल, system/core/init/builtins.cpp में BuiltinFunctionMap
क्लास में होती है. इसमें एनोटेशन शामिल होते हैं, जिनसे पता चलता है कि निर्देश को वेंडर के init सबप्रोसेस में चलाना ज़रूरी है या नहीं.
वेंडर इनिट के लिए SEPolicy को system/sepolicy में मौजूद निजी (system/sepolicy/private/vendor_init.te) और सार्वजनिक (system/sepolicy/public/vendor_init.te) डायरेक्ट्री में बांटा गया है.