Android, OEM को SELinux को पूरी तरह से लागू करने की जांच करने का ज़ोरदार सुझाव देता है. जैसे-जैसे मैन्युफ़ैक्चरर SELinux को लागू करते हैं, उन्हें अपनी साइट पर टेस्ट पूल में जोड़ दी जाती हैं.
नई नीति लागू करने के बाद, getenforce
कमांड देकर पक्का करें कि डिवाइस पर SELinux सही मोड में चल रहा हो.
इससे ग्लोबल SELinux मोड प्रिंट होता है: लागू करने वाला या अनुमति देने वाला. हर डोमेन के लिए SELinux मोड तय करने के लिए, आपको उससे जुड़ी फ़ाइलों की जांच करनी होगी या /platform/system/sepolicy/tools/
में मौजूद सही (-p
) फ़्लैग के साथ sepolicy-analyze
का नया वर्शन चलाना होगा.
अनुमति न मिलने की जानकारी
गड़बड़ियों की जांच करें. इन्हें dmesg
और logcat
पर इवेंट लॉग के तौर पर भेजा जाता है. साथ ही, इन्हें डिवाइस पर स्थानीय तौर पर देखा जा सकता है. मैन्युफ़ैक्चरर को इन डिवाइसों पर, SELinux के आउटपुट को dmesg
पर जांचना चाहिए. साथ ही, सार्वजनिक तौर पर रिलीज़ करने से पहले, अनुमति वाले मोड में सेटिंग को बेहतर बनाना चाहिए और आखिर में, लागू करने वाले मोड पर स्विच करना चाहिए. 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)
से आपको ऐक्शन के टारगेट का कॉन्टेक्स्ट पता चलता है. इस मामले में, यहnetd
का मालिकाना हक वाला unix_stream_socket है. - सबसे ऊपर मौजूद
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
नाम का ट्रेसपॉइंट तय करते हैं. Android का इस्तेमाल करें
इस ट्रेसपॉइंट को चालू करने और कॉलचेन को कैप्चर करने के लिए, simpleperf
.
इस्तेमाल किया जा सकने वाला कॉन्फ़िगरेशन
- Linux kernel 5.10 और इसके बाद के वर्शन के साथ काम करता है. खास तौर पर, Android Common Kernel की शाखाएं
mainline और
android12-5.10 के साथ काम करता है.
android12-5.4
ब्रैंच भी काम करता है.
simpleperf
का इस्तेमाल करके यह पता लगाया जा सकता है कि ट्रेसपॉइंट सही है या नहीं आपके डिवाइस पर परिभाषित:adb root && adb shell simpleperf list | grep avc:selinux_audited
. अन्य कर्नेल वर्शन के लिए, dd81662 और 30969bc को चुना जा सकता है. - इस सुविधा का इस्तेमाल करके, उस इवेंट को फिर से दिखाया जा सकता है जिसे डीबग किया जा रहा है. simpleperf का इस्तेमाल करके, बूट टाइम इवेंट रिकॉर्ड नहीं किए जा सकते. हालांकि, इवेंट को ट्रिगर करने के लिए, अब भी सेवा को रीस्टार्ट किया जा सकता है.
कॉल चेन कैप्चर करना
पहला चरण, 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
audit2allow का इस्तेमाल करना
audit2allow
टूल, dmesg
के अस्वीकार किए गए अनुरोधों को लेकर, उनसे मिलते-जुलते SELinux नीति स्टेटमेंट में बदलाव करता है. इसलिए, इससे SELinux के डेवलपमेंट में काफ़ी तेज़ी आ सकती है.
इसका इस्तेमाल करने के लिए, यह चलाएं:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
इसके बावजूद, हर संभावित जोड़ की जांच करके यह देखना ज़रूरी है कि उसमें ज़रूरत से ज़्यादा अनुमतियां तो नहीं मांगी गई हैं. उदाहरण के लिए, audit2allow
को फ़ीड करना
rmt_storage
अस्वीकार करने की वजह से, पहले के नतीजे इस तरह दिखाए गए
सुझाया गया SELinux नीति स्टेटमेंट:
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
इससे rmt
को कर्नेल मेमोरी लिखने की सुविधा मिल जाएगी,
चमकीला सुरक्षा छेद. अक्सर audit2allow
स्टेटमेंट सिर्फ़ शुरुआत करने के लिए होते हैं. इन स्टेटमेंट को लागू करने के बाद, आपको
सोर्स डोमेन और टारगेट के लेबल के साथ-साथ,
मैक्रो, ताकि आप एक अच्छी नीति तैयार कर सकें. कभी-कभी, अस्वीकार किए गए ऐप्लिकेशन की समीक्षा करने पर, नीति में कोई बदलाव नहीं करना पड़ता. इसके बजाय, उल्लंघन करने वाले ऐप्लिकेशन में बदलाव करना पड़ता है.