SELinux को मान्य किया जा रहा है

एंड्रॉइड ओईएम को अपने 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 विवरण केवल एक प्रारंभिक बिंदु होते हैं। इन कथनों को नियोजित करने के बाद, आपको एक अच्छी नीति पर पहुंचने के लिए स्रोत डोमेन और लक्ष्य के लेबल को बदलने के साथ-साथ उचित मैक्रोज़ को शामिल करने की आवश्यकता हो सकती है। कभी-कभी जांच किए जा रहे इनकार के परिणामस्वरूप कोई नीतिगत परिवर्तन नहीं होना चाहिए; बल्कि आपत्तिजनक आवेदन को बदला जाना चाहिए।