تقدّم بنية Arm v9 إضافة وضع علامات الذاكرة (MTE) من Arm، وهي تنفيذ على مستوى الأجهزة للذاكرة التي تم وضع علامات عليها.
على مستوى عالٍ، تضع MTE علامات على كل عملية تخصيص/إلغاء تخصيص للذاكرة باستخدام بيانات وصفية إضافية. تخصّص MTE علامة لموقع في الذاكرة، ويمكن بعد ذلك ربطها بالمؤشرات التي تشير إلى هذا الموقع في الذاكرة. أثناء وقت التشغيل، يتحقّق وحدة المعالجة المركزية من تطابُق المؤشر وعلامات البيانات الوصفية في كل عملية تحميل وتخزين.
في Android 12، يمكن لمخصّص الذاكرة المؤقتة في النواة ومساحة المستخدمين زيادة كل عملية تخصيص باستخدام البيانات الوصفية. يساعد ذلك في رصد أخطاء "الاستخدام بعد التحرير" وأخطاء "تجاوز سعة المخزن المؤقت" ، وهي المصدر الأكثر شيوعًا لأخطاء أمان الذاكرة في قواعد الرموز البرمجية لدينا.
أوضاع تشغيل MTE
تتضمّن MTE ثلاثة أوضاع تشغيل:
- الوضع المتزامن (SYNC)
- الوضع غير المتزامن (ASYNC)
- الوضع غير المتماثل (ASYMM)
الوضع المتزامن (SYNC)
تم تحسين هذا الوضع لرصد الأخطاء بشكل صحيح بدلاً من الأداء، و
يمكن استخدامه كأداة دقيقة لرصد الأخطاء، عندما يكون من المقبول حدوث زيادة في الأداء. عند تفعيل وضع MTE SYNC، يعمل كإجراء أمني للحد من المخاطر.
في حال عدم تطابُق العلامة، توقف وحدة المعالجة تنفيذ التعليمات على الفور و
تنهي العملية باستخدام SIGSEGV (الرمز
SEGV_MTESERR) ومعلومات كاملة عن الوصول إلى الذاكرة والعنوان الذي حدث فيه الخطأ.
ننصح باستخدام هذا الوضع أثناء الاختبار كبديل لـ HWASan/KASAN أو في مرحلة الإنتاج عندما تمثّل العملية المستهدَفة سطحًا عرضة للهجوم. بالإضافة إلى ذلك، عندما يشير الوضع ASYNC إلى وجود خطأ، يمكن الحصول على تقرير دقيق عن الخطأ باستخدام واجهات برمجة التطبيقات في وقت التشغيل لتبديل التنفيذ إلى الوضع SYNC.
عند التشغيل في الوضع SYNC، يسجِّل مخصّص Android عمليات تتبُّع تسلسل استدعاء الدوال لجميع عمليات التخصيص وإلغاء التخصيص و يستخدمها لتقديم تقارير أفضل عن الأخطاء تتضمّن شرحًا لخطأ في الذاكرة، مثل "الاستخدام بعد التحرير" أو "تجاوز سعة المخزن المؤقت"، و عمليات تتبُّع تسلسل استدعاء الدوال لأحداث الذاكرة ذات الصلة. تقدّم هذه التقارير معلومات أكثر سياقية و تسهّل تتبُّع الأخطاء وحلّها.
الوضع غير المتزامن (ASYNC)
تم تحسين هذا الوضع لتحقيق الأداء بدلاً من دقة تقارير الأخطاء، ويمكن
استخدامه لرصد أخطاء أمان الذاكرة بتكلفة منخفضة.
في حال عدم تطابُق العلامة، تواصل وحدة المعالجة تنفيذ التعليمات إلى أن تصل إلى أقرب نقطة دخول إلى النواة (مثل استدعاء نظام أو مقاطعة مؤقت)، حيث تنهي العملية باستخدام SIGSEGV (الرمز SEGV_MTEAERR) بدون تسجيل العنوان الذي حدث فيه الخطأ أو الوصول إلى الذاكرة.
ننصح باستخدام هذا الوضع في مرحلة الإنتاج على قواعد الرموز البرمجية التي تم اختبارها جيدًا والتي من المعروف أنّ كثافة أخطاء أمان الذاكرة فيها منخفضة، ويتم تحقيق ذلك باستخدام الوضع SYNC أثناء الاختبار.
الوضع غير المتماثل (ASYMM)
توفّر ميزة إضافية في بنية Arm v8.7-A، وهي وضع MTE غير المتماثل، عمليات تحقّق متزامنة من عمليات قراءة الذاكرة، وعمليات تحقّق غير متزامنة من عمليات كتابة الذاكرة، مع أداء مشابه لأداء الوضع ASYNC. في معظم الحالات، يمثّل هذا الوضع تحسينًا على الوضع ASYNC، وننصح باستخدامه بدلاً من الوضع ASYNC كلما كان متاحًا.
لهذا السبب، لا تشير أي من واجهات برمجة التطبيقات الموضّحة أدناه إلى الوضع غير المتماثل بدلاً من ذلك، يمكن ضبط نظام التشغيل لاستخدام الوضع غير المتماثل دائمًا عند طلب الوضع غير المتزامن. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة ضبط مستوى MTE المفضّل الخاص بوحدة المعالجة المركزية.
MTE في مساحة المستخدمين
توضّح الأقسام التالية كيفية تفعيل MTE لعمليات النظام والتطبيقات تكون MTE غير مفعّلة تلقائيًا، ما لم يتم ضبط أحد الخيارات أدناه لعملية معيّنة (اطّلِع أدناه على المكوّنات التي تم تفعيل MTE لها).
تفعيل MTE باستخدام نظام التصميم
بصفتها خاصية على مستوى العملية، يتم التحكّم في MTE من خلال إعداد مدّة التصميم لـ الملف التنفيذي الرئيسي. تسمح الخيارات التالية بتغيير هذا الإعداد للملفات التنفيذية الفردية أو للمجلدات الفرعية بأكملها في شجرة المصدر. يتم تجاهل الإعداد في المكتبات أو أي هدف ليس ملفًا تنفيذيًا ولا اختبارًا.
1. تفعيل MTE في Android.bp (مثال)،
لمشروع معيّن:
| وضع MTE | الإعداد |
|---|---|
| MTE غير متزامن | sanitize: {
memtag_heap: true,
} |
| MTE متزامن | sanitize: {
memtag_heap: true,
diag: {
memtag_heap: true,
},
} |
أو في Android.mk:
| وضع MTE | الإعداد |
|---|---|
Asynchronous MTE |
LOCAL_SANITIZE := memtag_heap |
Synchronous MTE |
LOCAL_SANITIZE := memtag_heapLOCAL_SANITIZE_DIAG := memtag_heap |
2. تفعيل MTE في مجلد فرعي في شجرة المصدر باستخدام متغيّر منتج:
| وضع MTE | قائمة التضمين | قائمة الاستبعاد |
|---|---|---|
| غير متزامن | PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS
MEMTAG_HEAP_ASYNC_INCLUDE_PATHS |
PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS
MEMTAG_HEAP_EXCLUDE_PATHS |
| متزامن | PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS
MEMTAG_HEAP_SYNC_INCLUDE_PATHS |
أو
| وضع MTE | الإعداد |
|---|---|
| MTE غير متزامن | MEMTAG_HEAP_ASYNC_INCLUDE_PATHS |
| MTE متزامن | MEMTAG_HEAP_SYNC_INCLUDE_PATHS |
أو من خلال تحديد مسار الاستبعاد لملف تنفيذي:
| وضع MTE | الإعداد |
|---|---|
| MTE غير متزامن | PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS
MEMTAG_HEAP_EXCLUDE_PATHS |
| MTE متزامن |
مثال (استخدام مشابه لـ PRODUCT_CFI_INCLUDE_PATHS)
PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS=vendor/$(vendor)
PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS=vendor/$(vendor)/projectA \
vendor/$(vendor)/projectBتفعيل MTE باستخدام خصائص النظام
يمكن إلغاء إعدادات الإنشاء أعلاه في وقت التشغيل من خلال ضبط خاصية النظام التالية:
arm64.memtag.process.<basename> = (off|sync|async)
حيث يمثّل basename الاسم الأساسي للملف التنفيذي.
على سبيل المثال، لضبط /system/bin/ping أو /data/local/tmp/ping
لاستخدام MTE غير المتزامن، استخدِم adb shell setprop arm64.memtag.process.ping async.
تفعيل MTE باستخدام متغيّر بيئة
هناك طريقة أخرى لإلغاء إعداد الإنشاء للعمليات الأصلية (غير التطبيقات)
وهي تحديد متغيّر البيئة: MEMTAG_OPTIONS=(off|sync|async)
إذا تم تحديد كل من متغيّر البيئة وخاصية النظام، تكون الأولوية للمتغيّر.
تفعيل MTE للتطبيقات
إذا لم يتم تحديد MTE، تكون غير مفعّلة تلقائيًا، ولكن
يمكن للتطبيقات التي تريد استخدام MTE فعل ذلك من خلال ضبط android:memtagMode
ضمن العلامة <application> أو
<process> في
AndroidManifest.xml.
android:memtagMode=(off|default|sync|async)
عند ضبط العلامة <application>، تؤثر السمة في جميع العمليات التي يستخدمها التطبيق، ويمكن إلغاؤها للعمليات الفردية من خلال ضبط العلامة <process>
لإجراء التجارب، يمكن استخدام تغييرات
التوافق لضبط القيمة التلقائية للسمة
memtagMode لتطبيق لا يحدّد
أي قيمة في ملف البيان (أو يحدّد default).
تظهر هذه الخيارات ضمن النظام > الإعدادات المتقدّمة > خيارات المطوّرين
> تغييرات توافق التطبيقات في قائمة الإعدادات العامة. يؤدي ضبط
NATIVE_MEMTAG_ASYNC أو NATIVE_MEMTAG_SYNC إلى تفعيل MTE
لتطبيق معيّن. بدلاً من ذلك، يمكن ضبط ذلك باستخدام الأمر am
على النحو التالي:
$ adb shell am compat enable NATIVE_MEMTAG_[A]SYNC my.app.name
إنشاء صورة نظام MTE
ننصح بشدة بتفعيل MTE على جميع الملفات الثنائية الأصلية أثناء التطوير والتشغيل. يساعد ذلك في رصد أخطاء أمان الذاكرة في وقت مبكر وتوفير تغطية واقعية للمستخدمين، إذا تم تفعيلها في إصدارات الاختبار.
ننصح بشدة بتفعيل MTE في الوضع المتزامن على جميع الملفات الثنائية الأصلية أثناء التطوير
SANITIZE_TARGET=memtag_heap SANITIZE_TARGET_DIAG=memtag_heap m
كما هو الحال مع أي متغيّر في نظام التصميم، يمكن استخدام SANITIZE_TARGET كـ متغيّر بيئة أو إعداد make (على سبيل المثال، في ملف product.mk).
يؤدي ذلك إلى تفعيل MTE لجميع العمليات الأصلية، ولكن ليس لـ
التطبيقات (التي تم إنشاء نسخة منها من zygote64) التي يمكن تفعيل MTE لها
باتّباع التعليمات الواردة في تفعيل MTE للتطبيقات.
ضبط مستوى MTE المفضّل الخاص بوحدة المعالجة المركزية
في بعض وحدات المعالجة المركزية، قد يكون أداء MTE في الوضعَين ASYMM أو حتى SYNC مشابهًا لـ أداء الوضع ASYNC. لذلك، من المفيد تفعيل عمليات تحقّق أكثر صرامة على وحدات المعالجة المركزية هذه عندما يُطلب وضع تحقّق أقل صرامة، وذلك للاستفادة من مزايا رصد الأخطاء في عمليات التحقّق الأكثر صرامة بدون التأثير سلبًا في الأداء.
تلقائيًا، يتم تشغيل العمليات التي تم ضبطها للتشغيل في الوضع ASYNC في الوضع ASYNC
على جميع وحدات المعالجة المركزية. لضبط النواة لتشغيل هذه العمليات في الوضع SYNC على
وحدات معالجة مركزية معيّنة، يجب كتابة القيمة sync في
sysfs إدخال
/sys/devices/system/cpu/cpu<N>/mte_tcf_preferred في وقت
التشغيل. يمكن إجراء ذلك باستخدام نص برمجي للإعداد. على سبيل المثال، لضبط وحدتَي المعالجة المركزية 0 و1
لتشغيل عمليات الوضع ASYNC في الوضع SYNC، ووحدتَي المعالجة المركزية 2 و3 لتشغيل العمليات في الوضع ASYMM،
يمكن إضافة ما يلي إلى عبارة الإعداد في نص برمجي للإعداد خاص بمورّد:
write /sys/devices/system/cpu/cpu0/mte_tcf_preferred sync write /sys/devices/system/cpu/cpu1/mte_tcf_preferred sync write /sys/devices/system/cpu/cpu2/mte_tcf_preferred asymm write /sys/devices/system/cpu/cpu3/mte_tcf_preferred asymm
تحتوي شواهد القبور من عمليات الوضع ASYNC التي يتم تشغيلها في الوضع SYNC على تتبع تسلسل استدعاء الدوال البرمجية دقيقة لموقع الخطأ في الذاكرة. ومع ذلك، لا تتضمّن عمليات تتبُّع تسلسل استدعاء الدوال البرمجية للتخصيص أو إلغاء التخصيص. لا تتوفّر عمليات تتبُّع تسلسل استدعاء الدوال هذه إلا إذا تم ضبط العملية للتشغيل في الوضع SYNC.
int mallopt(M_THREAD_DISABLE_MEM_INIT, level)
حيث level هي 0 أو 1.
يؤدي ذلك إلى إيقاف تهيئة الذاكرة في `malloc`، ويتجنّب تغيير علامات الذاكرة ما لم يكن ذلك ضروريًا لضمان صحة البيانات.
int mallopt(M_MEMTAG_TUNING, level)
حيث level هي:
M_MEMTAG_TUNING_BUFFER_OVERFLOWM_MEMTAG_TUNING_UAF
يختار ذلك استراتيجية تخصيص العلامات.
- الإعداد التلقائي هو
M_MEMTAG_TUNING_BUFFER_OVERFLOW. M_MEMTAG_TUNING_BUFFER_OVERFLOWتفعِّل الرصد الحتمي لأخطاء تجاوز سعة المخزن المؤقت الخطي وأخطاء نقص سعة المخزن المؤقت من خلال تخصيص قيم علامات مميّزة لعمليات التخصيص المجاورة. يقل احتمال رصد أخطاء "الاستخدام بعد التحرير" في هذا الوضع قليلاً لأنّ نصف قيم العلامات المحتمَلة فقط يكون متاحًا لكل موقع في الذاكرة. لا يمكن لـ MTE رصد تجاوز سعة المخزن المؤقت ضمن حبيبة العلامة نفسها (قطعة محاذية بحجم 16 بايت)، وقد لا ترصد تجاوزات السعة الصغيرة حتى في هذا الوضع. لا يمكن أن يكون تجاوز سعة المخزن المؤقت هذا سببًا في إتلاف الذاكرة ، لأنّ الذاكرة ضمن حبيبة واحدة لا تُستخدم أبدًا لعمليات تخصيص متعددة.M_MEMTAG_TUNING_UAFتفعِّل علامات عشوائية بشكل مستقل لاحتمالية موحّدة تبلغ% 93 تقريبًا لرصد كل من الأخطاء المكانية (تجاوز سعة المخزن المؤقت) والأخطاء الزمنية (الاستخدام بعد التحرير).
بالإضافة إلى واجهات برمجة التطبيقات الموضّحة أعلاه، قد يرغب المستخدمون المتمرّسون في التعرّف على ما يلي:
- يمكن أن يؤدي ضبط سجلّ الأجهزة
PSTATE.TCOإلى إيقاف التحقّق من العلامات مؤقتًا (مثال). على سبيل المثال، عند نسخ نطاق من الذاكرة يتضمّن محتوى علامات غير معروف، أو معالجة مؤثِّر سلبي في الأداء في حلقة نشطة. - عند استخدام
M_HEAP_TAGGING_LEVEL_SYNC، يقدّم معالج أعطال النظام معلومات إضافية، مثل عمليات تتبُّع تسلسل استدعاء الدوال للتخصيص وإلغاء التخصيص. تتطلّب هذه الوظيفة الوصول إلى وحدات بت العلامات ويتم تفعيلها من خلال تمرير العلامةSA_EXPOSE_TAGBITSعند ضبط معالج الإشارات. ننصح أي برنامج يضبط معالج الإشارات الخاص به ويفوّض الأعطال غير المعروفة إلى معالج النظام بفعل الشيء نفسه.
MTE في النواة
لتفعيل KASAN المُسرَّع بواسطة MTE للنواة، اضبط النواة باستخدام
CONFIG_KASAN=y, CONFIG_KASAN_HW_TAGS=y. يتم تفعيل عمليات الضبط هذه تلقائيًا على نِوى GKI، بدءًا من Android
12-5.10.
يمكنك التحكّم في ذلك في وقت التشغيل باستخدام وسيطات سطر الأوامر التالية:
kasan=[on|off]: لتفعيل KASAN أو إيقافها (الإعداد التلقائي:on)kasan.mode=[sync|async]- : للاختيار بين الوضع المتزامن وغير المتزامن (الإعداد التلقائي:sync)kasan.stacktrace=[on|off]: لتحديد ما إذا كان سيتم جمع عمليات تتبُّع تسلسل استدعاء الدوال (الإعداد التلقائي:on)- يتطلّب جمع عمليات تتبُّع تسلسل استدعاء الدوال البرمجية أيضًا
stack_depot_disable=off.
- يتطلّب جمع عمليات تتبُّع تسلسل استدعاء الدوال البرمجية أيضًا
kasan.fault=[report|panic]- لتحديد ما إذا كان سيتم طباعة التقرير فقط، أو إيقاف النواة أيضًا (الإعداد التلقائي:report). بغض النظر عن هذا الخيار، يتم إيقاف التحقّق من العلامات بعد أول خطأ يتم الإبلاغ عنه.
الاستخدام المقترَح
ننصح بشدة باستخدام الوضع SYNC أثناء التشغيل والتطوير والاختبار. يجب تفعيل هذا الخيار على مستوى العالم لجميع العمليات باستخدام متغيّر البيئة أو مع نظام التصميم. في هذا الوضع، يتم رصد الأخطاء في وقت مبكر من عملية التطوير، ويتم تثبيت قاعدة الرموز البرمجية بشكل أسرع، ويتم تجنُّب تكلفة رصد الأخطاء لاحقًا في مرحلة الإنتاج.
ننصح بشدة باستخدام الوضع ASYNC في مرحلة الإنتاج. يوفّر ذلك أداة منخفضة التكلفة لرصد وجود أخطاء أمان الذاكرة في إحدى العمليات، بالإضافة إلى إجراءات دفاعية إضافية. بعد رصد خلل، يمكن للمطوّر الاستفادة من واجهات برمجة التطبيقات في وقت التشغيل للتبديل إلى الوضع SYNC والحصول على تتبع تسلسل استدعاء الدوال البرمجية دقيقة من مجموعة عيّنات من المستخدمين.
ننصح بشدة بضبط مستوى MTE المفضّل الخاص بوحدة المعالجة المركزية لـ منظومة على رقاقة (SoC). عادةً ما يكون للوضع Asymm خصائص الأداء نفسها للوضع ASYNC، ويكون دائمًا تقريبًا أفضل منه. غالبًا ما تُظهر النِوى الصغيرة التي تعمل بالترتيب أداءً مشابهًا في جميع الأوضاع الثلاثة، ويمكن ضبطها لتفضيل الوضع SYNC.
على المطوّرين التحقّق من وجود الأعطال من خلال التحقّق من
/data/tombstones,
logcat أو من خلال مراقبة سلسلة نقل بيانات المورّد DropboxManager
لرصد أخطاء المستخدمين النهائيين. لمزيد من المعلومات عن تصحيح الأخطاء في الرموز البرمجية الأصلية لنظام Android، يُرجى الاطّلاع على
المعلومات هنا.
مكوّنات المنصة التي تم تفعيل MTE لها
في Android 12، تستخدم عدد من مكوّنات النظام المهمة للأمان وضع MTE ASYNC لرصد أعطال المستخدمين النهائيين والعمل كطبقة إضافية من إجراءات الدفاع المتعمّق. هذه المكوّنات هي:
- البرامج الخفية والأدوات المساعدة للشبكات (باستثناء
netd) - وحدات HAL للبلوتوث وSecureElement وNFC وتطبيقات النظام
- البرنامج الخفي
statsd system_serverzygote64(للسماح للتطبيقات بالاشتراك في استخدام MTE)
تم اختيار هذه الأهداف استنادًا إلى المعايير التالية:
- عملية مميزة (محدّدة كعملية يمكنها الوصول إلى شيء لا يمكن لمجال SELinux `unprivileged_app` الوصول إليه)
- عمليات الإدخال غير الموثوق بها (القاعدة الاثنين)
- انخفاض الأداء المقبول (لا يؤدي الانخفاض إلى حدوث وقت استجابة مرئي للمستخدم )
نشجّع المورّدين على تفعيل MTE في مرحلة الإنتاج لمزيد من المكوّنات، باتّباع المعايير المذكورة أعلاه. أثناء التطوير، ننصح باختبار هذه المكوّنات باستخدام الوضع SYNC، لرصد الأخطاء التي يمكن إصلاحها بسهولة، وتقييم تأثير الوضع ASYNC في أدائها.
نخطط لتوسيع قائمة مكوّنات النظام التي تم تفعيل MTE لها ، استنادًا إلى خصائص الأداء لتصاميم الأجهزة القادمة.