एंड्रॉइड ओईएम को अपने SELinux कार्यान्वयन का पूरी तरह से परीक्षण करने के लिए दृढ़ता से प्रोत्साहित करता है। जैसे ही निर्माता SELinux लागू करते हैं, उन्हें पहले उपकरणों के परीक्षण पूल पर नई नीति लागू करनी चाहिए।
नई नीति लागू करने के बाद, getenforce
कमांड जारी करके सुनिश्चित करें कि SELinux डिवाइस पर सही मोड में चल रहा है।
यह वैश्विक SELinux मोड प्रिंट करता है: या तो एनफोर्सिंग या परमिसिव। प्रत्येक डोमेन के लिए SELinux मोड निर्धारित करने के लिए, आपको संबंधित फ़ाइलों की जांच करनी होगी या /platform/system/sepolicy/tools/
में मौजूद उपयुक्त ( -p
) ध्वज के साथ sepolicy-analyze
का नवीनतम संस्करण चलाना होगा।
खंडन पढ़ना
त्रुटियों की जाँच करें, जो इवेंट लॉग के रूप में dmesg
और logcat
पर रूट की जाती हैं और डिवाइस पर स्थानीय रूप से देखने योग्य होती हैं। निर्माताओं को इन उपकरणों पर dmesg
के लिए SELinux आउटपुट की जांच करनी चाहिए और अनुमेय मोड में सार्वजनिक रिलीज से पहले सेटिंग्स को परिष्कृत करना चाहिए और अंततः एन्फोर्सिंग मोड में स्विच करना चाहिए। SELinux लॉग संदेशों में avc:
होता है और इसलिए इसे grep
के साथ आसानी से पाया जा सकता है। cat /proc/kmsg
चलाकर चल रहे इनकार लॉग को कैप्चर करना या cat /sys/fs/pstore/console-ramoops
चलाकर पिछले बूट से इनकार लॉग को कैप्चर करना संभव है।
लॉग को खराब होने से बचाने के लिए बूट पूर्ण होने के बाद SELinux त्रुटि संदेशों की दर-सीमित होती है। यह सुनिश्चित करने के लिए कि आप सभी प्रासंगिक संदेश देख रहे हैं, आप adb shell auditctl -r 0
चलाकर इसे अक्षम कर सकते हैं।
इस आउटपुट के साथ, निर्माता आसानी से पहचान सकते हैं कि सिस्टम उपयोगकर्ता या घटक SELinux नीति का उल्लंघन कर रहे हैं। निर्माता सॉफ़्टवेयर, SELinux नीति या दोनों में परिवर्तन करके इस ख़राब व्यवहार को सुधार सकते हैं।
विशेष रूप से, ये लॉग संदेश इंगित करते हैं कि प्रवर्तन मोड के तहत कौन सी प्रक्रियाएँ विफल होंगी और क्यों। यहाँ एक उदाहरण है:
avc: denied { connectto } for pid=2671 comm="ping" path="/dev/socket/dnsproxyd" scontext=u:r:shell:s0 tcontext=u:r:netd:s0 tclass=unix_stream_socket
इस आउटपुट की व्याख्या इस प्रकार करें:
- उपरोक्त
{ connectto }
की जा रही कार्रवाई को दर्शाता है। अंत मेंtclass
(unix_stream_socket
) के साथ, यह आपको मोटे तौर पर बताता है कि क्या किया जा रहा था। इस मामले में, कुछ यूनिक्स स्ट्रीम सॉकेट से कनेक्ट करने का प्रयास कर रहा था। -
scontext (u:r:shell:s0)
आपको बताता है कि किस संदर्भ ने कार्रवाई शुरू की। इस मामले में यह शेल के रूप में चलने वाली कोई चीज़ है। -
tcontext (u:r:netd:s0)
आपको कार्रवाई के लक्ष्य का संदर्भ बताता है। इस मामले में, यह एक unix_stream_socket है जिसका स्वामित्वnetd
के पास है। - शीर्ष पर
comm="ping"
आपको एक अतिरिक्त संकेत देता है कि अस्वीकृति उत्पन्न होने के समय क्या चल रहा था। इस मामले में, यह एक बहुत अच्छा संकेत है.
एक और उदाहरण:
adb shell su root dmesg | grep 'avc: '
आउटपुट:
<5> type=1400 audit: avc: denied { read write } for pid=177 comm="rmt_storage" name="mem" dev="tmpfs" ino=6004 scontext=u:r:rmt:s0 tcontext=u:object_r:kmem_device:s0 tclass=chr_file
इस इनकार के प्रमुख तत्व इस प्रकार हैं:
- कार्रवाई - प्रयास की गई कार्रवाई को कोष्ठक में हाइलाइट किया गया है,
read write
याsetenforce
। - अभिनेता -
scontext
(स्रोत संदर्भ) प्रविष्टि अभिनेता का प्रतिनिधित्व करती है, इस मामले मेंrmt_storage
डेमॉन। - वस्तु -
tcontext
(लक्ष्य संदर्भ) प्रविष्टि उस वस्तु का प्रतिनिधित्व करती है जिस पर कार्रवाई की जा रही है, इस मामले में kmem। - परिणाम -
tclass
(लक्ष्य वर्ग) प्रविष्टि उस वस्तु के प्रकार को इंगित करती है जिस पर कार्रवाई की जा रही है, इस मामले में एकchr_file
(वर्ण डिवाइस)।
डंपिंग उपयोगकर्ता और कर्नेल स्टैक
कुछ मामलों में, इवेंट लॉग में मौजूद जानकारी इनकार के मूल को इंगित करने के लिए पर्याप्त नहीं है। यह बेहतर ढंग से समझने के लिए कि अस्वीकृति क्यों हुई, कर्नेल और यूजरस्पेस सहित कॉल श्रृंखला को इकट्ठा करना अक्सर उपयोगी होता है।
हाल के कर्नेल avc:selinux_audited
नामक एक ट्रेसप्वाइंट को परिभाषित करते हैं। इस ट्रेसपॉइंट को सक्षम करने और कॉलचेन को कैप्चर करने के लिए एंड्रॉइड simpleperf
का उपयोग करें।
समर्थित कॉन्फ़िगरेशन
- लिनक्स कर्नेल >= 5.10, विशेष रूप से एंड्रॉइड कॉमन कर्नेल शाखाएँ मेनलाइन और एंड्रॉइड12-5.10 समर्थित हैं। android12-5.4 शाखा भी समर्थित है। यह निर्धारित करने के लिए कि आपके डिवाइस पर ट्रेसप्वाइंट परिभाषित है या नहीं, आप
simpleperf
उपयोग कर सकते हैं:adb root && adb shell simpleperf list | grep avc:selinux_audited
। अन्य कर्नेल संस्करणों के लिए, आप चेरी कमिट dd81662 और 30969bc चुन सकते हैं। - जिस ईवेंट को आप डिबग कर रहे हैं उसे पुन: उत्पन्न करना संभव होना चाहिए। सिंपलपरफ का उपयोग करके बूट टाइम इवेंट समर्थित नहीं हैं; हालाँकि आप अभी भी ईवेंट को ट्रिगर करने के लिए सेवा को पुनरारंभ करने में सक्षम हो सकते हैं।
कॉल चेन कैप्चर करना
पहला कदम simpleperf record
उपयोग करके ईवेंट को रिकॉर्ड करना है:
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
फिर, उस घटना को ट्रिगर किया जाना चाहिए जिसके कारण इनकार किया गया। उसके बाद रिकॉर्डिंग बंद कर देनी चाहिए. इस उदाहरण में, Ctrl-c
का उपयोग करके, नमूना कैप्चर किया जाना चाहिए था:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
अंत में, कैप्चर किए गए स्टैकट्रेस का निरीक्षण करने के लिए simpleperf report
उपयोग किया जा सकता है। उदाहरण के लिए:
adb shell -t "cd /data/local/tmp && su root simpleperf report -g --full-callgraph" [...] Children Self Command Pid Tid Shared Object Symbol 100.00% 0.00% dmesg 3318 3318 /apex/com.android.runtime/lib64/bionic/libc.so __libc_init | -- __libc_init | -- main toybox_main toy_exec_which dmesg_main klogctl entry_SYSCALL_64_after_hwframe do_syscall_64 __x64_sys_syslog do_syslog selinux_syslog slow_avc_audit common_lsm_audit avc_audit_post_callback avc_audit_post_callback
उपरोक्त कॉल श्रृंखला एक एकीकृत कर्नेल और यूजरस्पेस कॉल श्रृंखला है। यह आपको यूजरस्पेस से लेकर कर्नेल तक जहां इनकार होता है, ट्रेस शुरू करके कोड प्रवाह का बेहतर दृश्य प्रदान करता है। simpleperf
पर अधिक जानकारी के लिए Simpleperf निष्पादन योग्य कमांड संदर्भ देखें
अनुमेय पर स्विच करना
SELinux प्रवर्तन को userdebug या eng बिल्ड पर ADB के माध्यम से अक्षम किया जा सकता है। ऐसा करने के लिए, पहले adb root
चलाकर ADB को रूट पर स्विच करें। फिर, SELinux प्रवर्तन को अक्षम करने के लिए, चलाएँ:
adb shell setenforce 0
या कर्नेल कमांड लाइन पर (प्रारंभिक डिवाइस लाने के दौरान):
androidboot.selinux=permissive
androidboot.selinux=enforcing
या Android 12 में Bootconfig के माध्यम से:
androidboot.selinux=permissive
androidboot.selinux=enforcing
ऑडिट2अनुमति का उपयोग करना
audit2allow
टूल dmesg
इनकार लेता है और उन्हें संबंधित SELinux नीति विवरण में परिवर्तित करता है। इस प्रकार, यह SELinux के विकास को बहुत तेज़ कर सकता है।
इसका उपयोग करने के लिए, चलाएँ:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
फिर भी, अधिक अनुमतियों के लिए प्रत्येक संभावित जोड़ की जांच करने में सावधानी बरतनी चाहिए। उदाहरण के लिए, audit2allow
फीड करने से निम्नलिखित सुझाए गए SELinux नीति कथन में पहले दिखाए गए rmt_storage
इनकार को दिखाया गया है:
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
यह rmt
कर्नेल मेमोरी, एक स्पष्ट सुरक्षा छेद लिखने की क्षमता प्रदान करेगा। अक्सर audit2allow
विवरण केवल एक प्रारंभिक बिंदु होते हैं। इन कथनों को नियोजित करने के बाद, आपको एक अच्छी नीति पर पहुंचने के लिए स्रोत डोमेन और लक्ष्य के लेबल को बदलने के साथ-साथ उचित मैक्रोज़ को शामिल करने की आवश्यकता हो सकती है। कभी-कभी जांच किए जा रहे इनकार के परिणामस्वरूप कोई नीतिगत परिवर्तन नहीं होना चाहिए; बल्कि आपत्तिजनक आवेदन को बदला जाना चाहिए।