اسکودو

Scudo یک تخصیص دهنده حافظه پویا در حالت کاربر یا تخصیص دهنده هیپ است که به گونه ای طراحی شده است که در برابر آسیب پذیری های مرتبط با هیپ (مانند سرریز بافر مبتنی بر هیپ ، استفاده پس از آزاد شدن و دو برابر رایگان ) مقاوم باشد و در عین حال عملکرد را حفظ کند. این استانداردهای اولیه تخصیص و توزیع C (مانند malloc و رایگان)، و همچنین C++ اولیه (مانند جدید و حذف) را ارائه می دهد.

Scudo بیشتر یک کاهش دهنده است تا یک آشکارساز خطای حافظه کامل مانند AddressSanitizer (ASan) .

از زمان انتشار اندروید 11، scudo برای همه کدهای بومی استفاده می شود (به جز در دستگاه های با حافظه کم، جایی که هنوز از jemalloc استفاده می شود). در زمان اجرا، همه تخصیص‌ها و تخصیص‌های محلی Heap توسط Scudo برای همه فایل‌های اجرایی و وابستگی‌های کتابخانه‌ای آن‌ها سرویس می‌شوند و در صورت شناسایی خرابی یا رفتار مشکوک در پشته، این فرآیند متوقف می‌شود.

Scudo منبع باز و بخشی از پروژه کامپایلر-rt LLVM است. اسناد در https://llvm.org/docs/ScudoHardenedAllocator.html موجود است. زمان اجرا Scudo به عنوان بخشی از زنجیره ابزار اندروید و پشتیبانی به Soong و Make اضافه شد تا امکان فعال کردن آسان تخصیص دهنده را در یک باینری فراهم کند.

می توانید با استفاده از گزینه های شرح داده شده در زیر، کاهش اضافی را در تخصیص دهنده فعال یا غیرفعال کنید.

سفارشی سازی

برخی از پارامترهای تخصیص دهنده را می توان بر اساس هر فرآیند از چند راه تعریف کرد:

  • Statically: یک تابع __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/delete، new/free، new/delete[]
DeleteSizeMismatch true true گزارش خطا در مورد عدم تطابق بین اندازه های جدید و حذف را فعال می کند.
ZeroContents false false محتویات قطعه صفر را در تخصیص و تخصیص فعال می کند.
allocator_may_return_null false false مشخص می‌کند که تخصیص‌دهنده می‌تواند در صورت بروز خطای قابل بازیابی، به جای پایان دادن به فرآیند، null را برگرداند.
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 N/A 5000 فقط یک تخصیص دهنده 64 بیتی را تحت تأثیر قرار می دهد. در صورت تنظیم، سعی می کند حافظه استفاده نشده را در سیستم عامل آزاد کند، اما نه بیشتر از این فاصله زمانی (بر حسب میلی ثانیه). اگر مقدار منفی باشد، حافظه در سیستم عامل آزاد نمی شود.
abort_on_error true true در صورت تنظیم، ابزار پس از چاپ پیام خطا به جای _exit() abort() را فراخوانی می کند.

اعتبار سنجی

در حال حاضر هیچ آزمایش 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 : زمانی که از اپراتور حذف با اندازه C++14 استفاده می‌شود و بررسی اختیاری فعال است، بین اندازه‌ای که در هنگام اختصاص دادن یک قطعه ارسال شده و اندازه درخواست شده هنگام تخصیص آن ناسازگاری وجود دارد. این معمولاً یک مشکل کامپایلر یا یک سردرگمی نوع در شیء در حال واگذاری است.
  • RSS limit exhausted : از حداکثر RSS که به صورت اختیاری مشخص شده است تجاوز کرده است.

اگر در حال اشکال زدایی یک خرابی در خود سیستم عامل هستید، می توانید از ساخت سیستم عامل HWASan استفاده کنید. اگر در حال رفع اشکال یک خرابی در یک برنامه هستید، می‌توانید از ساخت برنامه HWASan نیز استفاده کنید.