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

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

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

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

أوضاع تشغيل MTE

لدى MTE ثلاثة أوضاع تشغيل:

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

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

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

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

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

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

تم تحسين هذا الوضع للأداء على حساب دقة تقارير الأخطاء ويمكن استخدامه كاكتشاف منخفض لأخطاء سلامة الذاكرة.
في حالة عدم تطابق العلامة، يستمر المعالج في التنفيذ حتى أقرب إدخال kernel (على سبيل المثال، مكالمة النظام أو مقاطعة المؤقت)، حيث ينهي العملية باستخدام 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_heap
LOCAL_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 ).
يمكن العثور عليها ضمن 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. وهذا يجعل من المفيد تمكين عمليات فحص أكثر صرامة على وحدات المعالجة المركزية (CPUs) عند طلب وضع فحص أقل صرامة، وذلك للحصول على فوائد اكتشاف الأخطاء من عمليات الفحص الأكثر صرامة دون الجوانب السلبية للأداء.
افتراضيًا، سيتم تشغيل العمليات التي تم تكوينها للتشغيل في وضع ASYNC في وضع ASYNC على كافة وحدات المعالجة المركزية (CPUs). لتكوين النواة لتشغيل هذه العمليات في وضع SYNC على وحدات معالجة مركزية معينة، يجب كتابة مزامنة القيمة إلى إدخال sysfs /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred في وقت التمهيد. يمكن القيام بذلك باستخدام برنامج نصي init. على سبيل المثال، لتكوين وحدات المعالجة المركزية (CPUs) 0-1 لتشغيل عمليات وضع ASYNC في وضع SYNC، ووحدات المعالجة المركزية (CPUs) 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 في الإنتاج. يوفر هذا أداة ذات حمل منخفض لاكتشاف وجود أخطاء تتعلق بسلامة الذاكرة في العملية بالإضافة إلى مزيد من الدفاع المتعمق. بمجرد اكتشاف الخطأ، يمكن للمطور الاستفادة من واجهات برمجة التطبيقات لوقت التشغيل للتبديل إلى وضع المزامنة والحصول على تتبع دقيق للمكدس من مجموعة عينات من المستخدمين.

نوصي بشدة بتكوين مستوى MTE المفضل الخاص بوحدة المعالجة المركزية لـ SoC. يتمتع الوضع Asymm عادةً بنفس خصائص الأداء مثل ASYNC، ويُفضل عليه دائمًا تقريبًا. غالبًا ما تُظهر النوى الصغيرة المرتبة أداءً مشابهًا في جميع الأوضاع الثلاثة، ويمكن تهيئتها لتفضل SYNC.

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

مكونات النظام الأساسي الممكّنة MTE

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

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

وقد تم اختيار هذه الأهداف بناء على المعايير التالية:

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

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