تفعيل إضافة وضع علامات الذاكرة

تقدّم بنية Arm v9 ميزة Memory Tagging Extension (MTE)، وهي تنفيذ على مستوى الأجهزة للذاكرة الموسومة.

على مستوى عالٍ، تضع ميزة MTE علامة على كل عملية تخصيص/إلغاء تخصيص للذاكرة باستخدام بيانات وصفية إضافية. يتم تعيين علامة لموقع الذاكرة، ويمكن بعد ذلك ربطها بمؤشرات تشير إلى موقع الذاكرة هذا. أثناء وقت التشغيل، يتحقّق وحدة المعالجة المركزية من تطابق المؤشر وعلامات البيانات الوصفية في كل عملية تحميل وتخزين.

في نظام التشغيل Android 12، يمكن لمخصّص مساحة التخزين المؤقت في الذاكرة الأساسية ومساحة المستخدمين زيادة حجم كل عملية تخصيص من خلال بيانات وصفية. يساعد ذلك في رصد أخطاء الاستخدام بعد التحرير وأخطاء تجاوز سعة المخزن المؤقت، وهي أكثر مصادر أخطاء أمان الذاكرة شيوعًا في قواعد الرموز البرمجية لدينا.

أوضاع تشغيل ميزة MTE

تتضمّن إضافة وضع علامات الذاكرة (MTE) ثلاثة أوضاع تشغيل:

  • الوضع المتزامن (SYNC)
  • الوضع غير المتزامن (ASYNC)
  • الوضع غير المتماثل (ASYMM)

الوضع المتزامن (SYNC)

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

ننصح باستخدام هذا الوضع أثناء الاختبار كبديل عن HWASan/KASAN أو في مرحلة الإنتاج عندما تمثّل العملية المستهدَفة مساحة عرضة للهجوم. بالإضافة إلى ذلك، عندما يشير الوضع ASYNC إلى وجود خطأ، يمكن الحصول على تقرير دقيق عن الخطأ باستخدام واجهات برمجة التطبيقات في وقت التشغيل للتبديل إلى الوضع SYNC.

عند التشغيل في وضع SYNC، تسجّل أداة تخصيص الذاكرة في Android عمليات تتبُّع تسلسل استدعاء الدوال البرمجية لجميع عمليات التخصيص وإلغاء التخصيص، وتستخدمها لتقديم تقارير أفضل عن الأخطاء تتضمّن شرحًا لخطأ في الذاكرة، مثل استخدام ذاكرة معيّنة بعد تفريغها (Use-After-Free) أو تجاوز المخزن المؤقت للذاكرة الديناميكية (Heap-Buffer-Overflow)، وعمليات تتبُّع تسلسل استدعاء الدوال البرمجية لأحداث الذاكرة ذات الصلة. وتوفّر هذه التقارير معلومات أكثر صلة بالسياق، ما يسهّل تتبُّع الأخطاء وإصلاحها.

الوضع غير المتزامن (ASYNC)

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

الوضع غير المتماثل (ASYMM)

توفّر ميزة إضافية في الإصدار 8.7-A من Arm، وهي وضع MTE غير المتماثل، فحصًا متزامنًا لعمليات قراءة الذاكرة، وفحصًا غير متزامن لعمليات كتابة الذاكرة، مع أداء مشابه لأداء الوضع ASYNC. في معظم الحالات، يكون هذا الوضع أفضل من وضع ASYNC، وننصحك باستخدامه بدلاً من وضع ASYNC كلما كان متاحًا.

لهذا السبب، لا تشير أي من واجهات برمجة التطبيقات الموضّحة أدناه إلى الوضع غير المتماثل. بدلاً من ذلك، يمكن ضبط نظام التشغيل لاستخدام الوضع غير المتزامن دائمًا عند طلب الوضع غير المتزامن. يُرجى الرجوع إلى قسم "ضبط مستوى 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_heap
LOCAL_SANITIZE_DIAG := memtag_heap

‫2- تفعيل إضافة وضع علامات الذاكرة (MTE) في دليل فرعي في شجرة المصدر باستخدام متغيّر منتج:

وضع MTE قائمة المواقع الجغرافية المضمَّنة قائمة الاستبعاد
async 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).
ويمكن العثور على هذه التغييرات ضمن System > Advanced > Developer options > App Compatibility Changes في قائمة الإعدادات العامة. يؤدي ضبط 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 في الوضعَين ASYMM أو SYNC مشابهًا لأداء ASYNC. ويجعل ذلك من المفيد تفعيل عمليات التحقّق الأكثر صرامة على وحدات المعالجة المركزية هذه عند طلب وضع تحقّق أقل صرامة، وذلك للاستفادة من مزايا رصد الأخطاء التي توفّرها عمليات التحقّق الأكثر صرامة بدون التأثير سلبًا في الأداء.
بشكلٍ تلقائي، سيتم تشغيل العمليات التي تم ضبطها على وضع ASYNC في وضع ASYNC على جميع وحدات المعالجة المركزية. لضبط النواة لتشغيل هذه العمليات في وضع SYNC على وحدات معالجة مركزية معيّنة، يجب كتابة القيمة sync في الإدخال sysfs /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred عند بدء التشغيل. يمكن إجراء ذلك باستخدام نص برمجي للتهيئة. على سبيل المثال، لضبط وحدات المعالجة المركزية 0-1 لتشغيل عمليات وضع ASYNC في وضع SYNC، ووحدات المعالجة المركزية 2-3 لاستخدام وضع ASYMM، يمكن إضافة ما يلي إلى عبارة init في نص برمجي init خاص بمورّد:

  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_OVERFLOW
  • M_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 المفضّل الخاص بوحدة المعالجة المركزية (CPU) لنظام على شريحة (SoC)، لأنّ وضع Asymm عادةً ما يتضمّن خصائص الأداء نفسها التي يتضمّنها وضع ASYNC، وهو دائمًا الخيار الأفضل. غالبًا ما تُظهر النوى الصغيرة التي تنفّذ التعليمات بالترتيب أداءً مشابهًا في جميع الأوضاع الثلاثة، ويمكن ضبطها لتفضيل وضع SYNC.

على المطوّرين التحقّق من حدوث الأعطال من خلال التحقّق من /data/tombstones أو logcat أو من خلال مراقبة مسار DropboxManager الخاص بالمورّد بحثًا عن أخطاء المستخدمين النهائيين. لمزيد من المعلومات حول تصحيح أخطاء الرمز البرمجي الأصلي لنظام Android، اطّلِع على المعلومات هنا.

مكوّنات المنصّة التي تم تفعيل ميزة "إضافة وضع علامات الذاكرة" فيها

في نظام التشغيل Android 12، تستخدم عدة مكونات نظام مهمة للأمان ميزة MTE ASYNC لرصد الأعطال التي تحدث للمستخدمين النهائيين، كما تعمل كطبقة إضافية من الدفاع المتعمّق. وهذه المكوّنات هي:

  • برامج خدمة وأدوات الشبكات (باستثناء netd)
  • البلوتوث وSecureElement وNFC HAL وتطبيقات النظام
  • statsd برنامج خفي
  • system_server
  • zygote64 (للسماح للتطبيقات بتفعيل ميزة MTE)

تم اختيار هذه الاستهدافات استنادًا إلى المعايير التالية:

  • عملية مميّزة (يتم تعريفها على أنّها عملية يمكنها الوصول إلى شيء لا يمكن لنطاق unprivileged_app SELinux الوصول إليه)
  • معالجة الإدخالات غير الموثوقة (قاعدة الاثنين)
  • انخفاض مقبول في الأداء (لا يؤدي الانخفاض إلى حدوث تأخير مرئي للمستخدم)

ننصح المورّدين بتفعيل MTE في مرحلة الإنتاج لعدد أكبر من المكوّنات، وذلك وفقًا للمعايير المذكورة أعلاه. أثناء عملية التطوير، ننصح باختبار هذه المكوّنات باستخدام وضع SYNC، وذلك لرصد الأخطاء التي يمكن إصلاحها بسهولة، وتقييم تأثير ASYNC على أدائها.
في المستقبل، يخطّط Android لتوسيع قائمة مكوّنات النظام التي يتم تفعيل MTE عليها، وذلك استنادًا إلى خصائص الأداء لتصاميم الأجهزة القادمة.