SELinux लागू करना

SELinux को डिफ़ॉल्ट रूप से 'अनुमति नहीं है' पर सेट किया जाता है. इसका मतलब है कि जिस ऐक्सेस के लिए, इसके पास कर्नेल में हुक है उसके लिए नीति में साफ़ तौर पर अनुमति होनी चाहिए. इसका मतलब है कि नीति फ़ाइल में, नियमों, टाइप, क्लास, अनुमतियों वगैरह के बारे में काफ़ी जानकारी होती है. इस दस्तावेज़ में, SELinux के बारे में पूरी जानकारी नहीं दी गई है. हालांकि, नए Android डिवाइसों को लॉन्च करते समय, नीति के नियम लिखने का तरीका समझना ज़रूरी है. SELinux के बारे में पहले से ही काफ़ी जानकारी उपलब्ध है. सुझाए गए संसाधनों के लिए, ज़रूरी दस्तावेज़ देखें.

मुख्य फ़ाइलें

SELinux को चालू करने के लिए, नया Android kernel इंटिग्रेट करें. इसके बाद, system/sepolicy डायरेक्ट्री में मौजूद फ़ाइलों को शामिल करें. कंपाइल होने पर, इन फ़ाइलों में SELinux कर्नेल की सुरक्षा नीति शामिल होती है. साथ ही, इनमें अपस्ट्रीम Android ऑपरेटिंग सिस्टम भी शामिल होता है.

आम तौर पर, आपको system/sepolicy फ़ाइलों में सीधे तौर पर बदलाव नहीं करना चाहिए. इसके बजाय, /device/manufacturer/device-name/sepolicy डायरेक्ट्री में, डिवाइस के हिसाब से बनी नीति की फ़ाइलें जोड़ें या उनमें बदलाव करें. Android 8.0 और इसके बाद के वर्शन में, इन फ़ाइलों में किए गए बदलावों का असर सिर्फ़ आपकी वेंडर डायरेक्ट्री में मौजूद नीति पर पड़ेगा. Android 8.0 और उसके बाद के वर्शन में, सार्वजनिक sepolicy को अलग करने के बारे में ज़्यादा जानकारी के लिए, Android 8.0 और उसके बाद के वर्शन में SEPolicy को पसंद के मुताबिक बनाना लेख पढ़ें. Android के वर्शन के बावजूद, अब भी इन फ़ाइलों में बदलाव किया जा रहा है:

नीति फ़ाइलें

*.te पर खत्म होने वाली फ़ाइलें, SELinux नीति की सोर्स फ़ाइलें होती हैं. इनमें डोमेन और उनके लेबल की जानकारी होती है. आपको /device/manufacturer/device-name/sepolicy में नई नीति फ़ाइलें बनानी पड़ सकती हैं. हालांकि, जहां भी हो सके वहां मौजूदा फ़ाइलों को अपडेट करने की कोशिश करें.

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

कॉन्टेक्स्ट फ़ाइलों में, अपने ऑब्जेक्ट के लिए लेबल तय किए जाते हैं.

  • file_contexts, फ़ाइलों को लेबल असाइन करता है और इसका इस्तेमाल, उपयोगकर्ता के अलग-अलग कॉम्पोनेंट करते हैं. नई नीतियां बनाते समय, फ़ाइलों को नए लेबल असाइन करने के लिए, यह फ़ाइल बनाएं या अपडेट करें. नया file_contexts लागू करने के लिए, फ़ाइल सिस्टम इमेज को फिर से बनाएं या जिस फ़ाइल को फिर से लेबल करना है उस पर restorecon चलाएं. अपग्रेड करने पर, file_contexts में किए गए बदलाव, अपग्रेड के हिस्से के तौर पर, सिस्टम और उपयोगकर्ता डेटा वाले सेक्शन पर अपने-आप लागू हो जाते हैं. बदलावों को अन्य partition में अपग्रेड करने पर भी अपने-आप लागू किया जा सकता है. इसके लिए, partition को रीड-राइट मोड में माउंट करने के बाद, अपनी init.board.rc फ़ाइल में restorecon_recursive कॉल जोड़ें.
  • genfs_contexts, proc या vfat जैसे फ़ाइल सिस्टम को लेबल असाइन करता है. ये फ़ाइल सिस्टम, एक्सटेंडेड एट्रिब्यूट के साथ काम नहीं करते. यह कॉन्फ़िगरेशन, कर्नेल नीति के हिस्से के तौर पर लोड किया जाता है. हालांकि, हो सकता है कि इन-कोर इनोड के लिए बदलाव लागू न हों. बदलाव को पूरी तरह से लागू करने के लिए, डिवाइस को रीबूट करना पड़ सकता है या फ़ाइल सिस्टम को अनमाउंट करके फिर से माउंट करना पड़ सकता है. खास माउंट के लिए भी खास लेबल असाइन किए जा सकते हैं. जैसे, context=mount विकल्प का इस्तेमाल करके vfat.
  • property_contexts, Android सिस्टम प्रॉपर्टी को लेबल असाइन करता है, ताकि यह कंट्रोल किया जा सके कि कौनसी प्रोसेस उन्हें सेट कर सकती हैं. स्टार्टअप के दौरान, init प्रोसेस इस कॉन्फ़िगरेशन को पढ़ती है.
  • service_contexts, Android बाइंडर सेवाओं को लेबल असाइन करता है, ताकि यह कंट्रोल किया जा सके कि कौनसी प्रोसेस, सेवा के लिए बाइंडर रेफ़रंस को जोड़ सकती हैं (रजिस्टर कर सकती हैं) और ढूंढ सकती हैं (लुकअप कर सकती हैं). स्टार्टअप के दौरान, servicemanager प्रोसेस इस कॉन्फ़िगरेशन को पढ़ती है.
  • seapp_contexts, ऐप्लिकेशन की प्रोसेस और /data/data डायरेक्ट्री को लेबल असाइन करता है. इस कॉन्फ़िगरेशन को हर ऐप्लिकेशन लॉन्च पर zygote प्रोसेस और स्टार्टअप के दौरान installd प्रोसेस पढ़ती है.
  • mac_permissions.xml, ऐप्लिकेशन के हस्ताक्षर और पैकेज के नाम के आधार पर, उन ऐप्लिकेशन को seinfo टैग असाइन करता है. इसके बाद, seinfo टैग का इस्तेमाल, seapp_contexts फ़ाइल में एक कुंजी के तौर पर किया जा सकता है. इससे, उस seinfo टैग वाले सभी ऐप्लिकेशन को कोई खास लेबल असाइन किया जा सकता है. स्टार्टअप के दौरान, system_server इस कॉन्फ़िगरेशन को पढ़ता है.
  • keystore2_key_contexts, Keystore 2.0 नेमस्पेस को लेबल असाइन करता है. ये नेमस्पेस, keystore2 डेमन की मदद से लागू किए जाते हैं. Keystore में हमेशा UID/AID पर आधारित नेमस्पेस उपलब्ध होते हैं. Keystore 2.0, sepolicy के मुताबिक तय किए गए नेमस्पेस को भी लागू करता है. इस फ़ाइल के फ़ॉर्मैट और नियमों के बारे में पूरी जानकारी यहां दी गई है.

BoardConfig.mk मेकफ़ाइल

नीति और संदर्भ फ़ाइलों में बदलाव करने या उन्हें जोड़ने के बाद, sepolicy सबडायरेक्ट्री और हर नई नीति फ़ाइल का रेफ़रंस देने के लिए, अपनी /device/manufacturer/device-name/BoardConfig.mkmakefile अपडेट करें. BOARD_SEPOLICY वैरिएबल के बारे में ज़्यादा जानकारी के लिए, system/sepolicy/README फ़ाइल देखें.

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

फिर से बनाने के बाद, आपके डिवाइस पर SELinux चालू हो जाता है. अब आपके पास, पसंद के मुताबिक बनाने में बताए गए तरीके के मुताबिक, Android ऑपरेटिंग सिस्टम में अपने हिसाब से बदलाव करने के लिए, SELinux की नीतियों को पसंद के मुताबिक बनाने का विकल्प है. इसके अलावा, पुष्टि में बताए गए तरीके के मुताबिक, अपने मौजूदा सेटअप की पुष्टि भी की जा सकती है.

जब नई नीति फ़ाइलें और BoardConfig.mk अपडेट हो जाते हैं, तो नीति की नई सेटिंग, कर्नेल की नीति की फ़ाइनल फ़ाइल में अपने-आप बन जाती हैं. डिवाइस पर sepolicy बनाने के तरीके के बारे में ज़्यादा जानने के लिए, sepolicy बनाना लेख पढ़ें.

लागू करना

SELinux का इस्तेमाल शुरू करने के लिए:

  1. कर्नेल में SELinux चालू करें: CONFIG_SECURITY_SELINUX=y
  2. kernel_cmdline या bootconfig पैरामीटर को बदलें, ताकि:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    या
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    यह सिर्फ़ डिवाइस के लिए नीति के शुरुआती डेवलपमेंट के लिए है. शुरुआती बूटस्ट्रैप नीति सेट करने के बाद, इस पैरामीटर को हटा दें, ताकि आपका डिवाइस नीति लागू कर सके या सीटीएस की जांच में पास हो सके.
  3. सिस्टम को अनुमति वाले मोड में बूट करें और देखें कि बूट करने पर कौनसी अनुमतियां अस्वीकार की गईं:
    Ubuntu 14.04 या इसके बाद के वर्शन पर:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    Ubuntu 12.04 पर:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. init: Warning! Service name needs a SELinux domain defined; please fix! निर्देशों और टूल के लिए, पुष्टि देखें के जैसी चेतावनियों के लिए, आउटपुट का आकलन करें.
  5. उन डिवाइसों और अन्य नई फ़ाइलों की पहचान करना जिन पर लेबल लगाना ज़रूरी है.
  6. अपने ऑब्जेक्ट के लिए मौजूदा या नए लेबल का इस्तेमाल करें. *_contexts फ़ाइलों को देखकर पता लगाएं कि पहले चीज़ों को किस तरह लेबल किया गया था. साथ ही, नया लेबल असाइन करने के लिए, लेबल के मतलब के बारे में जानकारी का इस्तेमाल करें. आम तौर पर, यह एक ऐसा मौजूदा लेबल होता है जो नीति के मुताबिक होता है. हालांकि, कभी-कभी किसी नए लेबल की ज़रूरत पड़ती है. साथ ही, उस लेबल को ऐक्सेस करने के लिए नियमों की ज़रूरत होती है. अपने लेबल, सही संदर्भ फ़ाइलों में जोड़ें.
  7. उन डोमेन/प्रोसेस की पहचान करें जिनके पास अपने सुरक्षा डोमेन होने चाहिए. आपको हर एक के लिए, पूरी तरह से नई नीति लिखनी पड़ सकती है. उदाहरण के लिए, init से जनरेट हुई सभी सेवाओं के लिए, यहां दिए गए निर्देशों से, उन सेवाओं के बारे में पता चलता है जो बंद नहीं हुई हैं. हालांकि, सभी सेवाओं को ऐसा करना होगा:
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. init.device.rc की समीक्षा करके, उन डोमेन की पहचान करें जिनके लिए कोई डोमेन टाइप नहीं है. डेवलपमेंट की प्रोसेस में, उन्हें जल्दी एक डोमेन दें, ताकि init में नियम जोड़ने से बचा जा सके. इसके अलावा, init के ऐक्सेस को अपनी नीति में शामिल किए गए ऐक्सेस से अलग किया जा सके.
  9. BOARD_SEPOLICY_* वैरिएबल का इस्तेमाल करने के लिए, BOARD_CONFIG.mk सेट अप करें. इसे सेट अप करने के बारे में जानने के लिए, system/sepolicy में README देखें.
  10. init.device.rc और fstab.device फ़ाइल की जांच करें और पक्का करें कि mount का हर इस्तेमाल, सही तरीके से लेबल किए गए फ़ाइल सिस्टम से जुड़ा हो या context= mount विकल्प दिया गया हो.
  11. हर बार अस्वीकार किए जाने की वजह देखें और हर बार के लिए SELinux नीति बनाएं, ताकि उन्हें सही तरीके से मैनेज किया जा सके. पसंद के मुताबिक बनाने में दिए गए उदाहरण देखें.

आपको AOSP में मौजूद नीतियों से शुरुआत करनी चाहिए. इसके बाद, अपनी पसंद के मुताबिक बदलाव करने के लिए, उन नीतियों को आधार बनाना चाहिए. नीति की रणनीति के बारे में ज़्यादा जानने और इनमें से कुछ चरणों के बारे में ज़्यादा जानने के लिए, SELinux नीति लिखना लेख पढ़ें.

इस्तेमाल के उदाहरण

यहां कुछ ऐसे उदाहरण दिए गए हैं जिन पर अपना सॉफ़्टवेयर और उससे जुड़ी SELinux नीतियां बनाते समय ध्यान देना चाहिए:

सिंबल लिंक: सिंबल लिंक, फ़ाइलों की तरह दिखते हैं. इसलिए, उन्हें अक्सर फ़ाइलों के तौर पर पढ़ा जाता है. इससे, उनका गलत इस्तेमाल किया जा सकता है. उदाहरण के लिए, init जैसे कुछ खास कॉम्पोनेंट, कुछ फ़ाइलों की अनुमतियां बदलते हैं. ऐसा कभी-कभी बहुत ज़्यादा खुलापन के लिए किया जाता है.

इसके बाद, हमलावर उन फ़ाइलों को अपने कंट्रोल वाले कोड के सिम्लिंक से बदल सकते हैं. इससे, हमलावर अपनी पसंद की फ़ाइलों को बदल सकता है. हालांकि, अगर आपको पता है कि आपका ऐप्लिकेशन कभी भी किसी सिमलिंक पर नहीं जाता, तो SELinux की मदद से उसे ऐसा करने से रोका जा सकता है.

सिस्टम फ़ाइलें: सिस्टम फ़ाइलों की उस क्लास पर विचार करें जिसमें सिर्फ़ सिस्टम सर्वर को बदलाव करना चाहिए. हालांकि, netd, init, और vold रूट के तौर पर चलते हैं, इसलिए वे उन सिस्टम फ़ाइलों को ऐक्सेस कर सकते हैं. इसलिए, अगर netd हैक हो जाता है, तो उन फ़ाइलों और सिस्टम सर्वर को भी हैक किया जा सकता है.

SELinux की मदद से, उन फ़ाइलों की पहचान सिस्टम सर्वर डेटा फ़ाइलों के तौर पर की जा सकती है. इसलिए, सिस्टम सर्वर ही एक ऐसा डोमेन है जिसके पास इनका रीड/राइट ऐक्सेस है. भले ही netd हैक हो गया हो, लेकिन वह डोमेन को सिस्टम सर्वर डोमेन पर स्विच नहीं कर सका और उन सिस्टम फ़ाइलों को ऐक्सेस नहीं कर सका. भले ही, वह रूट के तौर पर चलता हो.

ऐप्लिकेशन का डेटा: एक और उदाहरण, फ़ंक्शन की वह क्लास है जिसे रूट के तौर पर चलाना ज़रूरी है, लेकिन उसे ऐप्लिकेशन का डेटा ऐक्सेस नहीं करना चाहिए. यह बहुत काम का है, क्योंकि इसमें कई तरह के दावे किए जा सकते हैं. जैसे, ऐप्लिकेशन के डेटा से जुड़े कुछ डोमेन को इंटरनेट ऐक्सेस करने से रोकना.

setattr: chmod और chown जैसे निर्देशों के लिए, उन फ़ाइलों के सेट की पहचान की जा सकती है जहां उनसे जुड़ा डोमेन setattr कर सकता है. इसके अलावा, किसी भी फ़ाइल में बदलाव करने की अनुमति नहीं है. भले ही, वह फ़ाइल रूट के पास हो. इसलिए, हो सकता है कि कोई ऐप्लिकेशन app_data_files लेबल वाले डिवाइसों पर chmod और chown चलाए, लेकिन shell_data_files या system_data_files पर न चलाए.