سكودو

Scudo هو مخصص ذاكرة ديناميكي في وضع المستخدم ، أو مخصص كومة ، مصمم ليكون مرنًا ضد الثغرات الأمنية ذات الصلة (مثل تجاوز سعة المخزن المؤقت ، والاستخدام بعد الحر ، والحر المزدوج ) مع الحفاظ على الأداء. يوفر تخصيص C القياسي وأساسيات إلغاء التخصيص (مثل malloc و free) ، بالإضافة إلى C ++ البدائية (مثل جديد وحذف).

يعد Scudo وسيلة تخفيف أكثر من كونه كاشفًا كاملًا لأخطاء الذاكرة مثل AddressSanitizer (ASan) .

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

في Android 10 ، يجب تمكين scudo على أساس ثنائي من خلال تعيين LOCAL_SANITIZE := scudo خيار scudo في ملف .mk أو sanitize: { scudo: true, } في ملف .bp.

Scudo هو مصدر مفتوح وجزء من مشروع مترجم LLVM. الوثائق متاحة على https://llvm.org/docs/ScudoHardenedAllocator.html . يتم شحن وقت تشغيل Scudo كجزء من سلسلة أدوات Android وتم إضافة الدعم إلى Soong و Make للسماح بسهولة تمكين المخصص في ثنائي.

يمكنك تمكين أو تعطيل التخفيف الإضافي داخل المخصص باستخدام الخيارات الموضحة أدناه.

التخصيص

يمكن تحديد بعض معلمات المخصص على أساس كل عملية من خلال عدة طرق:

  • بشكل ثابت: حدد دالة __scudo_default_options في البرنامج التي تُرجع سلسلة الخيارات المراد تحليلها. يجب أن تحتوي هذه الوظيفة على النموذج الأولي التالي: extern "C" const char *__scudo_default_options() .
  • ديناميكيًا: استخدم متغير البيئة SCUDO_OPTIONS الذي يحتوي على سلسلة الخيارات المراد تحليلها. الخيارات المحددة بهذه الطريقة تلغي أي تعريف تم إجراؤه من خلال __scudo_default_options .

الخيارات التالية متاحة.

خيار 64 بت الافتراضي 32 بت الافتراضي وصف
QuarantineSizeKb 256 64 الحجم (بالكيلو بايت) للعزل المستخدم لتأخير إلغاء تخصيص القطع الفعلي. قد تقلل القيمة الأقل من استخدام الذاكرة ولكنها تقلل من فعالية التخفيف ؛ تعود القيمة السالبة إلى القيم الافتراضية. يؤدي تعيين كل من هذا و ThreadLocalQuarantineSizeKb على الصفر إلى تعطيل العزل بالكامل.
QuarantineChunksUpToSize 2048 512 الحجم (بالبايت) حتى القطع التي يمكن عزلها.
ThreadLocalQuarantineSizeKb 64 16 حجم ذاكرة التخزين المؤقت لكل مؤشر ترابط (بالكيلو بايت) لإلغاء تحميل وحدة العزل العامة. قد تؤدي القيمة الأقل إلى تقليل استخدام الذاكرة ولكنها قد تزيد من التنازع على وحدة العزل العالمية. يؤدي تعيين كل من هذا و QuarantineSizeKb إلى الصفر إلى تعطيل العزل تمامًا.
DeallocationTypeMismatch false false تمكين الإبلاغ عن الأخطاء في malloc / حذف ، جديد / مجاني ، جديد / حذف []
DeleteSizeMismatch true true تمكن من الإبلاغ عن الخطأ عن عدم التطابق بين أحجام الجديدة والحذف.
ZeroContents false false يتيح عدم وجود محتويات مجموعة عند التخصيص وإلغاء التخصيص.
allocator_may_return_null false false تحديد إمكانية إرجاع المُخصص بدون قيمة عند حدوث خطأ قابل للاسترداد ، بدلاً من إنهاء العملية.
hard_rss_limit_mb 0 0 عندما يصل RSS للعملية إلى هذا الحد ، تنتهي العملية.
soft_rss_limit_mb 0 0 عندما يصل RSS للعملية إلى هذا الحد ، تفشل عمليات التخصيص الإضافية أو تُرجع null (اعتمادًا على قيمة allocator_may_return_null ) ، حتى يتراجع RSS للسماح بالتخصيصات الجديدة.
allocator_release_to_os_interval_ms غير متاح 5000 يؤثر فقط على مُخصص 64 بت. في حالة الضبط ، يحاول تحرير الذاكرة غير المستخدمة لنظام التشغيل ، ولكن ليس أكثر من هذا الفاصل الزمني (بالمللي ثانية). إذا كانت القيمة سالبة ، فلن يتم تحرير الذاكرة لنظام التشغيل.
abort_on_error true true في حالة الضبط ، تستدعي الأداة abort() بدلاً من _exit() بعد طباعة رسالة الخطأ.

تصديق

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

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

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

فيما يلي قائمة برسائل الخطأ الحالية وأسبابها المحتملة:

  • corrupted chunk header : فشل التحقق من المجموع الاختباري لرأس القطعة. من المحتمل أن يكون هذا بسبب أحد أمرين: تمت الكتابة فوق الرأس (جزئيًا أو كليًا) ، أو أن المؤشر الذي تم تمريره إلى الوظيفة ليس جزءًا.
  • race on chunk header : هناك خيطان مختلفان يحاولان معالجة الرأس نفسه في نفس الوقت. عادة ما يكون هذا من أعراض حالة السباق أو نقص عام في القفل عند إجراء عمليات على هذا الجزء.
  • invalid chunk state : القطعة ليست في الحالة المتوقعة لعملية معينة ، على سبيل المثال ، لم يتم تخصيصها عند محاولة تحريرها ، أو لم يتم عزلها عند محاولة إعادة تدويرها. الحر المزدوج هو السبب النموذجي لهذا الخطأ.
  • misaligned pointer : يتم فرض متطلبات المحاذاة الأساسية بقوة: 8 بايت على الأنظمة الأساسية 32 بت و 16 بايت على الأنظمة الأساسية 64 بت. إذا كان المؤشر الذي تم تمريره إلى وظائفنا لا يتناسب مع هؤلاء ، فإن المؤشر الذي يتم تمريره إلى إحدى الوظائف يكون خارج المحاذاة.
  • allocation type mismatch : عند تمكين هذا الخيار ، يجب أن تتطابق وظيفة إلغاء التخصيص التي يتم استدعاؤها على القطعة مع نوع الوظيفة التي تم استدعاؤها لتخصيصها. يمكن أن يؤدي هذا النوع من عدم التطابق إلى حدوث مشكلات أمنية.
  • invalid sized delete : عند استخدام عامل الحذف بحجم 14 C ++ ، وتمكين الاختيار الاختياري ، هناك عدم تطابق بين الحجم الذي تم تمريره عند إلغاء تخصيص جزء والحجم المطلوب عند تخصيصه. هذا عادةً ما يكون مشكلة في المترجم أو تشويشًا في نوع الكائن الذي يتم إلغاء تخصيصه.
  • تم RSS limit exhausted : تم تجاوز الحد الأقصى المحدد بشكل اختياري لـ RSS.

إذا كنت تقوم بتصحيح عطل في نظام التشغيل نفسه ، فيمكنك استخدام بنية HWASan OS . إذا كنت تقوم بتصحيح عطل في أحد التطبيقات ، فمن الممكن أيضًا استخدام إنشاء تطبيق HWASan .