UndefinedBehaviorSanitizer

يقوم UnifiedBehaviorSanitizer (UBSan) بتنفيذ أدوات وقت الترجمة للتحقق من أنواع مختلفة من السلوك غير المحدد. في حين أن UBSan قادر على اكتشاف العديد من الأخطاء السلوكية غير المحددة ، فإن Android يدعم:

  • تنسيق
  • منطقي
  • الحدود
  • التعداد
  • تعويم المصبوب الفائض
  • تعويم القسمة على صفر
  • عدد صحيح القسمة على صفر
  • سمة غير فارغة
  • باطل
  • يعود
  • إرجاع سمة غير فارغة
  • قاعدة التحول
  • التحول الأس
  • توقيع عدد صحيح-تجاوز
  • لا يمكن الوصول إليه
  • تجاوز عدد صحيح غير موقعة
  • فلا ملزمة

يتم تضمين unsigned-integer-overflow، على الرغم من أنه ليس سلوكًا غير محدد من الناحية الفنية، في المطهر ويستخدم في العديد من وحدات Android، بما في ذلك مكونات خادم الوسائط، للتخلص من أي ثغرات أمنية كامنة لتجاوز الأعداد الصحيحة.

تطبيق

في نظام بناء Android، يمكنك تمكين UBSan عالميًا أو محليًا. لتمكين UBSan عالميًا، قم بتعيين SANITIZE_TARGET في Android.mk. لتمكين UBSan على مستوى كل وحدة، قم بتعيين LOCAL_SANITIZE وحدد السلوكيات غير المحددة التي تريد البحث عنها في Android.mk. على سبيل المثال:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0

LOCAL_SRC_FILES:= sanitizer-status.c

LOCAL_MODULE:= sanitizer-status

LOCAL_SANITIZE := alignment bounds null unreachable integer
LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer

include $(BUILD_EXECUTABLE)

وتكوين المخطط المكافئ (Android.bp):

cc_binary {

    cflags: [
        "-std=c11",
        "-Wall",
        "-Werror",
        "-O0",
    ],

    srcs: ["sanitizer-status.c"],

    name: "sanitizer-status",

    sanitize: {
        misc_undefined: [
            "alignment",
            "bounds",
            "null",
            "unreachable",
            "integer",
        ],
        diag: {
            misc_undefined: [
                "alignment",
                "bounds",
                "null",
                "unreachable",
                "integer",
            ],
        },
    },

}

اختصارات UBSan

يحتوي Android أيضًا على اختصارين، integer و default-ub ، لتمكين مجموعة من المطهرات في نفس الوقت. يتيح عدد صحيح إمكانية integer-divide-by-zero signed-integer-overflow unsigned-integer-overflow . يمكّن default-ub عمليات التحقق التي تحتوي على الحد الأدنى من مشكلات أداء المترجم: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound . يمكن استخدام فئة معقم الأعداد الصحيحة مع SANITIZE_TARGET وLOCAL_SANITIZE، بينما لا يمكن استخدام default-ub إلا مع SANITIZE_TARGET.

الإبلاغ عن الأخطاء بشكل أفضل

يستدعي تطبيق UBSan الافتراضي لنظام Android وظيفة محددة عند مواجهة سلوك غير محدد. بشكل افتراضي، يتم إحباط هذه الوظيفة. ومع ذلك، بدءًا من أكتوبر 2016، أصبح لدى UBSan على Android مكتبة وقت تشغيل اختيارية توفر تقارير أكثر تفصيلاً عن الأخطاء، بما في ذلك نوع السلوك غير المحدد الذي تمت مواجهته، ومعلومات سطر التعليمات البرمجية للملف والمصدر. لتمكين الإبلاغ عن الأخطاء باستخدام عمليات التحقق من الأعداد الصحيحة، قم بإضافة ما يلي إلى ملف Android.mk:

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

تعمل قيمة LOCAL_SANITIZE على تمكين المطهر أثناء الإنشاء. يقوم LOCAL_SANITIZE_DIAG بتشغيل وضع التشخيص للمطهر المحدد. من الممكن تعيين LOCAL_SANITIZE وLOCAL_SANITIZE_DIAG على قيم مختلفة، ولكن يتم تمكين عمليات التحقق هذه فقط في LOCAL_SANITIZE. إذا لم يتم تحديد التحقق في LOCAL_SANITIZE، ولكن تم تحديده في LOCAL_SANITIZE_DIAG، فلن يتم تمكين التحقق ولن يتم تقديم رسائل تشخيصية.

فيما يلي مثال على المعلومات التي توفرها مكتبة وقت التشغيل UBSan:

pixel-xl:/ # sanitizer-status ubsan
sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')

تعقيم الفائض الصحيح

يمكن أن يؤدي تجاوز الأعداد الصحيحة غير المقصودة إلى تلف الذاكرة أو ثغرات أمنية في الكشف عن المعلومات في المتغيرات المرتبطة بالوصول إلى الذاكرة أو تخصيص الذاكرة. لمكافحة ذلك، أضفنا مطهرات الفائض الصحيح الموقعة وغير الموقعة من Clang's UnifiedBehaviorSanitizer (UBSan) لتقوية إطار عمل الوسائط في Android 7.0. في Android 9، قمنا بتوسيع UBSan ليشمل المزيد من المكونات وتحسين دعم نظام البناء له.

تم تصميم هذا لإضافة عمليات فحص حول العمليات/التعليمات الحسابية - التي قد تتجاوز الحد - لإجهاض العملية بأمان في حالة حدوث تجاوز. يمكن لهذه المطهرات التخفيف من فئة كاملة من تلف الذاكرة ونقاط الضعف في الكشف عن المعلومات حيث يكون السبب الجذري هو تجاوز عدد صحيح، مثل ثغرة Stagefright الأصلية.

الأمثلة والمصادر

يتم توفير Integer Overflow Sanitization (IntSan) بواسطة المترجم ويضيف أدوات إلى الملف الثنائي أثناء وقت الترجمة لاكتشاف التجاوزات الحسابية. يتم تمكينه افتراضيًا في المكونات المختلفة عبر النظام الأساسي، على سبيل المثال /platform/external/libnl/Android.bp .

تطبيق

يستخدم IntSan مطهرات الفائض الصحيح الموقعة وغير الموقعة من UBSan. يتم تمكين هذا التخفيف على مستوى كل وحدة نمطية. فهو يساعد في الحفاظ على أمان المكونات الهامة لنظام Android ويجب عدم تعطيله.

نحن نشجعك بشدة على تمكين Integer Overflow Sanitization للمكونات الإضافية. المرشحون المثاليون هم الكود الأصلي المميز أو الكود الأصلي الذي يوزع مدخلات المستخدم غير الموثوق بها. هناك عبء صغير على الأداء مرتبط بالمطهر الذي يعتمد على استخدام الكود وانتشار العمليات الحسابية. توقع نسبة مئوية صغيرة من النفقات العامة واختبر ما إذا كان الأداء يمثل مصدر قلق.

دعم IntSan في ملفات makefiles

لتمكين IntSan في ملف تعريف، أضف:

LOCAL_SANITIZE := integer_overflow
    # Optional features
    LOCAL_SANITIZE_DIAG := integer_overflow
    LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
  • يأخذ LOCAL_SANITIZE قائمة مفصولة بفواصل من المطهرات، مع كون integer_overflow عبارة عن مجموعة من الخيارات المعبأة مسبقًا لمطهرات تجاوز السعة الفردية الموقعة وغير الموقعة مع قائمة الحظر الافتراضية .
  • يقوم LOCAL_SANITIZE_DIAG بتشغيل وضع التشخيص للمطهرات. استخدم وضع التشخيص فقط أثناء الاختبار لأن هذا لن يتم إيقافه عند تجاوز السعة، مما يلغي تمامًا الميزة الأمنية للتخفيف. راجع استكشاف الأخطاء وإصلاحها للحصول على تفاصيل إضافية.
  • يتيح لك LOCAL_SANITIZE_BLOCKLIST تحديد ملف BLOCKLIST لمنع تنظيف الوظائف والملفات المصدر. راجع استكشاف الأخطاء وإصلاحها للحصول على تفاصيل إضافية.

إذا كنت تريد المزيد من التحكم الدقيق، قم بتمكين المطهرات بشكل فردي باستخدام إحدى العلامتين أو كلتيهما:

LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow
    LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow

دعم IntSan في ملفات المخطط

لتمكين معالجة تجاوز السعة الصحيحة في ملف مخطط، مثل /platform/external/libnl/Android.bp ، أضف:

   sanitize: {
          integer_overflow: true,
          diag: {
              integer_overflow: true,
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

كما هو الحال مع إنشاء الملفات، فإن الخاصية integer_overflow عبارة عن مجموعة من الخيارات المعبأة مسبقًا لمطهرات تجاوز السعة الصحيحة الموقعة وغير الموقعة مع قائمة الحظر الافتراضية .

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

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

لتمكين المطهرات بشكل فردي، استخدم:

   sanitize: {
          misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
          diag: {
              misc_undefined: ["signed-integer-overflow",
                               "unsigned-integer-overflow",],
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

استكشاف الأخطاء وإصلاحها

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

للعثور على عمليات الإجهاض الناجمة عن التعقيم في تصميمات المستخدم، ابحث عن أعطال SIGABRT باستخدام رسائل الإجهاض التي تشير إلى تجاوز السعة الذي اكتشفه UBSan، مثل:

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/surfaceflinger <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: sub-overflow'

يجب أن يتضمن تتبع المكدس الدالة التي تسبب الإحباط، ومع ذلك، قد لا تكون التجاوزات التي تحدث في الوظائف المضمنة واضحة في تتبع المكدس.

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

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

بمجرد تحديد موقع العملية الحسابية التي بها مشكلات، تأكد من أن التجاوز سليم ومقصود (على سبيل المثال ليس له آثار أمنية). يمكنك معالجة الإجهاض المطهر عن طريق:

  • إعادة هيكلة الكود لتجنب التجاوز ( مثال )
  • التجاوز بشكل صريح عبر وظائف Clang __builtin_*_overflow ( مثال )
  • تعطيل التعقيم في الوظيفة عن طريق تحديد السمة no_sanitize ( مثال )
  • تعطيل تعقيم وظيفة أو ملف مصدر عبر ملف BLOCKLIST ( مثال )

يجب عليك استخدام الحل الأكثر دقة قدر الإمكان. على سبيل المثال، دالة كبيرة تحتوي على العديد من العمليات الحسابية وعملية واحدة متجاوزة يجب أن تتم إعادة هيكلة العملية الفردية بدلاً من إدراج الدالة بأكملها في قائمة الحظر.

تتضمن الأنماط الشائعة التي قد تؤدي إلى حدوث فيضانات حميدة ما يلي:

  • عمليات الإرسال الضمنية حيث يحدث تجاوز غير موقّع قبل إرسالها إلى نوع موقّع ( مثال )
  • عمليات حذف القائمة المرتبطة التي تقلل من مؤشر الحلقة عند الحذف ( مثال )
  • تعيين نوع غير موقع إلى -1 بدلاً من تحديد القيمة القصوى الفعلية ( مثال )
  • الحلقات التي تقلل عددًا صحيحًا غير موقّع في الشرط ( مثال ، مثال )

من المستحسن أن يتأكد المطورون من أن الحالات التي يكتشف فيها المطهر فائضًا أنه حميد بالفعل ولا توجد آثار جانبية غير مقصودة أو آثار أمنية قبل تعطيل عملية التعقيم.

تعطيل IntSan

يمكنك تعطيل IntSan باستخدام قوائم الحظر أو سمات الوظيفة. قم بالتعطيل بشكل مقتصد وفقط عندما تكون إعادة بناء التعليمات البرمجية غير معقولة أو إذا كانت هناك مشكلة في الأداء.

راجع وثائق Clang الأولية للحصول على مزيد من المعلومات حول تعطيل IntSan باستخدام سمات الوظيفة وتنسيق ملف BLOCKLIST . يجب تحديد نطاق قائمة الحظر لمطهر معين باستخدام أسماء الأقسام التي تحدد المطهر المستهدف لتجنب التأثير على المطهرات الأخرى.

تصديق

حاليًا، لا يوجد اختبار CTS خصيصًا لتعقيم Integer Overflow. وبدلاً من ذلك، تأكد من اجتياز اختبارات CTS مع تمكين IntSan أو بدونه للتحقق من عدم تأثيره على الجهاز.

تعقيم الحدود

يضيف BoundsSanitizer (BoundSan) أدوات إلى الثنائيات لإدراج عمليات فحص الحدود حول عمليات الوصول إلى المصفوفة. تتم إضافة عمليات التحقق هذه إذا لم يتمكن المترجم من إثبات أن الوصول سيكون آمنًا في وقت الترجمة، وإذا كان حجم المصفوفة معروفًا في وقت التشغيل، بحيث يمكن التحقق منه. يقوم Android 10 بنشر BoundSan في البلوتوث وبرامج الترميز. يتم توفير BoundSan بواسطة المترجم ويتم تمكينه افتراضيًا في المكونات المختلفة عبر النظام الأساسي.

تطبيق

يستخدم BoundSan مطهر حدود UBSan . يتم تمكين هذا التخفيف على مستوى كل وحدة نمطية. فهو يساعد في الحفاظ على أمان المكونات الهامة لنظام Android ويجب عدم تعطيله.

نحن نشجعك بشدة على تمكين BoundSan للمكونات الإضافية. المرشحون المثاليون هم الكود الأصلي المميز أو الكود الأصلي المعقد الذي يوزع مدخلات المستخدم غير الموثوق بها. يعتمد عبء الأداء المرتبط بتمكين BoundSan على عدد عمليات الوصول إلى المصفوفة التي لا يمكن إثبات أمانها. توقع نسبة مئوية صغيرة من النفقات العامة في المتوسط ​​واختبر ما إذا كان الأداء يمثل مصدر قلق.

تمكين BoundSan في ملفات المخطط

يمكن تمكين BoundSan في ملفات المخططات عن طريق إضافة "bounds" إلى خاصية التعقيم misc_undefined للوحدات الثنائية ووحدات المكتبة:

    sanitize: {
       misc_undefined: ["bounds"],
       diag: {
          misc_undefined: ["bounds"],
       },
       BLOCKLIST: "modulename_BLOCKLIST.txt",
دياج

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

قائمة الحظر

تسمح الخاصية BLOCKLIST بتحديد ملف BLOCKLIST الذي يمكن للمطورين استخدامه لمنع تنظيف الوظائف والملفات المصدر. استخدم هذه الخاصية فقط إذا كان الأداء يمثل مصدر قلق وكانت الملفات/الوظائف المستهدفة تساهم بشكل كبير. قم بمراجعة هذه الملفات/الوظائف يدويًا للتأكد من أن الوصول إلى المصفوفة آمن. راجع استكشاف الأخطاء وإصلاحها للحصول على تفاصيل إضافية.

تمكين BoundSan في ملفات makefiles

يمكن تمكين BoundSan في ملفات makefiles عن طريق إضافة "bounds" إلى المتغير LOCAL_SANITIZE للوحدات الثنائية ووحدات المكتبة:

    LOCAL_SANITIZE := bounds
    # Optional features
    LOCAL_SANITIZE_DIAG := bounds
    LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt

يقبل LOCAL_SANITIZE قائمة المطهرات مفصولة بفاصلة.

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

يسمح LOCAL_SANITIZE_BLOCKLIST بتحديد ملف BLOCKLIST الذي يسمح للمطورين بمنع الوظائف والملفات المصدر من التعقيم. استخدم هذه الخاصية فقط إذا كان الأداء يمثل مصدر قلق وكانت الملفات/الوظائف المستهدفة تساهم بشكل كبير. قم بمراجعة هذه الملفات/الوظائف يدويًا للتأكد من أن الوصول إلى المصفوفة آمن. راجع استكشاف الأخطاء وإصلاحها للحصول على تفاصيل إضافية.

تعطيل BoundSan

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

لمزيد من المعلومات حول تعطيل BoundSan مع سمات الوظيفة وتنسيق ملف BLOCKLIST ، راجع وثائق Clang LLVM. قم بنطاق قائمة الحظر على المطهر المعين باستخدام أسماء الأقسام التي تحدد المطهر المستهدف لتجنب التأثير على المطهرات الأخرى.

تصديق

لا يوجد اختبار CTS خصيصًا لـ BoundSan. بدلاً من ذلك، تأكد من اجتياز اختبارات CTS مع تمكين BoundSan أو بدونه للتحقق من أنه لا يؤثر على الجهاز.

استكشاف الأخطاء وإصلاحها

قم باختبار المكونات بدقة بعد تمكين BoundSan للتأكد من معالجة أي عمليات وصول خارج الحدود لم يتم اكتشافها مسبقًا.

يمكن التعرف على أخطاء BoundSan بسهولة لأنها تتضمن رسالة إحباط علامة مميزة التالية:

    pid: ###, tid: ###, name: Binder:###  >>> /system/bin/foobar <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: out-of-bounds'

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

    external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'