برای کسب اطلاعات در مورد نحوه خواندن خرابیهای HWASan به بخش درک گزارشهای HWASan مراجعه کنید!
ابزار تشخیص خطای حافظه با کمک سختافزار (HWASan) ابزاری مشابه AddressSanitizer است. HWASan در مقایسه با ASan از رم بسیار کمتری استفاده میکند، که آن را برای پاکسازی کل سیستم مناسب میکند. HWASan فقط در اندروید ۱۰ و بالاتر و فقط در سختافزار AArch64 در دسترس است.
اگرچه HWASan در درجه اول برای کد C/C++ مفید است، اما میتواند به اشکالزدایی کد جاوا که باعث خرابی در C/C++ مورد استفاده برای پیادهسازی رابطهای جاوا میشود نیز کمک کند. این ابزار مفید است زیرا خطاهای حافظه را هنگام وقوع شناسایی میکند و شما را مستقیماً به کد مسئول هدایت میکند.
در مقایسه با ASan کلاسیک، HWASan دارای موارد زیر است:
- سربار پردازنده مشابه (~۲ برابر)
- سربار مشابه در اندازه کد (۴۰ تا ۵۰ درصد)
- سربار رم بسیار کمتر (۱۰٪ - ۳۵٪)
HWASan همان مجموعه اشکالات ASan را شناسایی میکند:
- سرریز/کمریز بافر پشته و هیپ
- استفاده از هیپ پس از آزادسازی
- استفاده از پشته در خارج از محدوده
- دو برابر رایگان/وحشی رایگان
علاوه بر این، HWASan استفاده از پشته را پس از بازگشت تشخیص میدهد.
HWASan (همانند ASan) با UBSan سازگار است، هر دو میتوانند همزمان روی یک هدف فعال شوند.
جزئیات و محدودیتهای پیادهسازی
HWASan مبتنی بر رویکرد برچسبگذاری حافظه است، که در آن یک مقدار برچسب تصادفی کوچک هم با اشارهگرها و هم با محدودهای از آدرسهای حافظه مرتبط میشود. برای اینکه دسترسی به حافظه معتبر باشد، اشارهگر و برچسبهای حافظه باید با هم مطابقت داشته باشند. HWASan برای ذخیره برچسب اشارهگر در بالاترین بیتهای آدرس، به ویژگی ARMv8 یعنی نادیده گرفتن بایت بالا (TBI) که برچسبگذاری آدرس مجازی نیز نامیده میشود، متکی است.
میتوانید اطلاعات بیشتر در مورد طراحی HWASan را در سایت مستندات Clang مطالعه کنید.
از نظر طراحی، HWASan فاقد مناطق قرمز با اندازه محدود ASan برای تشخیص سرریزها یا قرنطینه با ظرفیت محدود ASan برای تشخیص استفاده پس از آزادسازی است. به همین دلیل، HWASan میتواند یک اشکال را صرف نظر از اینکه سرریز چقدر بزرگ باشد یا چه مدت پیش حافظه آزاد شده باشد، تشخیص دهد. این به HWASan یک مزیت بزرگ نسبت به ASan میدهد.
با این حال، HWASan تعداد محدودی از مقادیر برچسب ممکن (256) دارد، به این معنی که احتمال از دست رفتن هرگونه اشکال در طول یک اجرای برنامه 0.4٪ است.
الزامات
نسخههای اخیر (۴.۱۴+) کرنل رایج اندروید از HWASan به صورت پیشفرض پشتیبانی میکنند. نسخههای خاص اندروید ۱۰ از HWASan پشتیبانی نمیکنند.
پشتیبانی از فضای کاربری برای HWASan از اندروید ۱۱ به بعد در دسترس است.
اگر با هستهی متفاوتی کار میکنید، HWASan از هستهی لینوکس میخواهد که اشارهگرهای برچسبگذاریشده را در آرگومانهای فراخوانی سیستم بپذیرد. پشتیبانی از این مورد در مجموعههای پچ بالادستی زیر پیادهسازی شده است:
- آدرس برچسبگذاری شده arm64 با ABI
- arm64: حذف نشانگرهای کاربر منتقل شده به هسته
- mm: از ایجاد نامهای مستعار آدرس مجازی در brk()/mmap()/mremap() خودداری کنید.
- arm64: آدرسهای برچسبگذاری شده را در access_ok() که از نخهای هسته فراخوانی میشود، اعتبارسنجی کنید
اگر در حال ساخت با یک زنجیره ابزار سفارشی هستید، مطمئن شوید که همه چیز را تا کامیت LLVM c336557f شامل میشود.
از HWASan استفاده کنید
برای ساخت کل پلتفرم با استفاده از HWASan از دستورات زیر استفاده کنید:
lunch aosp_walleye-userdebug # (or any other product)export SANITIZE_TARGET=hwaddressm -j
برای راحتی، میتوانید تنظیم SANITIZE_TARGET را به تعریف محصول اضافه کنید، مشابه aosp_coral_hwasan .
برای کاربرانی که با AddressSanitizer آشنا هستند، بسیاری از پیچیدگیهای ساخت از بین رفته است:
- نیازی به اجرای دوبار دستور make نیست.
- ساختهای افزایشی به صورت خودکار و بدون دردسر انجام میشوند.
- نیازی به فلش کردن userdata نیست.
برخی از محدودیتهای AddressSanitizer نیز از بین رفتهاند:
- فایلهای اجرایی استاتیک پشتیبانی میشوند.
- اشکالی ندارد که از پاکسازی هر هدفی غیر از libc صرف نظر کنید. برخلاف ASan، الزامی وجود ندارد که اگر یک کتابخانه پاکسازی شود، هر فایل اجرایی که به آن پیوند دارد نیز باید پاکسازی شود.
جابجایی بین HWASan و ایمیجهای معمولی در همان شماره ساخت (یا بالاتر) میتواند آزادانه انجام شود. نیازی به پاک کردن دستگاه نیست.
برای صرف نظر کردن از پاکسازی یک ماژول، از LOCAL_NOSANITIZE := hwaddress (Android.mk) یا sanitize: { hwaddress: false } (Android.bp) استفاده کنید.
اهداف فردی را پاکسازی کنید
HWASan را میتوان در یک ساختار معمولی (بدون پاکسازی) برای هر هدف فعال کرد، مادامی که libc.so نیز پاکسازی شده باشد. hwaddress: true را به بلوک sanitize در "libc_defaults" در bionic/libc/Android.bp اضافه کنید. سپس همین کار را در هدفی که روی آن کار میکنید انجام دهید.
توجه داشته باشید که پاکسازی libc امکان برچسبگذاری تخصیص حافظه هیپ در سطح سیستم و همچنین بررسی برچسبهای مربوط به عملیات حافظه در داخل libc.so را فراهم میکند. این کار ممکن است حتی در فایلهای باینری که HWASan روی آنها فعال نشده است، در صورتی که دسترسی به حافظه بد در libc.so باشد، اشکالات را شناسایی کند (مثلاً pthread_mutex_unlock() روی یک mutex ویرایش شده با delete() ).
اگر کل پلتفرم با استفاده از HWASan ساخته شده باشد، نیازی به تغییر فایلهای ساخت نیست.
ردیابی بهتر پشتهها
HWASan از یک unwinder سریع و مبتنی بر اشارهگر فریم برای ثبت ردیابی پشته برای هر رویداد تخصیص و آزادسازی حافظه در برنامه استفاده میکند. اندروید به طور پیشفرض اشارهگرهای فریم را در کد AArch64 فعال میکند، بنابراین این در عمل عالی عمل میکند. اگر نیاز به unwind از طریق کد مدیریتشده دارید، HWASAN_OPTIONS=fast_unwind_on_malloc=0 را در محیط فرآیند تنظیم کنید. توجه داشته باشید که ردیابیهای پشته دسترسی بد به حافظه به طور پیشفرض از unwinder "کند" استفاده میکنند. این تنظیم فقط بر ردیابیهای تخصیص و آزادسازی تأثیر میگذارد. این گزینه بسته به بار، میتواند بسیار CPU-محور باشد.
نمادسازی
به نمادگذاری در «درک گزارشهای HWASan» مراجعه کنید.
HWASan در برنامهها
مشابه AddressSanitizer، HWASan نمیتواند کد جاوا را ببیند، اما میتواند اشکالات موجود در کتابخانههای JNI را تشخیص دهد. تا قبل از اندروید ۱۴، اجرای برنامههای HWASan روی دستگاهی که HWASan نبود، پشتیبانی نمیشد .
در یک دستگاه HWASan، برنامهها را میتوان با HWASan و با ساخت کد آنها با SANITIZE_TARGET:=hwaddress در Make یا -fsanitize=hwaddress در پرچمهای کامپایلر بررسی کرد. در یک دستگاه غیر HWASan (با اندروید ۱۴ یا جدیدتر)، باید یک فایل wrap.sh با تنظیم LD_HWASAN=1 اضافه شود. برای جزئیات بیشتر به مستندات توسعهدهنده برنامه مراجعه کنید.