ذاكرة التنفيذ فقط (XOM) لبرامج AArch64 الثنائية

.

يتم تلقائيًا وضع علامة "قابل للتنفيذ فقط" (غير قابل للقراءة) على أقسام الرموز القابلة للتنفيذ لملفّات AArch64 الثنائية كإجراء تخفيف للتحصين من هجمات إعادة استخدام الرمز "في الوقت المناسب". لم تعُد التعليمات البرمجية التي تمزج البيانات والرمز البرمجي معًا والتعليمات البرمجية التي تفحص هذه الأقسام عمدًا (بدون إعادة ربط أجزاء الذاكرة أولاً على أنّها قابلة للقراءة) مفيدة. تتأثر التطبيقات التي تستهدِف الإصدار 10 من حزمة SDK (المستوى 29 من واجهة برمجة التطبيقات أو إصدار أحدث) إذا حاول التطبيق قراءة أقسام الرموز البرمجية في مكتبات النظام التي تم تفعيل ميزة "ذاكرة التنفيذ فقط" (XOM) فيها بدون وضع علامة أولاً على القسم على أنّه قابل للقراءة.

للاستفادة بشكل كامل من هذه الميزة، يجب أن يكون الجهاز والنواة متوافقَين مع الميزة. بدون هذا الدعم، قد يتم فرض إجراءات التخفيف جزئيًا فقط. يحتوي قلب نظام التشغيل Android 4.9 المشترَك على الرقع المناسبة لتقديم دعم كامل لهذه الميزة على أجهزة ARMv8.2.

التنفيذ

تفترض الثنائيات AArch64 التي ينشئها المُجمِّع أنّه لا يتم مزج التعليمات البرمجية والبيانات. لا يؤثّر تفعيل هذه الميزة سلبًا في أداء الجهاز.

بالنسبة إلى الرمز الذي يجب أن يُجري فحصًا ذاتيًا للذاكرة في أقسامه القابلة للتنفيذ، من المستحسن استدعاء mprotect في أقسام الرمز التي تتطلّب الفحص للسماح بقراءتها، ثم إزالة إمكانية القراءة عند اكتمال الفحص.
يؤدي هذا التنفيذ إلى قراءة أجزاء من الذاكرة التي تم وضع علامة عليها على أنّها مخصّصة للتنفيذ فقط، ما يؤدي إلى حدوث خطأ في التقسيم (SEGFAULT). قد يحدث ذلك نتيجة خطأ أو ثغرة أمنية أو بيانات تم مزجها مع الرمز البرمجي (تجميع النصوص الحرفية) أو فحص الذاكرة عن قصد.

توافق الجهاز وتأثيره

قد لا تتوافق هذه الميزة مع الأجهزة التي تعمل بإصدارات أقدم من الإصدار 4.9 من نظام التشغيل أو التي تعمل بإصدارات أقدم من الإصدار 4.9 من نواة النظام بدون التصحيحات المطلوبة، أو قد لا تستفيد هذه الأجهزة من هذه الميزة بالكامل. قد لا تفرض الأجهزة التي لا تتيح استخدام النواة إمكانية وصول المستخدمين إلى الذاكرة المخصّصة للتنفيذ فقط، ومع ذلك، قد يفرض رمز النواة الذي يتحقّق صراحةً مما إذا كانت الصفحة قابلة للقراءة هذه السمة، مثل process_vm_readv().

يجب ضبط علامة kernel CONFIG_ARM64_UAO في kernel لمحاولة ضمان أن يحترم kernel صفحات userland التي تم وضع علامة execute-only عليها. قد لا تستفيد بشكل كامل من هذه الميزة أجهزة ARMv8 القديمة أو أجهزة ARMv8.2 التي تم إيقاف ميزة "تجاوز إذن وصول المستخدم" (UAO) فيها، وقد يظل بإمكانها قراءة الصفحات المخصّصة للتنفيذ فقط باستخدام طلبات نظام التشغيل.

إعادة صياغة الرمز البرمجي الحالي

قد يحتوي الرمز البرمجي الذي تم نقله من AArch32 على بيانات ورمز برمجي مختلطَين، ما يؤدي إلى ظهور مشاكل. في كثير من الحالات، يمكن حلّ هذه المشاكل ببساطة مثل نقل الثوابت إلى قسم .data في ملف التجميع.

قد تحتاج إلى إعادة صياغة الرمز البرمجي المكتوب بخط اليد لفصل الثابتة المجمّعة محليًا.

أمثلة:

من المفترض ألا تتضمّن الملفات الثنائية التي ينشئها مُجمِّع Clang أي مشاكل متعلّقة باختلاط البيانات في الرمز البرمجي. إذا تم تضمين رمز تم إنشاؤه بواسطة مجموعة مُجمّع GNU (GCC) (من مكتبة ثابتة)، عليك فحص الملف الثنائي الناتج للتأكّد من عدم تجميع الثوابت في أقسام الرمز.

إذا كان من الضروري إجراء فحص ذاتي للرمز البرمجي في أقسام الرمز القابل للتنفيذ، يجب أولاً استدعاء mprotect لتمييز الرمز البرمجي على أنّه قابل للقراءة. بعد اكتمال العملية، يُرجى الاتصال برقم mprotect مرة أخرى لوضع علامة على السجلّ بأنّه غير قابل للقراءة.

تفعيل XOM

يكون وضع التنفيذ فقط مفعَّلاً تلقائيًا لجميع الملفات الثنائية 64 بت في نظام الإنشاء.

إيقاف XOM

يمكنك إيقاف وضع التنفيذ فقط على مستوى الوحدة، أو من خلال شجرة دليل فرعي بالكامل، أو بشكل عام لعملية إنشاء كاملة.

يمكن إيقاف XOM في الوحدات الفردية التي لا يمكن إعادة تنظيمها أو التي تحتاج إلى قراءة الرمز القابل للتنفيذ، وذلك من خلال ضبط المتغيّرَين LOCAL_XOM وxom على false.

// 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 في إعدادات المنتج.

يمكنك إيقاف ملفات bin التي يمكن تنفيذها فقط على مستوى النظام من خلال ضبط القيمة ENABLE_XOM=false على الأمر make.

make -j ENABLE_XOM=false

التحقُّق

لا تتوفّر اختبارات CTS أو اختبارات التحقّق لوحدة معالجة تعليمات فقط الذاكرة. يمكنك التحقّق يدويًا من الملفات الثنائية باستخدام readelf والتحقّق من علامات الشريحة.