नीति के साथ काम करना

इस पेज पर बताया गया है कि Android, प्लैटफ़ॉर्म के ओवर-द-एयर (OTA) अपडेट के दौरान, नीति से जुड़ी समस्याओं को कैसे हल करता है. इन अपडेट में, प्लैटफ़ॉर्म की नई SELinux सेटिंग, वेंडर की पुरानी SELinux सेटिंग से अलग हो सकती हैं.

ऑब्जेक्ट का मालिकाना हक और लेबलिंग

हर ऑब्जेक्ट के लिए मालिकाना हक की जानकारी साफ़ तौर पर दी जानी चाहिए, ताकि प्लैटफ़ॉर्म और वेंडर की नीति को अलग रखा जा सके. उदाहरण के लिए, अगर वेंडर की नीति के लेबल /dev/foo और प्लैटफ़ॉर्म की नीति के लेबल /dev/foo को बाद के ओटीए में शामिल किया जाता है, तो अनपेक्षित व्यवहार होता है. जैसे, अनुरोध को अस्वीकार कर दिया जाता है या बूट फ़ेल हो जाता है. SELinux के लिए, यह लेबलिंग टकराव के तौर पर दिखता है. डिवाइस नोड में सिर्फ़ एक लेबल हो सकता है. यह लेबल, उस लेबल के तौर पर काम करता है जिसे आखिर में लागू किया गया था. इसकी वजह से:

  • जिन प्रोसेस के लिए, लेबल ऐक्सेस करना ज़रूरी है वे संसाधन का ऐक्सेस खो देती हैं.
  • फ़ाइल का ऐक्सेस पाने वाली प्रोसेस काम नहीं कर सकती, क्योंकि गलत डिवाइस नोड बनाया गया था.

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

टाइप/एट्रिब्यूट नेमस्पेसिंग

लेबल के टकराव के अलावा, SELinux टाइप और एट्रिब्यूट के नाम भी टकरा सकते हैं. SELinux, एक ही तरह के टाइप और एट्रिब्यूट के कई एलान की अनुमति नहीं देता. डुप्लीकेट एलान वाली नीति को कंपाइल नहीं किया जा सकता. टाइप और एट्रिब्यूट के नाम के टकराव से बचने के लिए, यह सुझाव दिया जाता है कि वेंडर के सभी एलान, vendor_ प्रीफ़िक्स से शुरू हों. उदाहरण के लिए, वेंडर को type foo, domain; के बजाय type vendor_foo, domain; का इस्तेमाल करना चाहिए.

फ़ाइल का मालिकाना हक

फ़ाइलों के लिए टकराव को रोकना मुश्किल है, क्योंकि प्लैटफ़ॉर्म और वेंडर की नीति, दोनों ही आम तौर पर सभी फ़ाइल सिस्टम के लिए लेबल उपलब्ध कराती हैं. टाइप के नाम रखने के उलट, फ़ाइलों के नेमस्पेसिंग का इस्तेमाल नहीं किया जा सकता, क्योंकि इनमें से कई फ़ाइलें कर्नल बनाता है. इन टकरावों को रोकने के लिए, इस सेक्शन में फ़ाइल सिस्टम के लिए नाम रखने से जुड़े दिशा-निर्देशों का पालन करें. Android 8.0 के लिए, ये सुझाव हैं. इन्हें तकनीकी तौर पर लागू नहीं किया जाता. आने वाले समय में, इन सुझावों को Vendor Test Suite (VTS) के ज़रिए लागू किया जाएगा.

सिस्टम (/system)

सिर्फ़ सिस्टम इमेज को /system कॉम्पोनेंट के लिए लेबल देने चाहिए. जैसे, file_contexts, service_contexts वगैरह. अगर वेंडर की नीति में /system कॉम्पोनेंट के लिए लेबल जोड़े जाते हैं, तो हो सकता है कि सिर्फ़ फ़्रेमवर्क वाला ओटीए अपडेट न किया जा सके.

वेंडर (/vendor)

AOSP की SELinux नीति, vendor पार्टीशन के उन हिस्सों को पहले से लेबल करती है जिनके साथ प्लैटफ़ॉर्म इंटरैक्ट करता है. इससे, प्लैटफ़ॉर्म प्रोसेस के लिए SELinux के नियम लिखे जा सकते हैं, ताकि वे vendor पार्टीशन के हिस्सों से कम्यूनिकेट कर सकें या उन्हें ऐक्सेस कर सकें. उदाहरण:

/कारोबारी या कंपनी का पाथ प्लैटफ़ॉर्म से मिला लेबल लेबल के हिसाब से प्लैटफ़ॉर्म प्रोसेस
/vendor(/.*)? vendor_file फ़्रेमवर्क में मौजूद सभी एचएएल क्लाइंट, ueventd वगैरह.
/vendor/framework(/.*)? vendor_framework_file dex2oat, appdomain वगैरह
/vendor/app(/.*)? vendor_app_file dex2oat, installd, idmap वगैरह
/vendor/overlay(/.*) vendor_overlay_file system_server, zygote, idmap वगैरह

इसलिए, vendor पार्टीशन में मौजूद अतिरिक्त फ़ाइलों को लेबल करते समय, कुछ खास नियमों का पालन करना ज़रूरी है. इन नियमों को neverallows के ज़रिए लागू किया जाता है:

  • vendor_file पार्टिशन में मौजूद सभी फ़ाइलों के लिए, डिफ़ॉल्ट लेबल होना चाहिए.vendor पासथ्रू एचएएल को लागू करने के लिए, प्लैटफ़ॉर्म की नीति के तहत यह ज़रूरी है.
  • वेंडर की नीति के तहत, vendor पार्टीशन में जोड़े गए सभी नए exec_types में vendor_file_type एट्रिब्यूट होना चाहिए. इसे neverallows के ज़रिए लागू किया जाता है.
  • आने वाले समय में प्लैटफ़ॉर्म/फ़्रेमवर्क के अपडेट से जुड़ी समस्याओं से बचने के लिए, vendor पार्टीशन में exec_types के अलावा अन्य फ़ाइलों को लेबल न करें.
  • AOSP से पहचाने गए एक ही प्रोसेस वाले सभी HAL के लिए, लाइब्रेरी की सभी डिपेंडेंसी को same_process_hal_file. के तौर पर लेबल किया जाना चाहिए

Procfs (/proc)

/proc में मौजूद फ़ाइलों को सिर्फ़ genfscon लेबल का इस्तेमाल करके लेबल किया जा सकता है. Android 7.0 में, प्लैटफ़ॉर्म और वेंडर, दोनों की नीति में procfs में मौजूद फ़ाइलों को लेबल करने के लिए genfscon का इस्तेमाल किया जाता था.

सुझाव: सिर्फ़ प्लैटफ़ॉर्म की नीति के लेबल /proc. अगर वेंडर को /proc में मौजूद उन फ़ाइलों को ऐक्सेस करने की ज़रूरत है जिन्हें फ़िलहाल डिफ़ॉल्ट लेबल (proc) के साथ लेबल किया गया है, तो वेंडर की नीति में उन्हें साफ़ तौर पर लेबल नहीं किया जाना चाहिए. इसके बजाय, वेंडर के डोमेन के लिए नियम जोड़ने के लिए, सामान्य proc टाइप का इस्तेमाल किया जाना चाहिए. इससे प्लैटफ़ॉर्म अपडेट, procfs के ज़रिए दिखाए गए आने वाले समय के कर्नल इंटरफ़ेस के साथ काम कर पाते हैं. साथ ही, ज़रूरत के मुताबिक उन्हें साफ़ तौर पर लेबल कर पाते हैं.

Debugfs (/sys/kernel/debug)

Debugfs को file_contexts और genfscon, दोनों में लेबल किया जा सकता है. Android 7.0 से लेकर Android 10 तक, प्लैटफ़ॉर्म और वेंडर, दोनों के लेबल debugfs.

Android 11 में, प्रोडक्शन डिवाइसों पर debugfs को ऐक्सेस या माउंट नहीं किया जा सकता. डिवाइस बनाने वाली कंपनियों को debugfs हटाना चाहिए.

Tracefs (/sys/kernel/debug/tracing)

Tracefs को file_contexts और genfscon, दोनों में लेबल किया जा सकता है. Android 7.0 में, सिर्फ़ प्लैटफ़ॉर्म के लेबल tracefs.

सुझाव: सिर्फ़ प्लैटफ़ॉर्म tracefs लेबल कर सकता है.

Sysfs (/sys)

/sys में मौजूद फ़ाइलों को file_contexts और genfscon, दोनों का इस्तेमाल करके लेबल किया जा सकता है. Android 7.0 में, प्लैटफ़ॉर्म और वेंडर, दोनों sysfs में फ़ाइलों को लेबल करने के लिए genfscon का इस्तेमाल करते हैं.

सुझाव: प्लैटफ़ॉर्म, sysfs नोड को ऐसे लेबल कर सकता है जो डिवाइस के हिसाब से नहीं हैं. इसके अलावा, सिर्फ़ वेंडर के पास फ़ाइलों को लेबल करने का विकल्प होता है.

tmpfs (/dev)

/dev में मौजूद फ़ाइलों को file_contexts में लेबल किया जा सकता है. Android 7.0 में, प्लैटफ़ॉर्म और वेंडर, दोनों की लेबल फ़ाइलें यहां मौजूद होती हैं.

सुझाव: वेंडर सिर्फ़ /dev/vendor फ़ॉर्मैट वाली फ़ाइलों को लेबल कर सकता है. उदाहरण के लिए, /dev/vendor/foo, /dev/vendor/socket/bar.

Rootfs (/)

/ में मौजूद फ़ाइलों को file_contexts में लेबल किया जा सकता है. Android 7.0 में, प्लैटफ़ॉर्म और वेंडर, दोनों की लेबल फ़ाइलें यहां मौजूद हैं.

सुझाव: / में सिर्फ़ सिस्टम को फ़ाइलों को लेबल करने की अनुमति दें.

डेटा (/data)

डेटा को file_contexts और seapp_contexts के कॉम्बिनेशन के ज़रिए लेबल किया जाता है.

सुझाव: वेंडर को /data/vendor के बाहर लेबल करने की अनुमति न दें. सिर्फ़ प्लैटफ़ॉर्म, /data के अन्य हिस्सों को लेबल कर सकता है.

Genfs के लेबल का वर्शन

वेंडर एपीआई लेवल 202504 से, system/sepolicy/compat/plat_sepolicy_genfs_ver.cil में genfscon के साथ असाइन किए गए नए SELinux लेबल, पुराने vendor पार्टिशन के लिए ज़रूरी नहीं हैं. इससे पुराने vendor पार्टीशन में, मौजूदा SEPolicy लागू करने की सुविधा बनी रहती है. इसे Makefile वैरिएबल BOARD_GENFS_LABELS_VERSION से कंट्रोल किया जाता है. यह /vendor/etc/selinux/genfs_labels_version.txt में सेव होता है.

उदाहरण:

  • वेंडर एपीआई लेवल 202404 में, /sys/class/udc नोड को डिफ़ॉल्ट रूप से sysfs के तौर पर लेबल किया जाता है.
  • वेंडर एपीआई लेवल 202504 से, /sys/class/udc को sysfs_udc के तौर पर लेबल किया गया है.

हालांकि, एपीआई लेवल 202404 का इस्तेमाल करने वाले vendor पार्टिशन में /sys/class/udc का इस्तेमाल किया जा सकता है. ऐसा डिफ़ॉल्ट sysfs लेबल या वेंडर के हिसाब से तय किए गए लेबल के साथ किया जा सकता है. /sys/class/udc को बिना किसी शर्त के sysfs_udc के तौर पर लेबल करने से, इन vendor पार्टीशन के साथ काम करने की सुविधा बंद हो सकती है. BOARD_GENFS_LABELS_VERSION को चुनने पर, प्लैटफ़ॉर्म पुराने vendor पार्टीशन के लिए, पिछले लेबल और अनुमतियों का इस्तेमाल करता रहता है.

BOARD_GENFS_LABELS_VERSION, वेंडर एपीआई लेवल से ज़्यादा या इसके बराबर हो सकता है. उदाहरण के लिए, vendor एपीआई लेवल 202404 का इस्तेमाल करने वाले पार्टिशन, BOARD_GENFS_LABELS_VERSION को 202504 पर सेट कर सकते हैं. इससे वे 202504 में पेश किए गए नए लेबल का इस्तेमाल कर पाएंगे. 202504 के लिए खास तौर पर बनाए गए genfs लेबल की सूची देखें.

genfscon नोड को लेबल करते समय, प्लैटफ़ॉर्म को पुराने vendor पार्टीशन का ध्यान रखना चाहिए. साथ ही, ज़रूरत पड़ने पर, प्लैटफ़ॉर्म को फ़ॉलबैक मैकेनिज़्म लागू करने चाहिए, ताकि यह पक्का किया जा सके कि नोड पुराने पार्टीशन के साथ काम करता है. प्लैटफ़ॉर्म, सिर्फ़ प्लैटफ़ॉर्म के लिए उपलब्ध लाइब्रेरी का इस्तेमाल करके, genfs लेबल के वर्शन के बारे में क्वेरी कर सकता है.

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

प्लैटफ़ॉर्म की SELinux नीति को निजी और सार्वजनिक हिस्सों में बांटा गया है. प्लैटफ़ॉर्म की सार्वजनिक नीति में ऐसे टाइप और एट्रिब्यूट शामिल होते हैं जो हमेशा वेंडर एपीआई लेवल के लिए उपलब्ध होते हैं. यह प्लैटफ़ॉर्म और वेंडर के बीच एपीआई के तौर पर काम करता है. यह नीति, वेंडर के लिए नीति बनाने वाले लोगों को उपलब्ध कराई जाती है, ताकि वेंडर, वेंडर की नीति वाली फ़ाइलें बना सकें. जब इन फ़ाइलों को प्लैटफ़ॉर्म की निजी नीति के साथ जोड़ा जाता है, तो डिवाइस के लिए पूरी तरह से काम करने वाली नीति तैयार होती है. प्लैटफ़ॉर्म की सार्वजनिक नीति के बारे में system/sepolicy/public में बताया गया है.

उदाहरण के लिए, वेंडर के कॉन्टेक्स्ट में init प्रोसेस को दिखाने वाले टाइप vendor_init को vendor_init के तहत तय किया गया है:system/sepolicy/public/vendor_init.te

type vendor_init, domain;

वेंडर, टाइप vendor_init का इस्तेमाल करके, नीति के लिए कस्टम नियम लिख सकते हैं:

# Allow vendor_init to set vendor_audio_prop in vendor's init scripts
set_prop(vendor_init, vendor_audio_prop)

किस तरह काम करता है

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

नीति में ज़्यादातर मौजूदा टाइप के बारे में बताया गया है. यहां vendor_init और debugfs, दोनों टाइप हैं:

allow vendor_init debugfs:dir { mounton };

यह इसलिए काम करता है, क्योंकि नीति को सभी तरह की जानकारी के साथ लिखा गया था. हालांकि, अगर वेंडर की नीति और प्लैटफ़ॉर्म की नीति में खास तरह के टाइप का इस्तेमाल किया जाता है और किसी ऑब्जेक्ट का लेबल सिर्फ़ एक नीति में बदलता है, तो दूसरी नीति में ऐसी नीति शामिल हो सकती है जिस पर पहले भरोसा किया गया था या जिसका ऐक्सेस खो गया था. उदाहरण के लिए, मान लें कि प्लैटफ़ॉर्म की नीति, sysfs नोड को sysfs के तौर पर लेबल करती है:

/sys(/.*)? u:object_r:sysfs:s0

वेंडर की नीति के तहत, /sys/usb का ऐक्सेस मिलता है. इसे sysfs के तौर पर लेबल किया जाता है:

allow vendor_init sysfs:chr_file rw_file_perms;

अगर प्लैटफ़ॉर्म की नीति में बदलाव करके, /sys/usb को sysfs_usb के तौर पर लेबल किया जाता है, तो वेंडर की नीति में कोई बदलाव नहीं होता. हालांकि, नई sysfs_usb टाइप के लिए नीति न होने की वजह से, vendor_init को /sys/usb का ऐक्सेस नहीं मिलता:

/sys/usb u:object_r:sysfs_usb:s0

इस समस्या को हल करने के लिए, Android ने वर्शन वाले एट्रिब्यूट का कॉन्सेप्ट पेश किया है. कंपाइल करने के समय, बिल्ड सिस्टम वेंडर नीति में इस्तेमाल किए गए प्लैटफ़ॉर्म के सार्वजनिक टाइप को, वर्शन वाले इन एट्रिब्यूट में अपने-आप बदल देता है. यह अनुवाद, मैपिंग फ़ाइलों की मदद से किया जाता है. ये फ़ाइलें, वर्शन वाले एट्रिब्यूट को प्लैटफ़ॉर्म के एक या उससे ज़्यादा सार्वजनिक टाइप से जोड़ती हैं.

उदाहरण के लिए, मान लें कि 202504 की प्लैटफ़ॉर्म नीति में /sys/usb को sysfs के तौर पर लेबल किया गया है. साथ ही, 202504 की वेंडर नीति में vendor_init को /sys/usb का ऐक्सेस दिया गया है. इस मामले में:

  • वेंडर नीति, नियम allow vendor_init sysfs:chr_file rw_file_perms; लिखती है, क्योंकि 202504 प्लैटफ़ॉर्म की नीति में /sys/usb को sysfs के तौर पर लेबल किया गया है. बिल्ड सिस्टम, वेंडर की नीति को कंपाइल करते समय, नियम को अपने-आप allow vendor_init_202504 sysfs_202504:chr_file rw_file_perms; में बदल देता है. vendor_init_202504 और sysfs_202504 एट्रिब्यूट, vendor_init और sysfs टाइप के होते हैं. ये टाइप, प्लैटफ़ॉर्म तय करता है.
  • बिल्ड सिस्टम, पहचान की मैपिंग वाली फ़ाइल /system/etc/selinux/mapping/202504.cil जनरेट करता है. system और vendor, दोनों पार्टीशन में 202504 के एक ही वर्शन का इस्तेमाल किया जाता है. इसलिए, मैपिंग फ़ाइल में type_202504 से type तक की पहचान की मैपिंग शामिल होती है. उदाहरण के लिए, vendor_init_202504 को vendor_init पर मैप किया गया है और sysfs_202504 को sysfs पर मैप किया गया है:
    (typeattributeset sysfs_202504 (sysfs))
    (typeattributeset vendor_init_202504 (vendor_init))
    ...

जब वर्शन 202504 से 202604 पर अपडेट होता है, तब 202504 vendor पार्टिशन के लिए नई मैपिंग फ़ाइल system/sepolicy/private/compat/202504/202504.cil में बनाई जाती है. इसे 202604 या नए system पार्टिशन के लिए /system/etc/selinux/mapping/202504.cil में इंस्टॉल किया जाता है. शुरुआत में, इस मैपिंग फ़ाइल में पहचान से जुड़ी मैपिंग होती हैं, जैसा कि पहले बताया गया है. अगर 202604 प्लैटफ़ॉर्म की नीति में /sys/usb के लिए नया लेबल sysfs_usb जोड़ा जाता है, तो मैपिंग फ़ाइल को अपडेट किया जाता है, ताकि sysfs_202504 को sysfs_usb पर मैप किया जा सके:

(typeattributeset sysfs_202504 (sysfs sysfs_usb))
(typeattributeset vendor_init_202504 (vendor_init))
...

इस अपडेट की मदद से, बदले गए वेंडर नीति के नियम allow vendor_init_202504 sysfs_202504:chr_file rw_file_perms; के तहत, नए sysfs_usb टाइप को अपने-आप vendor_init का ऐक्सेस मिल जाता है.

vendor के पुराने वर्शन के साथ काम करने के लिए, जब भी कोई नया सार्वजनिक टाइप जोड़ा जाता है, तो उस टाइप को मैपिंग फ़ाइल system/sepolicy/private/compat/ver/ver.cil में, वर्शन वाले कम से कम एक एट्रिब्यूट से मैप किया जाना चाहिए. इसके अलावा, उसे system/sepolicy/private/compat/ver/ver.ignore.cil में भी शामिल किया जाना चाहिए, ताकि यह बताया जा सके कि वेंडर के पिछले वर्शन में कोई मैचिंग टाइप नहीं है.

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

system_ext की सार्वजनिक नीति और प्रॉडक्ट की सार्वजनिक नीति

Android 11 से, system_ext और product पार्टीशन को, तय किए गए सार्वजनिक टाइप को vendor पार्टीशन में एक्सपोर्ट करने की अनुमति है. प्लैटफ़ॉर्म की सार्वजनिक नीति की तरह, वेंडर की नीति में भी टाइप और नियमों का इस्तेमाल किया जाता है. इन्हें वर्शन वाले एट्रिब्यूट में अपने-आप अनुवादित कर दिया जाता है. उदाहरण के लिए, type से type_ver में, जहां ver, vendor पार्टीशन का वेंडर एपीआई लेवल है.

जब system_ext और product पार्टीशन, एक ही प्लैटफ़ॉर्म वर्शन ver पर आधारित होते हैं, तो बिल्ड सिस्टम, system_ext/etc/selinux/mapping/ver.cil और product/etc/selinux/mapping/ver.cil के लिए बेस मैपिंग फ़ाइलें जनरेट करता है. इनमें type से type_ver तक की आइडेंटिटी मैपिंग होती हैं. वेंडर की नीति, वर्शन किए गए एट्रिब्यूट type_ver के साथ type को ऐक्सेस कर सकती है.

अगर सिर्फ़ system_ext और product पार्टीशन अपडेट किए जाते हैं, जैसे कि ver से ver+1 (या बाद में), जबकि vendor पार्टीशन ver पर रहता है, तो हो सकता है कि वेंडर की नीति को system_ext और product पार्टीशन के टाइप का ऐक्सेस न मिले. ब्रेकेज से बचने के लिए, system_ext और product पार्टीशन को, कॉन्क्रीट टाइप से type_ver एट्रिब्यूट में मैपिंग फ़ाइलें उपलब्ध करानी चाहिए. अगर कोई पार्टनर ver+1 (या बाद के वर्शन) system_ext और product पार्टीशन के साथ ver vendor पार्टीशन का इस्तेमाल करता है, तो उसकी यह ज़िम्मेदारी है कि वह मैपिंग फ़ाइलों को अपडेट करता रहे.

डिवाइस लागू करने वाली कंपनियों या वेंडर को system_ext और product पार्टीशन में मैपिंग फ़ाइलें इंस्टॉल करने के लिए, यह काम करना होगा:

  1. जनरेट की गई बेस मैपिंग फ़ाइलों को ver system_ext और product पार्टीशन से उनके सोर्स ट्री में कॉपी करें.
  2. ज़रूरत के मुताबिक, मैपिंग फ़ाइलों में बदलाव करें.
  3. ver+1 (या इसके बाद के वर्शन) system_ext और product पार्टीशन में, मैपिंग फ़ाइलें इंस्टॉल करें.

उदाहरण के लिए, मान लें कि 202504 system_ext पार्टीशन में foo_type नाम का एक सार्वजनिक टाइप है. इसके बाद, 202504 system_ext पार्टीशन में यह इस तरह दिखेगा:system_ext/etc/selinux/mapping/202504.cil

(typeattributeset foo_type_202504 (foo_type))
(expandtypeattribute foo_type_202504 true)
(typeattribute foo_type_202504)

अगर bar_type को 202604 system_ext में जोड़ा जाता है और अगर 202504 vendor पार्टीशन के लिए bar_type को foo_type पर मैप किया जाना चाहिए, तो 202504.cil को (typeattributeset foo_type_202504 (foo_type)) से (typeattributeset foo_type_202504 (foo_type bar_type)) पर अपडेट किया जा सकता है. इसके बाद, इसे 202604 system_ext पार्टीशन में इंस्टॉल किया जा सकता है. 202504 vendor पार्टीशन, 202604 system_ext के foo_type और bar_type को ऐक्सेस कर सकता है.

Android 9 के लिए एट्रिब्यूट में हुए बदलाव

Android 9 पर अपग्रेड किए जा रहे डिवाइसों पर इन एट्रिब्यूट का इस्तेमाल किया जा सकता है. हालांकि, Android 9 के साथ लॉन्च होने वाले डिवाइसों पर इनका इस्तेमाल नहीं किया जाना चाहिए.

नीति का उल्लंघन करने वाले एट्रिब्यूट

Android 9 में, डोमेन से जुड़े ये एट्रिब्यूट शामिल हैं:

  • data_between_core_and_vendor_violators. यह एट्रिब्यूट उन सभी डोमेन के लिए है जो vendor और coredomains के बीच पाथ के हिसाब से फ़ाइलें शेयर न करने की ज़रूरी शर्त का उल्लंघन करते हैं. प्लैटफ़ॉर्म और वेंडर प्रोसेस को कम्यूनिकेट करने के लिए, डिस्क पर मौजूद फ़ाइलों का इस्तेमाल नहीं करना चाहिए (अस्थिर ABI). सुझाव:
    • वेंडर कोड के लिए /data/vendor का इस्तेमाल किया जाना चाहिए.
    • सिस्टम को /data/vendor का इस्तेमाल नहीं करना चाहिए.
  • system_executes_vendor_violators. ऐसे सभी सिस्टम डोमेन (init और shell domains को छोड़कर) के लिए एट्रिब्यूट जो वेंडर बाइनरी को एक्ज़ीक्यूट न करने की ज़रूरी शर्त का उल्लंघन करते हैं. वेंडर के बाइनरी फ़ाइलों को चलाने के लिए, एपीआई का इस्तेमाल किया जाता है. हालांकि, यह एपीआई स्टेबल नहीं है. प्लैटफ़ॉर्म को वेंडर बाइनरी को सीधे तौर पर लागू नहीं करना चाहिए. सुझाव:
    • वेंडर बाइनरी पर प्लैटफ़ॉर्म की ऐसी निर्भरताएँ, HIDL HAL के पीछे होनी चाहिए.

      या

    • coredomains को वेंडर बाइनरी का ऐक्सेस चाहिए. इसलिए, उन्हें vendor पार्टीशन में ले जाना चाहिए. इससे वे coredomain नहीं रहेंगे.

भरोसेमंद नहीं माने गए एट्रिब्यूट

भरोसेमंद न होने वाले ऐसे ऐप्लिकेशन को HwBinder सेवाओं का ऐक्सेस नहीं मिलना चाहिए जो मनमाना कोड होस्ट करते हैं. हालांकि, ऐसे ऐप्लिकेशन को उन सेवाओं का ऐक्सेस मिल सकता है जिन्हें इन ऐप्लिकेशन के लिए सुरक्षित माना जाता है (नीचे सुरक्षित सेवाओं के बारे में जानें). इसकी दो मुख्य वजहें हैं:

  1. HwBinder सर्वर, क्लाइंट की पुष्टि नहीं करते हैं, क्योंकि HIDL फ़िलहाल कॉलर के यूआईडी की जानकारी नहीं दिखाता है. भले ही, HIDL इस तरह का डेटा दिखाता हो, लेकिन कई HwBinder सेवाएं या तो ऐप्लिकेशन के लेवल से नीचे काम करती हैं (जैसे, HAL) या उन्हें अनुमति के लिए ऐप्लिकेशन की पहचान पर भरोसा नहीं करना चाहिए. इसलिए, सुरक्षित रहने के लिए डिफ़ॉल्ट रूप से यह मान लिया जाता है कि हर HwBinder सेवा, अपने सभी क्लाइंट को सेवा की ओर से उपलब्ध कराए गए ऑपरेशन करने के लिए समान रूप से अधिकृत मानती है.
  2. एचएएल सर्वर (HwBinder सेवाओं का सबसेट) में system/core कॉम्पोनेंट की तुलना में, सुरक्षा से जुड़ी समस्याओं की दर ज़्यादा होती है. साथ ही, इनके पास स्टैक की निचली लेयर (हार्डवेयर तक) का ऐक्सेस होता है. इसलिए, Android के सुरक्षा मॉडल को बायपास करने की संभावनाएं बढ़ जाती हैं.

सुरक्षित सेवाएं

सुरक्षित सेवाओं में ये शामिल हैं:

  • same_process_hwservice. इन सेवाओं को क्लाइंट की प्रोसेस में चलाया जाता है. इसलिए, इनके पास उस क्लाइंट डोमेन का ऐक्सेस होता है जिसमें प्रोसेस चलती है.
  • coredomain_hwservice. इन सेवाओं से, दूसरी वजह से जुड़े जोखिम नहीं होते.
  • hal_configstore_ISurfaceFlingerConfigs. इस सेवा को खास तौर पर किसी भी डोमेन के लिए डिज़ाइन किया गया है.
  • hal_graphics_allocator_hwservice. ये कार्रवाइयां surfaceflinger Binder सेवा भी उपलब्ध कराती है. ऐप्लिकेशन को इसे ऐक्सेस करने की अनुमति है.
  • hal_omx_hwservice. यह mediacodec Binder सेवा का HwBinder वर्शन है. ऐप्लिकेशन को इसे ऐक्सेस करने की अनुमति है.
  • hal_codec2_hwservice. यह hal_omx_hwservice का नया वर्शन है.

इस्तेमाल किए जा सकने वाले एट्रिब्यूट

जिन hwservices को सुरक्षित नहीं माना जाता है उनमें untrusted_app_visible_hwservice एट्रिब्यूट होता है. इससे जुड़े एचएएल सर्वर में untrusted_app_visible_halserver एट्रिब्यूट होता है. Android 9 के साथ लॉन्च होने वाले डिवाइसों में, untrusted एट्रिब्यूट का इस्तेमाल नहीं किया जाना चाहिए.

सुझाव:

  • भरोसेमंद न होने वाले ऐप्लिकेशन को, सिस्टम सेवा से कम्यूनिकेट करना चाहिए. यह सेवा, वेंडर एचआईडीएल एचएएल से कम्यूनिकेट करती है. उदाहरण के लिए, ऐप्लिकेशन binderservicedomain से बात कर सकते हैं. इसके बाद, binderservicedomain (जो कि binderservicedomain है) hal_graphics_allocator से बात करता है.mediaserver

    या

  • जिन ऐप्लिकेशन को vendor HAL का डायरेक्ट ऐक्सेस चाहिए उनके पास वेंडर के तय किए गए अपने सेपोलिसी डोमेन होने चाहिए.

फ़ाइल एट्रिब्यूट की जांच

Android 9 में बिल्ड टाइम टेस्ट शामिल हैं. इनसे यह पक्का किया जाता है कि खास जगहों पर मौजूद सभी फ़ाइलों में सही एट्रिब्यूट मौजूद हों. जैसे, sysfs में मौजूद सभी फ़ाइलों में ज़रूरी sysfs_type एट्रिब्यूट मौजूद हो.

SELinux कॉन्टेक्स्ट लेबलिंग

प्लैटफ़ॉर्म और वेंडर sepolicy के बीच अंतर बनाए रखने के लिए, सिस्टम SELinux कॉन्टेक्स्ट फ़ाइलों को अलग-अलग तरीके से बनाता है, ताकि उन्हें अलग रखा जा सके.

फ़ाइल के कॉन्टेक्स्ट

Android 8.0 में, file_contexts के लिए ये बदलाव किए गए हैं:

  • बूट के दौरान डिवाइस पर कंपाइलेशन का अतिरिक्त ओवरहेड कम करने के लिए, file_contexts बाइनरी फ़ॉर्म में मौजूद नहीं होना चाहिए. इसके बजाय, ये रेगुलर एक्सप्रेशन टेक्स्ट फ़ाइलें होती हैं, जैसे कि {property, service}_contexts (जैसा कि 7.0 से पहले था).
  • file_contexts को दो फ़ाइलों में बांटा गया है:
    • plat_file_contexts
      • Android प्लैटफ़ॉर्म file_context, जिसमें डिवाइस के हिसाब से कोई लेबल नहीं होता. हालांकि, /vendor पार्टीशन के कुछ हिस्सों को लेबल करना ज़रूरी है, ताकि sepolicy फ़ाइलें ठीक से काम कर सकें.
      • यह डिवाइस पर /system/etc/selinux/plat_file_contexts में system पार्टिशन में मौजूद होना चाहिए. साथ ही, इसे init को शुरू में वेंडर file_context के साथ लोड करना चाहिए.
    • vendor_file_contexts
      • डिवाइस के हिसाब से file_context, डिवाइस की Boardconfig.mk फ़ाइलों में मौजूद BOARD_SEPOLICY_DIRS से पॉइंट की गई डायरेक्ट्री में मौजूद file_contexts को मिलाकर बनाया जाता है.
      • इसे vendor पार्टिशन में /vendor/etc/selinux/vendor_file_contexts पर इंस्टॉल किया जाना चाहिए. साथ ही, इसे init को शुरू में प्लैटफ़ॉर्म file_context के साथ लोड करना चाहिए.

प्रॉपर्टी के कॉन्टेक्स्ट

Android 8.0 में, property_contexts को दो फ़ाइलों में बांटा गया है:

  • plat_property_contexts
    • Android प्लैटफ़ॉर्म property_context जिसमें डिवाइस के हिसाब से कोई लेबल नहीं है.
    • यह system पार्टिशन में /system/etc/selinux/plat_property_contexts पर मौजूद होना चाहिए. साथ ही, इसे init को शुरू में वेंडर property_contexts के साथ लोड करना चाहिए.
  • vendor_property_contexts
    • डिवाइस के हिसाब से property_context, डिवाइस की Boardconfig.mk फ़ाइलों में मौजूद BOARD_SEPOLICY_DIRS से पॉइंट की गई डायरेक्ट्री में मौजूद property_contexts को मिलाकर बनाया जाता है.
    • यह vendor पार्टिशन में /vendor/etc/selinux/vendor_property_contexts पर मौजूद होना चाहिए. साथ ही, इसे प्लैटफ़ॉर्म property_context के साथ-साथ init को शुरू में लोड करना चाहिए

सेवा के संदर्भ

Android 8.0 में, service_contexts को इन फ़ाइलों में बांटा गया है:

  • plat_service_contexts
    • Android प्लैटफ़ॉर्म के लिए, servicemanager के लिए service_context. service_context में डिवाइस के हिसाब से कोई लेबल नहीं है.
    • यह system पार्टिशन में /system/etc/selinux/plat_service_contexts पर मौजूद होना चाहिए. साथ ही, इसे वेंडर service_contexts के साथ शुरू में servicemanager लोड करना चाहिए.
  • vendor_service_contexts
    • डिवाइस के हिसाब से service_context, डिवाइस की Boardconfig.mk फ़ाइलों में मौजूद BOARD_SEPOLICY_DIRS से पॉइंट की गई डायरेक्ट्री में मौजूद service_contexts को मिलाकर बनाया जाता है.
    • इसे vendor पार्टिशन में /vendor/etc/selinux/vendor_service_contexts पर मौजूद होना चाहिए. साथ ही, इसे प्लैटफ़ॉर्म service_contexts के साथ-साथ servicemanager की शुरुआत में लोड किया जाना चाहिए.
    • हालांकि, servicemanager डिवाइस चालू होने के दौरान इस फ़ाइल को ढूंढता है, लेकिन TREBLE के सभी नियमों का पालन करने वाले डिवाइस में vendor_service_contexts मौजूद नहीं होना चाहिए. ऐसा इसलिए है, क्योंकि vendor और system के बीच होने वाले सभी इंटरैक्शन, hwservicemanager/hwbinder के ज़रिए होने चाहिए.
  • plat_hwservice_contexts
    • Android प्लैटफ़ॉर्म hwservice_context के लिए hwservicemanager, जिसमें डिवाइस के हिसाब से कोई लेबल नहीं है.
    • यह system पार्टीशन में /system/etc/selinux/plat_hwservice_contexts पर मौजूद होना चाहिए. साथ ही, इसे vendor_hwservice_contexts के साथ शुरू में hwservicemanager लोड करना चाहिए.
  • vendor_hwservice_contexts
    • डिवाइस के हिसाब से hwservice_context, डिवाइस की Boardconfig.mk फ़ाइलों में मौजूद BOARD_SEPOLICY_DIRS से पॉइंट की गई डायरेक्ट्री में मौजूद hwservice_contexts को मिलाकर बनाया जाता है.
    • यह vendor पार्टीशन में /vendor/etc/selinux/vendor_hwservice_contexts पर मौजूद होना चाहिए. साथ ही, इसे plat_service_contexts के साथ-साथ hwservicemanager से शुरू में लोड किया जाना चाहिए.
  • vndservice_contexts
    • डिवाइस के हिसाब से service_context, डिवाइस के Boardconfig.mk में मौजूद BOARD_SEPOLICY_DIRS से पॉइंट की गई डायरेक्ट्री में मौजूद vndservice_contexts को मिलाकर बनाए गए vndservicemanager के लिए.
    • यह फ़ाइल, vendor पार्टिशन में /vendor/etc/selinux/vndservice_contexts पर मौजूद होनी चाहिए. साथ ही, इसे vndservicemanager को शुरू में लोड करना चाहिए.

Seapp कॉन्टेक्स्ट

Android 8.0 में, seapp_contexts को दो फ़ाइलों में बांटा गया है:

  • plat_seapp_contexts
    • Android प्लैटफ़ॉर्म seapp_context, जिसमें डिवाइस के हिसाब से कोई बदलाव नहीं किया गया है.
    • system पार्टिशन में /system/etc/selinux/plat_seapp_contexts. पर मौजूद होना चाहिए
  • vendor_seapp_contexts
    • डिवाइस के हिसाब से प्लैटफ़ॉर्म seapp_context के लिए बनाया गया एक्सटेंशन. इसे डिवाइस की Boardconfig.mk फ़ाइलों में मौजूद BOARD_SEPOLICY_DIRS से पॉइंट की गई डायरेक्ट्री में मौजूद seapp_contexts को मिलाकर बनाया गया है.
    • vendor पार्टिशन में /vendor/etc/selinux/vendor_seapp_contexts पर मौजूद होना चाहिए.

MAC पते से जुड़ी अनुमतियां

Android 8.0 में, mac_permissions.xml को दो फ़ाइलों में बांटा गया है:

  • प्लैटफ़ॉर्म mac_permissions.xml
    • Android प्लैटफ़ॉर्म mac_permissions.xml, जिसमें डिवाइस के हिसाब से कोई बदलाव नहीं किया गया है.
    • system पार्टिशन में /system/etc/selinux/. पर मौजूद होना चाहिए
  • प्लैटफ़ॉर्म से बाहर mac_permissions.xml
    • डिवाइस के हिसाब से प्लैटफ़ॉर्म का एक्सटेंशन mac_permissions.xml से बनाया गया mac_permissions.xml, डिवाइस की Boardconfig.mk फ़ाइलों में मौजूद BOARD_SEPOLICY_DIRS से पॉइंट की गई डायरेक्ट्री में मिला.
    • vendor पार्टिशन में /vendor/etc/selinux/. पर मौजूद होना चाहिए

Android 17 के लिए, शेयर की गई मेमोरी में हुए बदलाव

Android 17 और इसके बाद के वर्शन के साथ लॉन्च होने वाले डिवाइसों में, यहां दी गई प्रॉपर्टी होनी चाहिए. साथ ही, उनमें memfd_class नीति की सुविधा चालू होनी चाहिए. इसके अलावा, उन्हें शेयर की गई मेमोरी से जुड़ी नीति को अपडेट करना होगा, ताकि memfd_file क्लास ऑब्जेक्ट काम कर सकें:

  • वेंडर एपीआई लेवल 202604 या उसके बाद के वर्शन वाले Automotive चिपसेट के लिए:memfd इससे मौजूदा डिवाइसों को Android के नए वर्शन पर अपग्रेड किया जा सकता है. इसके लिए, वेंडर के सेगमेंट को अपडेट करने की ज़रूरत नहीं होती.
  • android16-6.12 या इससे ऊपर का कर्नल होना चाहिए, क्योंकि ये कर्नल memfd_class सुविधा के साथ काम करते हैं. यह सुविधा, memfd के लिए फ़ाइन-ग्रेन्ड नीति लागू करने के लिए ज़रूरी है.

memfd_class नीति की सुविधा चालू करना

हाल ही में, SELinux ने memfd को एक ऐसी फ़ाइल के तौर पर लेबल किया था जिसका टाइप, उसके बैकिंग फ़ाइल सिस्टम–-tmpfs के जैसा था. इस वजह से, नीति के नज़रिए से, tmpfs माउंट पर मौजूद किसी memfd को दूसरी फ़ाइल से अलग करना मुमकिन नहीं था. अब SELinux, memfd को प्रोसेस के सुरक्षा कॉन्टेक्स्ट के साथ लेबल करता है. साथ ही, memfds को memfd_file क्लास ऑब्जेक्ट के तौर पर माना जाता है. इस फ़ंक्शन को memfd_class नीति की क्षमता से सुरक्षित किया जाता है, ताकि पुराने यूज़रस्पेस एनवायरमेंट के साथ बैकवर्ड कंपैटिबिलिटी बनी रहे.

memfd_class नीति लागू करने की सुविधा चालू करने के लिए, BOARD_VENDOR_SEPOLICY_DIRS में जाकर policy_capabilities फ़ाइल बनाएं. फ़ाइल में यह एंट्री होनी चाहिए:

# $BOARD_VENDOR_SEPOLICY_DIRS/*/policy_capabilities
policycap memfd_class;

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

पुष्टि करें कि memfd_class नीति की सुविधा चालू हो

memfd_class नीति की सुविधा का स्टेटस देखने के लिए, इस निर्देश का इस्तेमाल करें:

adb shell 'cat /sys/fs/selinux/policy_capabilities/memfd_class'

अगर नतीजा 1 है, तो memfd_class नीति की सुविधा चालू हो जाती है. ऐसा न करने पर, यह सुविधा चालू नहीं होती.

मौजूदा नीति को memfd पर ले जाना

कुछ प्रोसेस, अपनी नीति में tmpfs_domain() मैक्रो का इस्तेमाल करती हैं, ताकि वे अपने memfds को ऐक्सेस कर सकें और उन्हें नेमस्पेस कर सकें. उदाहरण के लिए:

# foo.te
tmpfs_domain(foo)

इसका मतलब यह है:

# foo.te
type_transition foo tmpfs:file foo_tmpfs;
allow foo foo_tmpfs:file { read write getattr map };

और प्रोसेस bar को प्रोसेस foo के memfds को इस तरह ऐक्सेस करने की अनुमति देता है:

# bar.te
allow bar foo_tmpfs:file { read write getattr map };

memfd_class नीति की सुविधा चालू होने पर, tmpfs_domain() मैक्रो की अब ज़रूरत नहीं है. ऐसा इसलिए है, क्योंकि प्लैटफ़ॉर्म की नीति को अपडेट कर दिया गया है. इससे कोई भी प्रोसेस अपना memfds बना सकती है और उसका इस्तेमाल कर सकती है. इसके बारे में यहां बताया गया है:

# system/sepolicy/private/domain.te
allow domain self:memfd_file { create read write getattr map };

और प्रोसेस foo से बनाए गए memfds को प्रोसेस bar इस तरह से ऐक्सेस कर सकती है:

# bar.te
allow bar foo:memfd_file { read write getattr map };

प्लैटफ़ॉर्म की नीति को अपडेट किया गया है, ताकि memfd के मौजूदा इस्तेमाल को ध्यान में रखा जा सके. हालांकि, वेंडर और डिवाइस के हिसाब से बनी ऐसी नीति को अपडेट करना होगा जिसमें tmpfs लेबल का इस्तेमाल किया गया है, ताकि memfd_file का इस्तेमाल किया जा सके. अगर नीति को ऐसे SoCs या डिवाइसों के साथ शेयर किया जाता है जिनमें वेंडर एपीआई लेवल 202604 या उसके बाद का वर्शन नहीं है, तो हमारा सुझाव है कि कंपैटिबिलिटी के लिए, नई memfd_file नीति के साथ-साथ लेगसी tmpfs नीति को भी बनाए रखा जाए.

memfd से जुड़े एवीसी डेनियल की पहचान करना

Memfd से जुड़े अस्वीकार किए गए अनुरोधों को वापस पाने के लिए, इस कमांड का इस्तेमाल करें:

adb shell logcat -d -b events | grep memfd

avc denials with tmpfs as the target

यहां दिए गए उदाहरण में, avc के लिए अनुमति न मिलने की जानकारी दी गई है. ऐसा तब हुआ, जब किसी प्रोसेस ने ऐसे memfd में डेटा लिखने की कोशिश की जिसके लिए उसके पास अनुमति नहीं थी:

audit(0.0:539): avc:  denied  { write } for  comm="binder:665_1" name="memfd:MessageQueue"
dev="tmpfs" ino=8324 scontext=u:r:mediacodec:s0 tcontext=u:object_r:tmpfs:s0 tclass=file
permissive=0

memfd_class नीति की सुविधा चालू होने पर, memfd का टारगेट कॉन्टेक्स्ट, tmpfs नहीं, बल्कि सुरक्षा के लिए कॉन्टेक्स्ट असाइन करने की प्रोसेस होती है. साथ ही, टारगेट क्लास file नहीं, बल्कि memfd_file होती है. इसलिए, अगर आपको memfd से जुड़े avc अस्वीकार किए जा रहे हैं और सवाल में मौजूद memfd को tmpfs फ़ाइल के तौर पर लेबल किया गया है, तो इसका मतलब है कि memfd_class नीति की सुविधा चालू नहीं है.

avc denials with memfd_file as the target class

यहां दिए गए उदाहरण में, avc के ऐक्सेस से इनकार करने की जानकारी दी गई है. ऐसा तब होता है, जब कोई प्रोसेस ऐसे memfd में लिखने की कोशिश करती है जिसमें लिखने की अनुमति नहीं है. साथ ही, memfd_class नीति की केपबिलिटी चालू है. इसके अलावा, एक और लाइन दी गई है, जिसे ऐक्सेस से इनकार करने के बाद logd उसी टाइमस्‍टैंप के साथ दिखाता है:

audit(0.0:86): avc: denied { read } for
path=2F6D656D66643A4D6564696142756666657247726F7570202864656C6574656429 ino=512 dev=""
scontext=u:r:mediaserver:s0 tcontext=u:object_r:mediaextractor:s0 tclass=memfd_file

auditd  : Decoded path for audit(0.0:86): /memfd:MediaBufferGroup (deleted)

मिलता-जुलता टाइमस्टैंप यह दिखाता है कि Decoded path for … log, 0.0.86 टाइमस्टैंप के साथ avc के अस्वीकार किए जाने से जुड़ा है. यह लॉग, avc डेनियल में पाथ वैल्यू से हेक्साडेसिमल स्ट्रिंग को डिकोड करता है. साथ ही, memfd मेमोरी रीजन का नाम देता है. इससे यह समझने में मदद मिल सकती है कि कौनसे बफ़र को शेयर किया जा रहा है. सोर्स कॉन्टेक्स्ट और टारगेट कॉन्टेक्स्ट से यह समझने में मदद मिलती है कि किन प्रोसेस को मेमोरी शेयर करने की ज़रूरत है. ऊपर दिए गए उदाहरण से यह साफ़ तौर पर पता चलता है कि mediaserver प्रोसेस को mediaextractor के memfds को ऐक्सेस करने की अनुमति होनी चाहिए. इसलिए, सही नीति यह है:

# mediaserver.te
allow mediaserver mediaextractor:memfd_file { getattr read write map };

Android 17 में सुरक्षा डोमेन से जुड़े अपडेट

Android 17 में मौजूद ASharedMemory_create() एपीआई, शेयर की गई मेमोरी के लिए मेमोरी असाइन करने के लिए, लेगसी ऐशमेम ड्राइवर और memfd फ़्रेमवर्क में से किसी एक को चुनने के लिए, शर्त के हिसाब से लॉजिक लागू करता है.

memfd की ज़रूरी शर्तें (वेंडर एपीआई लेवल 202604 या उसके बाद का वर्शन और कर्नल android16-6.12 या उसके बाद का वर्शन) पूरी करने वाले डिवाइसों के लिए, एपीआई, कॉल करने वाले ऐप्लिकेशन के targetSdkVersion का आकलन करता है. अगर टारगेट SDK वर्शन 37 या इसके बाद का है, तो memfd को असाइन किया जाता है. इससे डेवलपर को टारगेट एसडीके के वर्शन को अपग्रेड करते समय आने वाली समस्याओं को ठीक करने में मदद मिलती है.

अगर डिवाइस memfd's ज़रूरी शर्तें पूरी नहीं करता है, तो ASharedMemory ऐशमेम पर वापस आ जाता है. इससे अपग्रेड किए गए डिवाइसों पर, वेंडर के पुराने पार्टीशन या कर्नल के साथ काम करने की सुविधा बनी रहती है.

इस बदलाव को लागू करने के लिए, SELinux की प्लैटफ़ॉर्म नीति, SDK वर्शन 37 या इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन को platform_app, priv_app, और untrusted_app सुरक्षा डोमेन में, /dev/ashmem खोलने और memfd पर ashmem ioctl कमांड लागू करने से रोकती है. ऐसा, टारगेट किए गए एसडीके वर्शन के आधार पर ऐप्लिकेशन के डोमेन को अलग-अलग करके किया जाता है. इस अपडेट में platform_app_36, priv_app_36, और untrusted_app_34 सुरक्षा डोमेन जोड़े गए हैं. ये अन्य ऐप्लिकेशन डोमेन के साथ मिलकर, ashmem को खोलने की अनुमतियां बनाए रखते हैं. साथ ही, memfds पर ashmem ioctl कमांड को लागू करने की सुविधा भी बनाए रखते हैं.

Android के आने वाले वर्शन में, ऐप्लिकेशन के उस सेट को कम कर दिया जाएगा जिनके पास ashmem डिवाइस को खोलने और memfds पर ashmem ioctl कमांड लागू करने की अनुमतियां हैं. अब सिर्फ़ platform_app_36, priv_app_36, और untrusted_app_34 के साथ-साथ पुराने एसडीके वर्शन के लिए, भरोसेमंद न माने जाने वाले ऐप्लिकेशन डोमेन के पास ये अनुमतियां होंगी.

अपने टारगेट एसडीके वर्शन को पिन करने वाले ऐप्लिकेशन के लिए, कस्टम वेंडर या ओईएम SELinux नीतियों को इन डोमेन में हुए बदलावों के मुताबिक अपडेट करना होगा. इसके बारे में यहां बताया गया है.

platform_app SELinux डोमेन से जुड़े अपडेट

platform_app डोमेन को ऐप्लिकेशन के targetSdkVersion के आधार पर बांटा जाता है. एसडीके वर्शन 37 या इसके बाद के वर्शन को टारगेट करने वाले प्लैटफ़ॉर्म ऐप्लिकेशन को platform_app डोमेन असाइन किया जाता है. वहीं, एसडीके वर्शन 36 या इससे पहले के वर्शन को टारगेट करने वाले ऐप्लिकेशन, platform_app_36 का इस्तेमाल करते हैं. पिछले वर्शन के साथ काम करने की सुविधा के लिए, platform_app_36 डोमेन में /dev/ashmem खोलने की सुविधा बनी रहती है. दोनों डोमेन पर नीति को आसानी से मैनेज करने के लिए, platform_app_all एट्रिब्यूट का इस्तेमाल करें.

मान लें कि प्लैटफ़ॉर्म ऐप्लिकेशन sample-plat-app को /dev/foo_device से डेटा पढ़ने और लिखने की ज़रूरत है. वेंडर की मौजूदा SELinux नीति कुछ ऐसी दिख सकती है:

# This will only allow sample-plat-app to access the device if it
# is placed in the platform_app domain (i.e. target SDK version is 37 or higher).
allow platform_app foo_device:chr_file rw_file_perms;

हालांकि, अगर sample-plat-app को टारगेट किए जा रहे SDK टूल के वर्शन 36 पर पिन किया जाता है, तो इसे platform_app_36 डोमेन में रखा जाता है. साथ ही, SELinux की पुरानी नीति लागू नहीं होगी. इसके अलावा, एवीसी से जुड़ी यह गड़बड़ी दिखेगी:

auditd  : type=1400 audit(0.0:11): avc:  denied  { read write } for  comm="sample-plat-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:platform_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0

इस समस्या को ठीक करने के लिए, नीति को इस तरह अपडेट किया जा सकता है, क्योंकि ऐप्लिकेशन के पास हमेशा डिवाइस नोड का ऐक्सेस होना चाहिए:

# This allows sample-plat-app to access the device independent of
# target SDK version.
allow platform_app_all foo_device:chr_file rw_file_perms;

ऐसा हो सकता है कि कुछ मामलों में platform_app_all काम न करे. उदाहरण के लिए, अगर hal_client_domain() मैक्रो का इस्तेमाल platform_app_all के साथ किया जाता है, तो नीति कंपाइल नहीं हो पाती. ऐसा इसलिए है, क्योंकि platform_app_all एक एट्रिब्यूट है. साथ ही, hal_client_domain() इसके साथ कोई दूसरा एट्रिब्यूट अटैच करने की कोशिश करेगा, जो कि मुमकिन नहीं है:

# platform_app.te
hal_client_domain(platform_app, hal_foo)

ऐसे मामलों में, सीधे तौर पर platform_app_36 टाइप का इस्तेमाल करना ज़रूरी है, ताकि आपकी नीति में यह कॉन्टेंट शामिल हो:

# platform_app.te
hal_client_domain(platform_app, hal_foo)

# platform_app_36.te
hal_client_domain(platform_app_36, hal_foo)

priv_app SELinux डोमेन अपडेट

priv_app डोमेन को ऐप्लिकेशन के targetSdkVersion के आधार पर बांटा जाता है. एसडीके वर्शन 37 या इसके बाद के वर्शन को टारगेट करने वाले खास ऐप्लिकेशन को priv_app डोमेन असाइन किया जाता है. वहीं, एसडीके वर्शन 36 या इससे पहले के वर्शन को टारगेट करने वाले ऐप्लिकेशन, priv_app_36 का इस्तेमाल करते हैं. पिछले वर्शन के साथ काम करने की सुविधा के लिए, priv_app_36 डोमेन में /dev/ashmem खोलने की सुविधा बनी रहती है. दोनों डोमेन पर नीति को आसानी से मैनेज करने के लिए, priv_app_all एट्रिब्यूट का इस्तेमाल करें.

मान लें कि प्लैटफ़ॉर्म ऐप्लिकेशन sample-priv-app को /dev/foo_device से डेटा पढ़ने और लिखने की ज़रूरत है. वेंडर की मौजूदा SELinux नीति कुछ ऐसी दिख सकती है:

# This will only allow sample-priv-app to access the device if it
# is placed in the priv_app domain (i.e. target SDK version is 37 or higher).
allow priv_app foo_device:chr_file rw_file_perms;

हालांकि, अगर sample-priv-app को टारगेट किए जा रहे SDK टूल के वर्शन 36 पर पिन किया जाता है, तो इसे priv_app_36 डोमेन में रखा जाता है. साथ ही, SELinux की पुरानी नीति लागू नहीं होगी. इसके अलावा, एवीसी से जुड़ी यह गड़बड़ी दिखेगी:

auditd  : type=1400 audit(0.0:11): avc:  denied  { read write } for  comm="sample-priv-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:priv_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0

इस समस्या को ठीक करने के लिए, नीति को इस तरह अपडेट किया जा सकता है, क्योंकि ऐप्लिकेशन के पास हमेशा डिवाइस नोड का ऐक्सेस होना चाहिए:

# This allows sample-priv-app to access the device independent of
# target SDK version.
allow priv_app_all foo_device:chr_file rw_file_perms;

ऐसा हो सकता है कि कुछ मामलों में priv_app_all काम न करे. उदाहरण के लिए, अगर priv_app_all के साथ hal_client_domain() मैक्रो का इस्तेमाल किया जाता है, तो नीति कंपाइल नहीं होगी. ऐसा इसलिए है, क्योंकि priv_app_all एक एट्रिब्यूट है. साथ ही, hal_client_domain() इसके साथ कोई दूसरा एट्रिब्यूट अटैच करने की कोशिश करेगा, जो कि मुमकिन नहीं है:

# priv_app.te
hal_client_domain(priv_app, hal_foo)

ऐसे मामलों में, सीधे तौर पर priv_app_36 टाइप का इस्तेमाल करना ज़रूरी है. इसलिए, आपकी नीति फ़ाइलें कुछ ऐसी दिखेंगी:

# priv_app.te
hal_client_domain(priv_app, hal_foo)

# priv_app_36.te
hal_client_domain(priv_app_36, hal_foo)

अविश्वसनीय ऐप्लिकेशन के लिए SELinux डोमेन से जुड़े अपडेट

untrusted_app डोमेन को ऐप्लिकेशन के targetSdkVersion के आधार पर बांटा जाता है. SDK टूल के वर्शन 37 या इसके बाद के वर्शन को टारगेट करने वाले ऐसे ऐप्लिकेशन जिन पर भरोसा नहीं किया जा सकता उन्हें untrusted_app डोमेन असाइन किया जाता है. वहीं, SDK टूल के वर्शन 34 से 36 तक के वर्शन को टारगेट करने वाले ऐप्लिकेशन को नया untrusted_app_34 डोमेन असाइन किया जाता है. untrusted_app_34 डोमेन के साथ-साथ untrusted_app_X डोमेन में, `/dev/ashmem` को खोलने की सुविधा बरकरार रहती है. यहां `X` टारगेट SDK टूल का पुराना वर्शन है. ऐसा इसलिए होता है, ताकि ये डोमेन पुराने वर्शन के साथ काम कर सकें.