اسکودو یک تخصیصدهنده حافظه پویا در حالت کاربر یا تخصیصدهنده هیپ است که به گونهای طراحی شده است که در برابر آسیبپذیریهای مربوط به هیپ (مانند سرریز بافر مبتنی بر هیپ ، استفاده پس از آزادسازی و آزادسازی مضاعف ) مقاوم باشد و در عین حال عملکرد را حفظ کند. این برنامه توابع اولیه تخصیص و آزادسازی استاندارد C (مانند malloc و free) و همچنین توابع اولیه C++ (مانند new و delete) را ارائه میدهد.
اسکودو بیشتر یک ابزار کاهشدهندهی خطا است تا یک ابزار تشخیص خطای حافظهی کامل مانند AddressSanitizer (ASan) .
از زمان انتشار اندروید ۱۱، از scudo برای تمام کدهای بومی استفاده میشود (به جز در دستگاههای با حافظه کم، که در آنها jemalloc هنوز استفاده میشود). در زمان اجرا، تمام تخصیصها و آزادسازیهای هیپ بومی برای تمام فایلهای اجرایی و وابستگیهای کتابخانهای آنها توسط Scudo مدیریت میشوند و در صورت تشخیص خرابی یا رفتار مشکوک در هیپ، این فرآیند متوقف میشود.
Scudo متنباز و بخشی از پروژه compiler-rt مربوط به LLVM است. مستندات آن در آدرس https://llvm.org/docs/ScudoHardenedAllocator.html موجود است. زمان اجرای Scudo به عنوان بخشی از زنجیره ابزار اندروید ارائه میشود و پشتیبانی از آن به Soong و Make اضافه شده است تا امکان فعالسازی آسان تخصیصدهنده در یک فایل باینری فراهم شود.
شما میتوانید با استفاده از گزینههای شرح داده شده در زیر، کاهش اضافی را در تخصیصدهنده فعال یا غیرفعال کنید.
سفارشیسازی
برخی از پارامترهای تخصیصدهنده را میتوان به چندین روش برای هر فرآیند تعریف کرد:
- به صورت ایستا: یک تابع
__scudo_default_optionsدر برنامه تعریف کنید که رشته گزینههایی را که باید تجزیه شوند، برگرداند. این تابع باید الگوی اولیه زیر را داشته باشد:extern "C" const char *__scudo_default_options(). - به صورت پویا: از متغیر محیطی
SCUDO_OPTIONSکه حاوی رشته گزینههایی است که باید تجزیه شوند، استفاده کنید. گزینههای تعریف شده به این روش، هر تعریفی را که از طریق__scudo_default_optionsانجام شود، لغو میکنند.
گزینههای زیر موجود است.
| گزینه | پیشفرض ۶۴ بیتی | پیشفرض ۳۲ بیتی | توضیحات |
|---|---|---|---|
QuarantineSizeKb | 256 | 64 | اندازه (برحسب کیلوبایت) قرنطینه که برای به تأخیر انداختن آزادسازی واقعی تکهها استفاده میشود. مقدار کمتر ممکن است استفاده از حافظه را کاهش دهد اما اثربخشی کاهش را نیز کم میکند؛ مقدار منفی به مقادیر پیشفرض برمیگردد. تنظیم هر دو مورد این و ThreadLocalQuarantineSizeKb روی صفر، قرنطینه را به طور کامل غیرفعال میکند. |
QuarantineChunksUpToSize | 2048 | 512 | اندازهای (بر حسب بایت) که میتوان تکهها را تا آن اندازه قرنطینه کرد. |
ThreadLocalQuarantineSizeKb | 64 | 16 | اندازه (برحسب کیلوبایت) حافظه پنهان هر رشته برای تخلیه قرنطینه سراسری استفاده میشود. مقدار کمتر ممکن است استفاده از حافظه را کاهش دهد اما ممکن است باعث افزایش رقابت در قرنطینه سراسری شود. تنظیم هر دو مورد این و QuarantineSizeKb روی صفر، قرنطینه را به طور کامل غیرفعال میکند. |
DeallocationTypeMismatch | false | false | گزارش خطا را در malloc/delete، new/free، new/delete[] فعال میکند. |
DeleteSizeMismatch | true | true | گزارش خطا در مورد عدم تطابق بین اندازههای new و delete را فعال میکند. |
ZeroContents | false | false | فعال کردن محتوای بدون قطعه (zero chunk) در هنگام تخصیص و آزادسازی |
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 | 5000 | ناموجود | فقط روی تخصیصدهندهی ۶۴ بیتی تأثیر میگذارد. در صورت تنظیم، سعی میکند حافظهی استفاده نشده را به سیستمعامل آزاد کند، اما نه بیشتر از این فاصله (به میلیثانیه). اگر مقدار منفی باشد، حافظه به سیستمعامل آزاد نمیشود. |
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: الزامات اساسی همترازی به شدت اعمال میشوند: ۸ بایت در پلتفرمهای ۳۲ بیتی و ۱۶ بایت در پلتفرمهای ۶۴ بیتی. اگر اشارهگری که به توابع ما ارسال میشود با این موارد مطابقت نداشته باشد، اشارهگر ارسالی به یکی از توابع ناهمتراز است. -
allocation type mismatch: وقتی این گزینه فعال باشد، تابع آزادسازی تخصیص که روی یک تکه فراخوانی میشود باید با نوع تابعی که برای تخصیص آن فراخوانی شده است، مطابقت داشته باشد. این نوع عدم تطابق میتواند مشکلات امنیتی ایجاد کند. -
invalid sized delete: وقتی از عملگر حذف با اندازه C++14 استفاده میشود و بررسی اختیاری آن فعال است، بین اندازهای که هنگام آزادسازی یک تکه داده شده و اندازهای که هنگام تخصیص آن درخواست شده است، عدم تطابق وجود دارد. این معمولاً یک مشکل کامپایلر یا یک سردرگمی نوع در شیء در حال آزادسازی است. -
RSS limit exhausted: از حداکثر RSS که به صورت اختیاری مشخص شده است، عبور شده است.
اگر در حال اشکالزدایی از یک خرابی در خود سیستم عامل هستید، میتوانید از نسخه سیستم عامل HWASan استفاده کنید. اگر در حال اشکالزدایی از یک خرابی در یک برنامه هستید، استفاده از نسخه برنامه HWASan نیز امکانپذیر است.