AArch64 सिस्टम बायनेरिज़ के लिए निष्पादन योग्य कोड अनुभाग डिफ़ॉल्ट रूप से केवल-निष्पादित (गैर-पठनीय) के रूप में चिह्नित होते हैं, जो समय-समय पर कोड के पुन: उपयोग के हमलों के खिलाफ सख्त शमन के रूप में होते हैं। वह कोड जो डेटा और कोड को एक साथ मिलाता है और वह कोड जो जानबूझकर इन अनुभागों का निरीक्षण करता है (पहले मेमोरी सेगमेंट को पढ़ने योग्य के रूप में रीमैप किए बिना) अब काम नहीं करता है। 10 (एपीआई स्तर 29 या उच्चतर) के लक्ष्य एसडीके वाले ऐप्स प्रभावित होते हैं यदि ऐप पहले अनुभाग को पढ़ने योग्य के रूप में चिह्नित किए बिना मेमोरी में केवल निष्पादन योग्य मेमोरी (एक्सओएम) सक्षम सिस्टम लाइब्रेरी के कोड अनुभागों को पढ़ने का प्रयास करता है।
इस शमन से पूरी तरह से लाभ उठाने के लिए, हार्डवेयर और कर्नेल समर्थन दोनों की आवश्यकता है। इस समर्थन के बिना, शमन केवल आंशिक रूप से लागू किया जा सकता है। Android 4.9 सामान्य कर्नेल में ARMv8.2 उपकरणों पर इसके लिए पूर्ण समर्थन प्रदान करने के लिए उपयुक्त पैच शामिल हैं।
कार्यान्वयन
कंपाइलर द्वारा उत्पन्न AArch64 बायनेरिज़ यह मानते हैं कि कोड और डेटा आपस में मिश्रित नहीं होते हैं। इस सुविधा को सक्षम करने से डिवाइस के प्रदर्शन पर नकारात्मक प्रभाव नहीं पड़ता है।
उस कोड के लिए जिसे अपने निष्पादन योग्य खंडों पर जानबूझकर स्मृति आत्मनिरीक्षण करना होता है, यह सलाह दी जाती है कि निरीक्षण की आवश्यकता वाले कोड के खंडों पर mprotect
कॉल करें ताकि उन्हें पढ़ने योग्य बनाया जा सके, फिर निरीक्षण पूरा होने पर पठनीयता को हटा दें।
यह कार्यान्वयन केवल-निष्पादित के रूप में चिह्नित मेमोरी सेगमेंट में रीड्स का कारण बनता है जिसके परिणामस्वरूप सेगमेंटेशन गलती ( SEGFAULT
) होती है। यह बग, भेद्यता, कोड के साथ मिश्रित डेटा (शाब्दिक पूलिंग), या जानबूझकर मेमोरी आत्मनिरीक्षण के परिणामस्वरूप हो सकता है।
डिवाइस समर्थन और प्रभाव
आवश्यक पैच के बिना पुराने हार्डवेयर या पुराने कर्नेल (4.9 से कम) वाले डिवाइस इस सुविधा का पूरी तरह से समर्थन या लाभ नहीं उठा सकते हैं। कर्नेल समर्थन के बिना डिवाइस केवल निष्पादन मेमोरी के उपयोगकर्ता एक्सेस को लागू नहीं कर सकते हैं, हालांकि कर्नेल कोड जो स्पष्ट रूप से जांचता है कि कोई पृष्ठ पढ़ने योग्य है या नहीं, अभी भी इस संपत्ति को लागू कर सकता है, जैसे कि process_vm_readv()
।
कर्नेल ध्वज CONFIG_ARM64_UAO
को कर्नेल में सेट किया जाना चाहिए ताकि यह सुनिश्चित किया जा सके कि कर्नेल केवल-निष्पादन के रूप में चिह्नित उपयोगकर्तालैंड पृष्ठों का सम्मान करता है। पहले के ARMv8 डिवाइस, या उपयोगकर्ता एक्सेस ओवरराइड (UAO) अक्षम वाले ARMv8.2 डिवाइस, इससे पूरी तरह से लाभान्वित नहीं हो सकते हैं और अभी भी syscalls का उपयोग करके केवल-निष्पादित पृष्ठों को पढ़ने में सक्षम हो सकते हैं।
मौजूदा कोड को पुनः सक्रिय करना
AArch32 से पोर्ट किए गए कोड में मिश्रित डेटा और कोड हो सकते हैं, जिससे समस्याएँ उत्पन्न हो सकती हैं। कई मामलों में, इन समस्याओं को ठीक करना असेंबली फ़ाइल में स्थिरांक को .data
अनुभाग में ले जाने जितना आसान है।
स्थानीय स्तर पर एकत्रित स्थिरांकों को अलग करने के लिए हस्तलिखित असेंबली को दोबारा तैयार करने की आवश्यकता हो सकती है।
उदाहरण:
क्लैंग कंपाइलर द्वारा उत्पन्न बायनेरिज़ में डेटा को कोड में मिश्रित करने में कोई समस्या नहीं होनी चाहिए। यदि जीएनयू कंपाइलर संग्रह (जीसीसी) उत्पन्न कोड शामिल है (एक स्थिर लाइब्रेरी से), तो यह सुनिश्चित करने के लिए आउटपुट बाइनरी का निरीक्षण करें कि स्थिरांक को कोड अनुभागों में पूल नहीं किया गया है।
यदि निष्पादन योग्य कोड अनुभागों पर कोड आत्मनिरीक्षण आवश्यक है, तो कोड को पठनीय चिह्नित करने के लिए पहले mprotect
कॉल करें। फिर ऑपरेशन पूरा होने के बाद, इसे अपठनीय चिह्नित करने के लिए mprotect
दोबारा कॉल करें।
सक्षम करने से
बिल्ड सिस्टम में सभी 64-बिट बायनेरिज़ के लिए डिफ़ॉल्ट रूप से केवल निष्पादन सक्षम है।
अक्षम करने
आप केवल मॉड्यूल स्तर पर, संपूर्ण उपनिर्देशिका ट्री द्वारा, या वैश्विक स्तर पर संपूर्ण बिल्ड के लिए निष्पादन को अक्षम कर सकते हैं।
LOCAL_XOM
और xom
वेरिएबल्स को false
पर सेट करके XOM को उन अलग-अलग मॉड्यूलों के लिए अक्षम किया जा सकता है, जिन्हें रिफैक्टर नहीं किया जा सकता है, या उनके निष्पादन योग्य कोड को पढ़ने की आवश्यकता है।
// Android.mk LOCAL_XOM := false // Android.bp cc_binary { // or other module types ... xom: false, }
यदि किसी स्टैटिक लाइब्रेरी में केवल-एक्सेक्यूट मेमोरी अक्षम है, तो बिल्ड सिस्टम इसे उस स्टैटिक लाइब्रेरी के सभी आश्रित मॉड्यूल पर लागू करता है। आप xom: true,
का उपयोग करके इसे ओवरराइड कर सकते हैं।
किसी विशेष उपनिर्देशिका (उदाहरण के लिए, foo/bar/) में केवल-निष्पादित मेमोरी को अक्षम करने के लिए, मान को XOM_EXCLUDE_PATHS
पर पास करें।
make -j XOM_EXCLUDE_PATHS=foo/bar
वैकल्पिक रूप से, आप अपने उत्पाद कॉन्फ़िगरेशन में PRODUCT_XOM_EXCLUDE_PATHS
वैरिएबल सेट कर सकते हैं।
आप अपने make
कमांड पर ENABLE_XOM=false
पास करके विश्व स्तर पर केवल-निष्पादित बायनेरिज़ को अक्षम कर सकते हैं।
make -j ENABLE_XOM=false
मान्यकरण
केवल निष्पादित मेमोरी के लिए कोई सीटीएस या सत्यापन परीक्षण उपलब्ध नहीं हैं। आप readelf
उपयोग करके और सेगमेंट फ़्लैग की जांच करके बायनेरिज़ को मैन्युअल रूप से सत्यापित कर सकते हैं।