نسخه نهم Arm، افزونه برچسبگذاری حافظه Arm (MTE) را معرفی میکند که یک پیادهسازی سختافزاری از حافظه برچسبگذاری شده است.
در سطح بالا، MTE هر تخصیص/آزادسازی حافظه را با فرادادههای اضافی برچسبگذاری میکند. MTE یک برچسب را به یک مکان حافظه اختصاص میدهد که سپس میتواند با اشارهگرهایی که به آن مکان حافظه ارجاع میدهند، مرتبط شود. در زمان اجرا، CPU بررسی میکند که اشارهگر و برچسبهای فراداده در هر بار بارگذاری و ذخیره مطابقت داشته باشند.
در اندروید ۱۲، تخصیصدهنده حافظه هیپ فضای کاربری و هسته میتوانند هر تخصیص را با فرادادهها تقویت کنند. این امر به شناسایی اشکالات استفاده پس از آزادسازی و سرریز بافر کمک میکند که رایجترین منبع اشکالات ایمنی حافظه در پایگاههای کد ما هستند.
حالتهای عملیاتی MTE
MTE سه حالت عملیاتی دارد:
- حالت همگامسازی (SYNC)
- حالت ناهمزمان (ASYNC)
- حالت نامتقارن (ASYMM)
حالت همگامسازی (SYNC)
این حالت برای صحت تشخیص اشکال نسبت به عملکرد بهینه شده است و میتواند به عنوان یک ابزار دقیق تشخیص اشکال، زمانی که سربار عملکرد بالاتر قابل قبول است، مورد استفاده قرار گیرد. هنگامی که فعال باشد، MTE SYNC به عنوان یک کاهشدهنده امنیت عمل میکند. در صورت عدم تطابق برچسب، پردازنده بلافاصله اجرا را متوقف میکند و فرآیند را با SIGSEGV (کد SEGV_MTESERR ) و اطلاعات کامل در مورد دسترسی به حافظه و آدرس خطا خاتمه میدهد.
ما استفاده از این حالت را در حین آزمایش به عنوان جایگزینی برای HWASan/KASAN یا در مرحله تولید، زمانی که فرآیند هدف نشاندهنده یک سطح حمله آسیبپذیر است، توصیه میکنیم. علاوه بر این، هنگامی که حالت ASYNC وجود یک اشکال را نشان داده است، میتوان با استفاده از APIهای زمان اجرا برای تغییر اجرا به حالت SYNC، یک گزارش اشکال دقیق دریافت کرد.
هنگام اجرا در حالت SYNC، تخصیصدهنده اندروید ردپاهای پشته را برای همه تخصیصها و آزادسازیها ثبت میکند و از آنها برای ارائه گزارشهای خطای بهتر استفاده میکند که شامل توضیحی در مورد خطای حافظه، مانند استفاده پس از آزادسازی یا سرریز بافر، و ردپاهای پشته از رویدادهای حافظه مربوطه است. چنین گزارشهایی اطلاعات زمینهای بیشتری ارائه میدهند و ردیابی و رفع اشکالات را آسانتر میکنند.
حالت ناهمزمان (ASYNC)
این حالت برای عملکرد بالاتر از دقت گزارشهای اشکال بهینه شده است و میتواند به عنوان تشخیص کم سربار برای اشکالات ایمنی حافظه مورد استفاده قرار گیرد. در صورت عدم تطابق برچسب، پردازنده اجرا را تا نزدیکترین ورودی هسته (به عنوان مثال، یک syscall یا وقفه تایمر) ادامه میدهد، جایی که فرآیند را با SIGSEGV (کد SEGV_MTEAERR ) بدون ثبت آدرس خطا یا دسترسی به حافظه خاتمه میدهد.
ما استفاده از این حالت را در محیط عملیاتی روی کدهایی که به خوبی آزمایش شدهاند و چگالی باگهای ایمنی حافظه در آنها کم است، توصیه میکنیم. این امر با استفاده از حالت SYNC در حین آزمایش محقق میشود.
حالت نامتقارن (ASYMM)
یک ویژگی اضافی در Arm v8.7-A، حالت نامتقارن MTE است که بررسی همزمان خواندن حافظه و بررسی غیرهمزمان نوشتن حافظه را با عملکردی مشابه حالت ASYNC فراهم میکند. در بیشتر مواقع، این حالت نسبت به حالت ASYNC بهبود یافته است و توصیه میکنیم هر زمان که در دسترس است، از آن به جای ASYNC استفاده کنید.
به همین دلیل، هیچ یک از APIهای شرح داده شده در زیر به حالت نامتقارن اشاره نمیکنند. در عوض، میتوان سیستم عامل را طوری پیکربندی کرد که همیشه هنگام درخواست ناهمگام از حالت نامتقارن استفاده کند. برای اطلاعات بیشتر، به پیکربندی سطح MTE ترجیحی مخصوص CPU مراجعه کنید.
MTE در فضای کاربری
بخشهای زیر نحوه فعالسازی MTE برای فرآیندها و برنامههای سیستم را شرح میدهند. MTE به طور پیشفرض غیرفعال است، مگر اینکه یکی از گزینههای زیر برای یک فرآیند خاص تنظیم شده باشد ( در زیر ببینید MTE برای چه اجزایی فعال است).
فعال کردن MTE با استفاده از سیستم ساخت
به عنوان یک ویژگی در سطح فرآیند، MTE توسط تنظیمات زمان ساخت فایل اجرایی اصلی کنترل میشود. گزینههای زیر امکان تغییر این تنظیمات را برای فایلهای اجرایی منفرد یا برای کل زیرشاخهها در درخت منبع فراهم میکنند. این تنظیمات در کتابخانهها یا هر هدفی که نه اجرایی است و نه آزمایشی، نادیده گرفته میشود.
۱. فعال کردن MTE در Android.bp ( مثال )، برای یک پروژه خاص:
| حالت MTE | تنظیم |
|---|---|
| MTE ناهمزمان | sanitize: {
memtag_heap: true,
} |
| MTE همزمان | sanitize: {
memtag_heap: true,
diag: {
memtag_heap: true,
},
} |
یا در Android.mk:
| حالت MTE | تنظیم |
|---|---|
Asynchronous MTE | LOCAL_SANITIZE := memtag_heap |
Synchronous MTE | LOCAL_SANITIZE := memtag_heapLOCAL_SANITIZE_DIAG := memtag_heap |
۲. فعال کردن MTE روی یک زیرشاخه در درخت منبع با استفاده از یک متغیر محصول:
| حالت MTE | شامل لیست | لیست را حذف کنید |
|---|---|---|
| ناهمگام | PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS MEMTAG_HEAP_ASYNC_INCLUDE_PATHS | PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS MEMTAG_HEAP_EXCLUDE_PATHS |
| همگامسازی | PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS MEMTAG_HEAP_SYNC_INCLUDE_PATHS |
یا
| حالت MTE | تنظیم |
|---|---|
| MTE ناهمزمان | MEMTAG_HEAP_ASYNC_INCLUDE_PATHS |
| MTE همزمان | MEMTAG_HEAP_SYNC_INCLUDE_PATHS |
یا با مشخص کردن مسیر حذف یک فایل اجرایی:
| حالت MTE | تنظیم |
|---|---|
| MTE ناهمزمان | PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS MEMTAG_HEAP_EXCLUDE_PATHS |
| MTE همزمان |
مثال، (کاربرد مشابه PRODUCT_CFI_INCLUDE_PATHS )
PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS=vendor/$(vendor)
PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS=vendor/$(vendor)/projectA \
vendor/$(vendor)/projectBفعال کردن MTE با استفاده از ویژگیهای سیستم
تنظیمات ساخت بالا را میتوان در زمان اجرا با تنظیم ویژگی سیستمی زیر لغو کرد:
arm64.memtag.process.<basename> = (off|sync|async) که در آن basename مخفف نام پایه فایل اجرایی است.
برای مثال، برای تنظیم /system/bin/ping یا /data/local/tmp/ping برای استفاده از MTE ناهمزمان، adb shell setprop arm64.memtag.process.ping async استفاده کنید.
فعال کردن MTE با استفاده از یک متغیر محیطی
یک راه دیگر برای لغو تنظیمات ساخت برای فرآیندهای بومی (غیر از برنامهها) تعریف متغیر محیطی است: MEMTAG_OPTIONS=(off|sync|async) اگر هم متغیر محیطی و هم ویژگی سیستم تعریف شده باشند، متغیر اولویت دارد.
فعال کردن MTE برای برنامهها
اگر مشخص نشده باشد، MTE به طور پیشفرض غیرفعال است، اما برنامههایی که میخواهند از MTE استفاده کنند میتوانند با تنظیم android:memtagMode در زیر تگ <application> یا <process> در AndroidManifest.xml این کار را انجام دهند.
android:memtagMode=(off|default|sync|async) وقتی این ویژگی روی برچسب <application> تنظیم شود، روی تمام فرآیندهای مورد استفاده برنامه تأثیر میگذارد و میتواند با تنظیم برچسب <process> برای فرآیندهای منفرد لغو شود.
برای آزمایش، میتوان از تغییرات سازگاری برای تنظیم مقدار پیشفرض ویژگی memtagMode برای برنامهای که هیچ مقداری را در مانیفست مشخص نکرده است (یا default را مشخص میکند) استفاده کرد.
این موارد در منوی تنظیمات کلی، در قسمت System > Advanced > Developer options > App Compatibility Changes قرار دارند. تنظیم NATIVE_MEMTAG_ASYNC یا NATIVE_MEMTAG_SYNC MTE را برای یک برنامه خاص فعال میکند. به عنوان یک روش جایگزین، میتوان این مورد را با استفاده از دستور am به شرح زیر تنظیم کرد:
$ adb shell am compat enable NATIVE_MEMTAG_[A]SYNC my.app.nameساخت یک تصویر سیستم MTE
ما اکیداً توصیه میکنیم که MTE را روی تمام فایلهای باینری بومی در طول توسعه و راهاندازی فعال کنید. این کار به شناسایی زودهنگام اشکالات ایمنی حافظه کمک میکند و در صورت فعال بودن در نسخههای آزمایشی، پوشش کاربر واقعبینانهای را فراهم میکند.
اکیداً توصیه میکنیم که MTE را در حالت همگامسازی روی تمام فایلهای باینری بومی در طول توسعه فعال کنید.
SANITIZE_TARGET=memtag_heap SANITIZE_TARGET_DIAG=memtag_heap m همانند هر متغیری در سیستم ساخت، SANITIZE_TARGET میتواند به عنوان یک متغیر محیطی یا یک تنظیم make (برای مثال، در یک فایل product.mk ) استفاده شود.
این MTE را برای همه فرآیندهای بومی فعال میکند، اما نه برای برنامههایی (که از zygote64 منشعب شدهاند) که MTE را میتوان برای آنها با دنبال کردن دستورالعملهای موجود در Enable MTE for apps فعال کرد.
سطح MTE ترجیحی مختص CPU را پیکربندی کنید
در برخی از CPUها، عملکرد MTE در حالتهای ASYMM یا حتی SYNC ممکن است مشابه ASYNC باشد. این امر باعث میشود که فعال کردن بررسیهای سختگیرانهتر روی آن CPUها، زمانی که حالت بررسی با دقت کمتری درخواست میشود، ارزشمند باشد تا بتوان از مزایای تشخیص خطای بررسیهای سختگیرانهتر بدون کاهش عملکرد بهرهمند شد.
به طور پیشفرض، فرآیندهای پیکربندیشده برای اجرا در حالت ASYNC، در تمام CPUها در حالت ASYNC اجرا میشوند. برای پیکربندی هسته برای اجرای این فرآیندها در حالت SYNC در CPUهای خاص، مقدار sync باید در زمان بوت در ورودی sysfs /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred نوشته شود. این کار را میتوان با یک اسکریپت init انجام داد. به عنوان مثال، برای پیکربندی CPUهای 0-1 برای اجرای فرآیندهای حالت ASYNC در حالت SYNC و CPUهای 2-3 برای استفاده از حالت ASYMM، میتوان موارد زیر را به بند init یک اسکریپت init فروشنده اضافه کرد:
write /sys/devices/system/cpu/cpu0/mte_tcf_preferred sync write /sys/devices/system/cpu/cpu1/mte_tcf_preferred sync write /sys/devices/system/cpu/cpu2/mte_tcf_preferred asymm write /sys/devices/system/cpu/cpu3/mte_tcf_preferred asymm
سنگ قبرهای مربوط به فرآیندهای حالت ASYNC که در حالت SYNC اجرا میشوند، حاوی یک ردیابی پشته دقیق از محل خطای حافظه هستند. با این حال، آنها شامل ردیابی پشته تخصیص یا آزادسازی تخصیص حافظه نیستند. این ردیابیهای پشته فقط در صورتی در دسترس هستند که فرآیند برای اجرا در حالت SYNC پیکربندی شده باشد.
int mallopt(M_THREAD_DISABLE_MEM_INIT, level) که در آن level ۰ یا ۱ است.
مقداردهی اولیه حافظه را در malloc غیرفعال میکند و از تغییر برچسبهای حافظه مگر در صورت لزوم برای صحت، جلوگیری میکند.
int mallopt(M_MEMTAG_TUNING, level) که در آن level عبارت است از:
-
M_MEMTAG_TUNING_BUFFER_OVERFLOW -
M_MEMTAG_TUNING_UAF
استراتژی تخصیص برچسب را انتخاب میکند.
- تنظیم پیشفرض
M_MEMTAG_TUNING_BUFFER_OVERFLOWاست. -
M_MEMTAG_TUNING_BUFFER_OVERFLOWبا اختصاص مقادیر برچسب متمایز به تخصیصهای مجاور، امکان تشخیص قطعی اشکالات سرریز بافر خطی و سرریز زیرین را فراهم میکند. این حالت شانس کمی برای تشخیص اشکالات استفاده پس از آزادسازی دارد زیرا تنها نیمی از مقادیر برچسب ممکن برای هر مکان حافظه در دسترس هستند. MTE نمیتواند سرریز را در همان گرانول برچسب (قطعه تراز شده ۱۶ بایتی) تشخیص دهد و حتی در این حالت نیز میتواند سرریزهای کوچک را از دست بدهد. چنین سرریزی نمیتواند علت فساد حافظه باشد، زیرا حافظه درون یک گرانول هرگز برای تخصیصهای متعدد استفاده نمیشود. -
M_MEMTAG_TUNING_UAFتگهای تصادفی مستقل را برای احتمال یکنواخت حدود ۹۳٪ در تشخیص اشکالات مکانی (سرریز بافر) و زمانی (استفاده پس از آزادسازی) فعال میکند.
علاوه بر API های شرح داده شده در بالا، کاربران باتجربه ممکن است بخواهند از موارد زیر نیز آگاه باشند:
- تنظیم رجیستر سختافزاری
PSTATE.TCOمیتواند به طور موقت بررسی برچسب را متوقف کند ( مثال ). برای مثال، هنگام کپی کردن طیف وسیعی از حافظه با محتوای برچسب ناشناخته یا پرداختن به یک گلوگاه عملکرد در یک حلقه داغ. - هنگام استفاده از
M_HEAP_TAGGING_LEVEL_SYNC، کنترلکنندهی خرابی سیستم اطلاعات اضافی مانند ردیابیهای پشته تخصیص و آزادسازی تخصیص را ارائه میدهد. این قابلیت نیاز به دسترسی به بیتهای برچسب دارد و با ارسال پرچمSA_EXPOSE_TAGBITSهنگام تنظیم کنترلکنندهی سیگنال فعال میشود. توصیه میشود هر برنامهای که کنترلکنندهی سیگنال خود را تنظیم میکند و خرابیهای ناشناخته را به سیستم محول میکند، همین کار را انجام دهد.
MTE در هسته
برای فعال کردن KASAN شتابیافته توسط MTE برای هسته، هسته را با CONFIG_KASAN=y و CONFIG_KASAN_HW_TAGS=y پیکربندی کنید. این پیکربندیها به طور پیشفرض در هستههای GKI فعال هستند و از Android 12-5.10 شروع میشوند.
شما میتوانید این را در زمان بوت با استفاده از آرگومانهای خط فرمان زیر کنترل کنید:
-
kasan=[on|off]- فعال یا غیرفعال کردن KASAN (پیشفرض:on) -
kasan.mode=[sync |async ]- بین حالت همگام و ناهمگام یکی را انتخاب کنید (پیشفرض:sync) -
kasan.stacktrace=[on|off]- آیا دادههای پشته جمعآوری شوند یا خیر (پیشفرض:on)- جمعآوری ردیابی پشته همچنین به
stack_depot_disable=offنیاز دارد.
- جمعآوری ردیابی پشته همچنین به
-
kasan.fault=[report|panic]- اینکه آیا فقط گزارش را چاپ کند، یا هسته را نیز وحشتزده کند (پیشفرض:report). صرف نظر از این گزینه، بررسی برچسب پس از اولین خطای گزارششده غیرفعال میشود.
میزان مصرف توصیه شده
ما اکیداً توصیه میکنیم از حالت SYNC در طول راهاندازی، توسعه و آزمایش استفاده کنید. این گزینه باید به صورت سراسری برای تمام فرآیندهایی که از متغیر محیطی یا با سیستم ساخت استفاده میکنند، فعال شود. در این حالت، اشکالات در مراحل اولیه توسعه شناسایی میشوند، کدبیس سریعتر تثبیت میشود و از هزینه تشخیص اشکالات در مراحل بعدی تولید جلوگیری میشود.
ما اکیداً توصیه میکنیم از حالت ASYNC در محیط عملیاتی استفاده کنید. این حالت، ابزاری با سربار کم برای تشخیص وجود اشکالات ایمنی حافظه در یک فرآیند و همچنین دفاع عمیقتر فراهم میکند. پس از شناسایی یک اشکال، توسعهدهنده میتواند از APIهای زمان اجرا برای تغییر به حالت SYNC استفاده کند و یک ردیابی پشته دقیق از مجموعهای از کاربران نمونهبرداری شده دریافت کند.
ما اکیداً توصیه میکنیم سطح MTE ترجیحی مختص CPU را برای SoC پیکربندی کنید. حالت Asymm معمولاً ویژگیهای عملکردی مشابه ASYNC دارد و تقریباً همیشه نسبت به آن ارجحیت دارد. هستههای کوچک مرتب اغلب عملکرد مشابهی را در هر سه حالت نشان میدهند و میتوانند طوری پیکربندی شوند که SYNC را ترجیح دهند.
توسعهدهندگان باید وجود خرابیها را با بررسی /data/tombstones ، logcat یا با نظارت بر خط لوله DropboxManager فروشنده برای یافتن اشکالات کاربر نهایی بررسی کنند. برای اطلاعات بیشتر در مورد اشکالزدایی کد بومی اندروید، به اطلاعات اینجا مراجعه کنید.
اجزای پلتفرم فعالشده با MTE
در اندروید ۱۲، تعدادی از اجزای حیاتی سیستم از MTE ASYNC برای تشخیص خرابیهای کاربر نهایی و عمل به عنوان یک لایه اضافی دفاع در عمق استفاده میکنند. این اجزا عبارتند از:
- دیمنها و ابزارهای شبکه (به استثنای
netd) - بلوتوث، SecureElement، NFC HALها و برنامههای سیستمی
- دیمن
statsd -
system_server -
zygote64(برای اینکه برنامهها بتوانند از MTE استفاده کنند)
این اهداف بر اساس معیارهای زیر انتخاب شدند:
- یک فرآیند ممتاز (به عنوان فرآیندی تعریف میشود که به چیزی دسترسی دارد که دامنهی SELinux با نام unprivileged_app به آن دسترسی ندارد)
- ورودیهای غیرقابل اعتماد را پردازش میکند ( قانون دو )
- کاهش سرعت عملکرد قابل قبول (کاهش سرعت باعث ایجاد تأخیر قابل مشاهده توسط کاربر نمیشود)
ما فروشندگان را تشویق میکنیم که MTE را در مرحله تولید برای اجزای بیشتر، با رعایت معیارهای ذکر شده در بالا، فعال کنند. در طول توسعه، توصیه میکنیم این اجزا را با استفاده از حالت SYNC آزمایش کنید تا اشکالات به راحتی برطرف شوند و تأثیر ASYNC بر عملکرد آنها ارزیابی شود.
ما قصد داریم با توجه به ویژگیهای عملکردی طراحیهای سختافزاری آینده، فهرست اجزای سیستمی که MTE روی آنها فعال است را گسترش دهیم.