SELinux लागू करना

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

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

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

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

नीति से जुड़ी फ़ाइलें

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

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

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

  • file_contexts फ़ाइलों को लेबल असाइन करता है. इसका इस्तेमाल अलग-अलग userspace कॉम्पोनेंट करते हैं. नई नीतियां बनाते समय, इस फ़ाइल को बनाएं या अपडेट करें, ताकि फ़ाइलों को नए लेबल असाइन किए जा सकें. नए file_contexts लागू करने के लिए, फ़ाइल सिस्टम इमेज को फिर से बनाएं या जिस फ़ाइल का लेबल बदलना है उस पर restorecon चलाएं. अपग्रेड करने पर, file_contexts में किए गए बदलाव, सिस्टम और userdata पार्टीशन पर अपने-आप लागू हो जाते हैं. ऐसा अपग्रेड करने की प्रोसेस के तहत होता है. पार्टिशन को रीड-राइट मोड में माउंट करने के बाद, restorecon_recursive कॉल को init.board.rc फ़ाइल में जोड़कर, अन्य पार्टिशन में अपग्रेड करने पर बदलाव अपने-आप लागू हो सकते हैं.
  • genfs_contexts, फ़ाइल सिस्टम को लेबल असाइन करता है. जैसे, proc या vfat. ये एक्सटेंडेड एट्रिब्यूट के साथ काम नहीं करते. इस कॉन्फ़िगरेशन को कर्नेल नीति के हिस्से के तौर पर लोड किया जाता है. हालांकि, हो सकता है कि इन-कोर इनोड के लिए बदलाव लागू न हों. इसके लिए, डिवाइस को रीबूट करना पड़ सकता है या फ़ाइल सिस्टम को अनमाउंट करके फिर से माउंट करना पड़ सकता है, ताकि बदलाव पूरी तरह से लागू हो सके. कुछ खास माउंट को भी कुछ खास लेबल असाइन किए जा सकते हैं. जैसे, vfat विकल्प का इस्तेमाल करके context=mount.
  • 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 के नेमस्पेस को लेबल असाइन करता है. इन नेमस्पेस को keystore2 डेमॉन लागू करता है. Keystore हमेशा से यूआईडी/एआईडी पर आधारित नेमस्पेस उपलब्ध कराता है. Keystore 2, sepolicy में तय किए गए नेमस्पेस को भी लागू करता है. इस फ़ाइल के फ़ॉर्मैट और कन्वेंशनल के बारे में ज़्यादा जानकारी यहां दी गई है.

BoardConfig.mk मेकफ़ाइल

नीति और कॉन्टेक्स्ट फ़ाइलों में बदलाव करने या उन्हें जोड़ने के बाद, अपनी /device/manufacturer/device-name/BoardConfig.mk makefile अपडेट करें. इससे sepolicy सबडायरेक्ट्री और हर नई नीति फ़ाइल का रेफ़रंस दिया जा सकेगा. 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 का नहीं.