UndefinedBehaviorSanitizer

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

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

يتم تضمين تجاوز عدد صحيح بدون إشارة ، على الرغم من أنه ليس سلوكًا غير محدد تقنيًا ، في المطهر ويتم استخدامه في العديد من وحدات 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 ، بينما لا يمكن استخدام الافتراضي إلا مع 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 UndefinedBehaviorSanitizer (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 في ملف makefile ، أضف:

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 هي مجموعة من الخيارات معبأة مسبقًا لمطهرات تجاوز عدد صحيح فردي موقعة وغير موقعة مع قائمة BLOCKLIST افتراضية .

تتيح مجموعة الخصائص 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's __builtin _ * _ الفائض ( مثال )
  • تعطيل التعقيم في الوظيفة عن طريق تحديد السمة no_sanitize ( مثال )
  • تعطيل تعقيم وظيفة أو ملف مصدر عبر ملف BLOCKLIST ( مثال )

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

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

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

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

تعطيل IntSan

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

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

تصديق

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

تطهير الحدود

يضيف BoundsSanitizer (BoundSan) أدوات القياس إلى الثنائيات لإدراج عمليات التحقق من الحدود حول عمليات الوصول إلى الصفيف. تتم إضافة هذه الفحوصات إذا لم يتمكن المترجم من إثبات في وقت الترجمة أن الوصول سيكون آمنًا وإذا كان حجم الصفيف معروفًا في وقت التشغيل ، بحيث يمكن التحقق منه. ينشر Android 10 BoundSan في تقنية Bluetooth وبرامج الترميز. يتم توفير 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 في الوظائف والملفات المصدر مع BLOCKLISTs أو سمات الوظيفة. من الأفضل الحفاظ على تمكين 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]'