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