SELinux नीति बनाना

इस पेज पर, SELinux नीति बनाने का तरीका बताया गया है. SELinux नीति, AOSP की मुख्य नीति (प्लैटफ़ॉर्म) और डिवाइस के हिसाब से बनी नीति (वेंडर) के कॉम्बिनेशन से बनाई जाती है. Android 4.4 से लेकर Android 7.0 तक के लिए, SELinux नीति का बिल्ड फ़्लो, सुरक्षा नीति के सभी फ़्रैगमेंट को मर्ज करता है. इसके बाद, रूट डायरेक्ट्री में मोनोलिथिक फ़ाइलें जनरेट की जाती हैं. इसका मतलब है कि नीति में हर बार बदलाव होने पर, SoC वेंडर और ODM मैन्युफ़ैक्चरर, boot.img (नॉन-A/B डिवाइसों के लिए) या system.img (A/B डिवाइसों के लिए) में बदलाव करते हैं.

Android 8.0 और इसके बाद के वर्शन में, प्लैटफ़ॉर्म और वेंडर की नीति अलग-अलग बनाई जाती है. SoC और ओईएम, नीति में मौजूद उनसे जुड़े हिस्सों को अपडेट कर सकते हैं. साथ ही, अपनी इमेज (जैसे, vendor.img और boot.img) बना सकते हैं. इसके बाद, वे इन इमेज को अपडेट भी कर सकते हैं. ऐसा हर प्लैटफ़ॉर्म के लिए किया जा सकता है.

हालांकि, SELinux नीति की अलग-अलग मॉड्यूल वाली फ़ाइलें /vendor पार्टिशन में सेव होती हैं. इसलिए, init प्रोसेस को सिस्टम और वेंडर पार्टिशन को पहले माउंट करना होता है, ताकि वह उन पार्टिशन से SELinux फ़ाइलें पढ़ सके और उन्हें कर्नेल में लोड करने से पहले, सिस्टम डायरेक्ट्री में मौजूद मुख्य SELinux फ़ाइलों के साथ मर्ज कर सके.

सोर्स फ़ाइलें

SELinux बनाने का लॉजिक इन फ़ाइलों में मौजूद है:

  • external/selinux: यह बाहरी SELinux प्रोजेक्ट है, जिसका इस्तेमाल, HOST कमांड लाइन की सुविधाओं को बनाने के लिए किया जाता है. इन सुविधाओं की मदद से, SELinux नीति और लेबल को कंपाइल किया जाता है.
    • external/selinux/libselinux: Android, बाहरी libselinux प्रोजेक्ट के सिर्फ़ एक सबसेट का इस्तेमाल करता है. साथ ही, उसमें Android के हिसाब से कुछ बदलाव भी करता है. ज़्यादा जानकारी के लिए, external/selinux/README.android देखें.
    • external/selinux/libsepol:
      • chkcon: यह तय करती है कि किसी बाइनरी नीति (होस्ट एक्सीक्यूटेबल) के लिए, सुरक्षा कॉन्टेक्स्ट मान्य है या नहीं.
      • libsepol: यह एक SELinux लाइब्रेरी है, जिसे बाइनरी की सुरक्षा नीतियों (होस्ट स्टैटिक/शेयर की गई लाइब्रेरी, टारगेट स्टैटिक लाइब्रेरी) में बदलाव करने के लिए इस्तेमाल किया जाता है.
    • external/selinux/checkpolicy: यह SELinux नीति के लिए कंपाइलर (होस्ट के लिए एक्सीक्यूटेबल: checkpolicy, checkmodule, और dispol) की तरह काम करती है. यह libsepol पर निर्भर करती है.
  • system/sepolicy: इसमें Android SELinux नीति के मुख्य कॉन्फ़िगरेशन हैं, जिनमें कॉन्टेक्स्ट और नीति फ़ाइलें शामिल हैं. यहां (system/sepolicy/Android.mk) सुरक्षा नीति के बिल्ड का मुख्य लॉजिक भी मौजूद है.

system/sepolicy में मौजूद फ़ाइलों के बारे में ज़्यादा जानकारी के लिए SELinux लागू करने का तरीका जानें.

Android 7.x और इससे पहले के वर्शन

इस सेक्शन में बताया गया है कि Android 7.x और इससे पहले के वर्शन में, SELinux नीति कैसे बनाई जाती है.

Android 7.x और इससे पहले के वर्शन के लिए बिल्ड प्रोसेस

SELinux नीति, AOSP की मुख्य नीति और डिवाइस के हिसाब से किए गए बदलावों को जोड़कर बनाई जाती है. इसके बाद, इस नीति पर नीति कंपाइलर टूल और जांच करने वाले अलग-अलग टूल का इस्तेमाल किया जाता है. डिवाइस के हिसाब से किया गया बदलाव, डिवाइस के हिसाब से बनाई गई Boardconfig.mk फ़ाइल में बताए गएBOARD_SEPOLICY_DIRS वैरिएबल की मदद से किया जाता है. ग्लोबल बिल्ड के इस वैरिएबल में, उन डायरेक्ट्री की सूची होती है जिनमें नीति से जुड़ी अन्य फ़ाइलों को खोजने का क्रम तय होता है.

उदाहरण के लिए, किसी डिवाइस के लिए फ़ाइनल SELinux कॉन्फ़िगरेशन जनरेट करने के लिए, SoC वेंडर और ODM, दोनों एक-एक डायरेक्ट्री जोड़ सकते हैं. इनमें से एक डायरेक्ट्री, SoC के हिसाब से सेटिंग के लिए होगी और दूसरी डायरेक्ट्री, डिवाइस के हिसाब से सेटिंग के लिए:

  • BOARD_SEPOLICY_DIRS += device/SOC/common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy

डिवाइस पर file_contexts.bin जनरेट करने के लिए, system/sepolicy और BOARD_SEPOLICY_DIRS में मौजूद file_contexts फ़ाइलों के कॉन्टेंट को जोड़ा जाता है:

इस इमेज में, Android 7.x के लिए SELinux का बिल्ड लॉजिक दिखाया गया है.

पहली इमेज. SELinux का बिल्ड लॉजिक.

sepolicy फ़ाइल में कई सोर्स फ़ाइलें होती हैं:

  • सादा टेक्स्ट policy.conf, security_classes, initial_sids, *.te फ़ाइलों, genfs_contexts, और port_contexts को इस क्रम में जोड़कर जनरेट की जाती है.
  • हर फ़ाइल (जैसे, security_classes) का कॉन्टेंट, system/sepolicy/ और BOARDS_SEPOLICY_DIRS में मौजूद एक ही नाम वाली फ़ाइलों को जोड़कर बनाई जाती है.
  • policy.conf को सिंटैक्स की जांच के लिए, SELinux कंपाइलर को भेजा जाता है और डिवाइस पर sepolicy के तौर पर बाइनरी फ़ॉर्मैट में कंपाइल किया जाता है.
    इस इमेज में, Android 7.x के लिए SELinux नीति फ़ाइल जनरेट करने में इस्तेमाल की गई फ़ाइलें दिखाई गई हैं.

    दूसरी इमेज. SELinux नीति की फ़ाइल.

SELinux की फ़ाइलें

कंपाइल करने के बाद, Android 7.x और इससे पहले के वर्शन वाले डिवाइसों में आम तौर पर, SELinux से जुड़ी ये फ़ाइलें होती हैं:

  • selinux_version
  • सुरक्षा नीति: नीति से जुड़ी फ़ाइलों को जोड़ने के बाद बाइनरी आउटपुट (जैसे, security_classes, initial_sids, और *.te)
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

ज़्यादा जानकारी के लिए, SELinux लागू करने का तरीका पढ़ें.

SELinux को शुरू करना

SELinux, सिस्टम के चालू होने पर नीति लागू करने वाले मोड के बजाय, नीति लागू न करने वाले मोड में काम करता है. init प्रोसेस ये काम करती है:

  • /sys/fs/selinux/load की मदद से, sepolicy फ़ाइलों को रैमडिस्क से कर्नेल में लोड किया जाता है.
  • SELinux को नीति लागू करने वाले मोड पर स्विच किया जाता है.
  • SELinux डोमेन नियम को खुद पर लागू करने के लिए, re-exec() चलाता है.

सिस्टम चालू होने में लगने वाले समय को कम करने के लिए, re-exec() पर init प्रोसेस को जल्द से जल्द पूरा करें.

Android 8.0 और इसके बाद के वर्शन

Android 8.0 में, SELinux की नीति को प्लैटफ़ॉर्म और वेंडर कॉम्पोनेंट में बांटा गया है. इससे, प्लैटफ़ॉर्म/वेंडर की नीति को अलग-अलग अपडेट किया जा सकता है. साथ ही, डिवाइस के साथ काम करने की सुविधा भी बनी रहती है.

प्लैटफ़ॉर्म की सुरक्षा नीति को प्लैटफ़ॉर्म के निजी और सार्वजनिक हिस्सों में बांटा गया है. इससे, वेंडर नीति लिखने वालों को खास टाइप और एट्रिब्यूट एक्सपोर्ट करने में मदद मिलती है. प्लैटफ़ॉर्म के सार्वजनिक टाइप/एट्रिब्यूट को किसी प्लैटफ़ॉर्म वर्शन के लिए, स्थिर एपीआई के तौर पर बनाए रखने की गारंटी है. प्लैटफ़ॉर्म मैपिंग फ़ाइलों का इस्तेमाल करके, कई वर्शन के लिए प्लैटफ़ॉर्म के पिछले सार्वजनिक टाइप/एट्रिब्यूट के साथ काम करने की गारंटी दी जा सकती है.

Android 8.0 के लिए बिल्ड प्रोसेस

Android 8.0 में SELinux की नीति, /system और /vendor के हिस्सों को मिलाकर बनाई गई है. इसे सही तरीके से सेट अप करने का लॉजिक, /platform/system/sepolicy/Android.mk में दिया गया है.

नीति इन लोकेशन पर मौजूद है:

लोकेशन इसमें शामिल है
system/sepolicy/public प्लैटफ़ॉर्म की सुरक्षा नीति का एपीआई
system/sepolicy/private प्लैटफ़ॉर्म को लागू करने से जुड़ी जानकारी (वेंडर इसे अनदेखा कर सकते हैं)
system/sepolicy/vendor नीति और कॉन्टेक्स्ट फ़ाइलें, जिनका इस्तेमाल वेंडर कर सकते हैं (वेंडर चाहें, तो इन फ़ाइलों को अनदेखा कर सकते हैं)
BOARD_SEPOLICY_DIRS वेंडर की सुरक्षा नीति
BOARD_ODM_SEPOLICY_DIRS (Android 9 और उसके बाद के वर्शन) Odm की सुरक्षा नीति
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 और उसके बाद के वर्शन) System_ext की सुरक्षा नीति का एपीआई
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 और उसके बाद के वर्शन) System_ext को लागू करने से जुड़ी जानकारी (वेंडर इस जानकारी को अनदेखा कर सकते हैं)
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 और उसके बाद के वर्शन) प्रॉडक्ट की सुरक्षा नीति का एपीआई
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 और उसके बाद के वर्शन) प्रॉडक्ट लागू करने की जानकारी (वेंडर इस जानकारी को अनदेखा कर सकते हैं)

इस नीति का इस्तेमाल करके, बिल्ड सिस्टम उससे जुड़े पार्टिशन पर सिस्टम, system_ext, प्रॉडक्ट, वेंडर, और ओडीएम नीति के कॉम्पोनेंट बनाता है. इसमें ये चरण शामिल हैं:

  1. नीतियों को SELinux कॉमन इंटरमीडिएट लैंग्वेज (सीआईएल) फ़ॉर्मैट में बदलना. खास तौर पर ये नीतियां:
    1. सार्वजनिक प्लैटफ़ॉर्म की नीति (सिस्टम + system_ext + प्रॉडक्ट)
    2. निजी और सार्वजनिक नीति दोनों
    3. सार्वजनिक + वेंडर और BOARD_SEPOLICY_DIRS नीति
  2. वेंडर नीति के तहत, सार्वजनिक तौर पर उपलब्ध कराई गई नीति का वर्शन बनाना. इसके लिए, सार्वजनिक CIL नीति का इस्तेमाल किया जाता है, ताकि सार्वजनिक + वेंडर + BOARD_SEPOLICY_DIRS नीति के बारे में यह बताया जा सके कि किन हिस्सों को ऐसे एट्रिब्यूट में बदलना चाहिए जिन्हें प्लैटफ़ॉर्म की नीति से जोड़ा जाएगा.
  3. प्लैटफ़ॉर्म और वेंडर पार्ट को लिंक करने वाली मैपिंग फ़ाइल बनाना. शुरुआत में, यह सिर्फ़ सार्वजनिक नीति के टाइप को, वेंडर नीति में मौजूद उससे मिलते-जुलते एट्रिब्यूट से लिंक करता है. बाद में, इसे आने वाले समय में प्लैटफ़ॉर्म के वर्शन में सेव की जाने वाली फ़ाइल के लिए रेफ़रंस माना जाएगा. इससे, इस प्लैटफ़ॉर्म के वर्शन को टारगेट करने वाली वेंडर नीति के साथ काम करना भी आसान होगा.
  4. नीति से जुड़ी फ़ाइलों को जोड़ना (डिवाइस पर मौजूद और पहले से कंपाइल किए गए समाधान, दोनों).
    1. मैपिंग, प्लैटफ़ॉर्म, और वेंडर की नीति को जोड़ें.
    2. आउटपुट बाइनरी नीति फ़ाइल को कंपाइल करें.

प्लैटफ़ॉर्म की सार्वजनिक सुरक्षा नीति

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

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

प्लैटफ़ॉर्म की निजी सुरक्षा नीति

प्लैटफ़ॉर्म की निजी सुरक्षा नीति में, /system/sepolicy/private में बताई गई सभी बातें शामिल होती हैं. नीति के इस हिस्से में, सिर्फ़ प्लैटफ़ॉर्म के लिए उपलब्ध टाइप, अनुमतियां, और प्लैटफ़ॉर्म की सुविधाओं के लिए ज़रूरी एट्रिब्यूट शामिल होते हैं. इन्हें vendor/device नीति लेखकों के लिए एक्सपोर्ट नहीं किया जाता. नॉन-प्लैटफ़ॉर्म की नीति लिखने वाले लोगों को प्लैटफ़ॉर्म की निजी सुरक्षा नीति में बताए गए टाइप/एट्रिब्यूट/नियमों के आधार पर, अपनी नीति के एक्सटेंशन नहीं लिखने चाहिए. इसके अलावा, सिर्फ़ फ़्रेमवर्क के अपडेट के हिस्से के तौर पर, इन नियमों में बदलाव किया जा सकता है या इन्हें हटाया जा सकता है.

प्लैटफ़ॉर्म की निजी मैपिंग

प्लैटफ़ॉर्म की निजी मैपिंग में नीति के ऐसे स्टेटमेंट शामिल होते हैं जो पिछले प्लैटफ़ॉर्म वर्शन की प्लैटफ़ॉर्म की सार्वजनिक नीति में ज़ाहिर किए गए एट्रिब्यूट, प्लैटफ़ॉर्म की मौजूदा सार्वजनिक नीति में इस्तेमाल किए गए टाइप के साथ मैप करते हैं. इससे यह पक्का होता है कि प्लैटफ़ॉर्म की सार्वजनिक सुरक्षा नीति के पिछले वर्शन के प्लैटफ़ॉर्म के सार्वजनिक एट्रिब्यूट के आधार पर लिखी गई वेंडर नीति काम करती रहेगी. वर्शन, किसी प्लैटफ़ॉर्म वर्शन के लिए AOSP में सेट किए गए PLATFORM_SEPOLICY_VERSION बिल्ड वैरिएबल पर आधारित होता है. प्लैटफ़ॉर्म के हर पिछले वर्शन के लिए, एक अलग मैपिंग फ़ाइल मौजूद होती है. प्लैटफ़ॉर्म को इस मैपिंग फ़ाइल में से वेंडर की नीति स्वीकार करनी होती है. ज़्यादा जानकारी के लिए, नीति के मुताबिक काम करने के बारे में जानें.

Android 11 और उसके बाद के वर्शन

system_ext और प्रॉडक्ट की सुरक्षा नीति

Android 11 में, system_ext नीति और प्रॉडक्ट नीति जोड़ी गई है. प्लैटफ़ॉर्म की सुरक्षा नीति की तरह, system_ext नीति और प्रॉडक्ट नीति को भी सार्वजनिक नीति और निजी नीति में बांटा गया है.

सार्वजनिक नीति, वेंडर को एक्सपोर्ट की जाती है. टाइप और एट्रिब्यूट, स्टेबल एपीआई बन जाते हैं. साथ ही, वेंडर की नीति में सार्वजनिक नीति के टाइप और एट्रिब्यूट का रेफ़रंस दिया जा सकता है. PLATFORM_SEPOLICY_VERSION के हिसाब से, टाइप के वर्शन तय किए जाते हैं. साथ ही, वर्शन वाली नीति को वेंडर की नीति में शामिल किया जाता है. ओरिजनल नीति, system_ext और प्रॉडक्ट के पार्टिशन, दोनों में शामिल होती है.

निजी नीति में, सिर्फ़ system_ext और सिर्फ़ प्रॉडक्ट टाइप, अनुमतियां, और एट्रिब्यूट शामिल होते हैं. ये system_ext और प्रॉडक्ट के पार्टीशन की सुविधाओं के लिए ज़रूरी होते हैं. निजी नीति, वेंडर को नहीं दिखती. इसका मतलब है कि ये नियम इंटरनल हैं और इनमें बदलाव किया जा सकता है.

system_ext और प्रॉडक्ट मैपिंग

system_ext और प्रॉडक्ट के पास, तय किए गए सार्वजनिक टाइप को वेंडर में एक्सपोर्ट करने की अनुमति होती है. हालांकि, हर पार्टनर की यह ज़िम्मेदारी है कि वह अपने प्रॉडक्ट को नीति के मुताबिक बनाए रखे. नीति के मुताबिक काम करने के लिए, पार्टनर अपनी मैपिंग फ़ाइलें उपलब्ध करा सकते हैं. ये फ़ाइलें, पिछले वर्शन के एट्रिब्यूट के वर्शन को मौजूदा सार्वजनिक सुरक्षा नीति में इस्तेमाल किए जाने वाले कंक्रीट टाइप से मैप करती हैं.

  • अगर system_ext के लिए मैपिंग फ़ाइल इंस्टॉल करनी है, तो {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil में मैपिंग जानकारी वाली अपनी पसंद की cil फ़ाइल डालें. इसके बाद, system_ext_{ver}.cil को PRODUCT_PACKAGES में जोड़ें.
  • प्रॉडक्ट के लिए मैपिंग फ़ाइल इंस्टॉल करने के लिए, {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil में अपनी पसंद की मैपिंग जानकारी वाली cil फ़ाइल डालें. इसके बाद, product_{ver}.cil को PRODUCT_PACKAGES में जोड़ें.

उदाहरण देखें, जिसमें redbull डिवाइस के प्रॉडक्ट पार्टीशन की मैपिंग फ़ाइल जोड़ी गई है.

पहले से कंपाइल की गई SELinux नीति

init, SELinux को चालू करने से पहले, init जैसे पार्टीशन (system, system_ext, product, vendor, और odm) से सभी सीआईएल फ़ाइलें इकट्ठा करता है. इसके बाद, उन्हें बाइनरी नीति में कंपाइल करता है, जोकि कर्नेल में लोड किया जा सकने वाला फ़ॉर्मैट है. कंपाइल करने में समय लगता है (आम तौर पर 1-2 सेकंड), इसलिए CIL फ़ाइलों को बिल्ड से पहले ही कंपाइल किया जाता है और इनपुट CIL फ़ाइलों के sha256 हैश के साथ, /vendor/etc/selinux/precompiled_sepolicy या /odm/etc/selinux/precompiled_sepolicy में डाला जाता है. init, रनटाइम के दौरान हैश की तुलना करके, यह जांच करता है कि नीति की कोई फ़ाइल अपडेट हुई है या नहीं. अगर कोई बदलाव नहीं किया गया होता, तो init पहले से कंपाइल की गई नीति को लोड करता है. अगर कोई बदलाव किया गया है, तो init रन किए जाने पर कंपाइल करता है. साथ ही, वह पहले से कंपाइल की गई नीति के बजाय इसका इस्तेमाल करता है.

पहले से कंपाइल की गई नीति का इस्तेमाल खास तौर पर तब किया जाता है, जब ये सभी शर्तें पूरी होती हैं. यहां, {partition} उस पार्टीशन को दिखाता है जहां पहले से कंपाइल की गई नीति मौजूद है: vendor या odm.

  • /system/etc/selinux/plat_sepolicy_and_mapping.sha256 और /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 दोनों मौजूद हैं और एक जैसे हैं.
  • /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 और /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 दोनों मौजूद नहीं हैं. इसके अलावा, हो सकता है कि दोनों मौजूद हों और एक जैसे हों.
  • /product/etc/selinux/product_sepolicy_and_mapping.sha256 और /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 दोनों मौजूद नहीं हैं. इसके अलावा, हो सकता है कि दोनों मौजूद हों और एक जैसे हों.

अगर उनमें से कोई भी अलग होता है, तो init डिवाइस पर मौजूद कंपाइलेशन पाथ का इस्तेमाल करता है. ज़्यादा जानकारी के लिए, system/core/init/selinux.cpp देखें.