Arm v9 Extension برچسبگذاری حافظه Arm (MTE) را معرفی میکند که یک پیادهسازی سختافزاری از حافظه برچسبگذاری شده است.
در سطح بالایی، MTE هر تخصیص/تخصیص حافظه را با ابرداده اضافی برچسب گذاری می کند. یک تگ به یک مکان حافظه اختصاص می دهد، که سپس می تواند با اشاره گرهایی که به آن مکان حافظه اشاره می کنند مرتبط شود. در زمان اجرا، CPU بررسی می کند که نشانگر و تگ های فراداده در هر بارگذاری و ذخیره مطابقت دارند.
در اندروید 12، تخصیص دهنده حافظه هسته و فضای کاربران می تواند هر تخصیص را با ابرداده افزایش دهد. این به شناسایی باگهای بدون استفاده و سرریز بافر، که رایجترین منبع اشکالات ایمنی حافظه در پایگاههای کد ما هستند، کمک میکند.
حالت های عملیاتی 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، حالت Asymmetric MTE بررسی همزمان خواندن حافظه و بررسی ناهمزمان نوشتن حافظه را با عملکردی مشابه حالت ASYNC فراهم می کند. در اکثر مواقع، این حالت نسبت به حالت ASYNC بهبود یافته است و توصیه می کنیم هر زمان که در دسترس بود، از آن به جای ASYNC استفاده کنید.
به همین دلیل، هیچ یک از API های توضیح داده شده در زیر به حالت نامتقارن اشاره ای نمی کنند. در عوض، سیستم عامل را می توان طوری پیکربندی کرد که همیشه از حالت نامتقارن هنگام درخواست Asynchronous استفاده کند. لطفاً برای اطلاعات بیشتر به بخش "پیکربندی سطح MTE ترجیحی ویژه CPU" مراجعه کنید.
MTE در فضای کاربران
بخشهای زیر نحوه فعال کردن MTE را برای فرآیندها و برنامههای سیستم توضیح میدهند. MTE به طور پیشفرض غیرفعال است، مگر اینکه یکی از گزینههای زیر برای یک فرآیند خاص تنظیم شده باشد (ببینید MTE برای چه مؤلفههایی در زیر فعال است).
MTE را با استفاده از سیستم ساخت فعال کنید
به عنوان یک ویژگی گسترده فرآیند، MTE توسط تنظیم زمان ساخت فایل اجرایی اصلی کنترل می شود. گزینههای زیر اجازه میدهند این تنظیم را برای فایلهای اجرایی جداگانه یا برای کل زیر شاخههای درخت منبع تغییر دهید. این تنظیم در کتابخانهها یا هر هدفی که نه قابل اجرا و نه آزمایشی است نادیده گرفته میشود.
1. فعال کردن 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_heap LOCAL_SANITIZE_DIAG := memtag_heap |
2. فعال کردن 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 |
یا با تعیین مسیر exclude یک فایل اجرایی:
حالت 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 را میتوان طبق دستورالعملهای بالا فعال کرد.
سطح MTE ترجیحی ویژه CPU را پیکربندی کنید
در برخی از CPU ها، عملکرد MTE در حالت های ASYMM یا حتی SYNC ممکن است مشابه عملکرد ASYNC باشد. این امر باعث میشود در صورت درخواست حالت بررسی دقیقتر، بررسیهای دقیقتر روی آن پردازندهها فعال شود تا از مزایای تشخیص خطای بررسیهای سختگیرانهتر، بدون جنبههای منفی عملکرد، برخوردار شوید.
بهطور پیشفرض، فرآیندهایی که برای اجرا در حالت ASYNC پیکربندی شدهاند، در حالت ASYNC روی همه پردازندهها اجرا میشوند. برای پیکربندی هسته برای اجرای این فرآیندها در حالت SYNC روی CPUهای خاص، مقدار sync باید در ورودی sysfs
/sys/devices/system/cpu/cpu<N>/mte_tcf_preferred
در زمان بوت نوشته شود. این را می توان با یک اسکریپت init انجام داد. به عنوان مثال، برای پیکربندی CPU 0-1 برای اجرای فرآیندهای حالت ASYNC در حالت SYNC، و CPU های 2-3 برای استفاده از run در حالت 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
0 یا 1 است.
مقداردهی اولیه حافظه را در 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 نمیتواند سرریز را در همان گرانول برچسب (تکه تراز شده 16 بایتی) تشخیص دهد و میتواند سرریزهای کوچک را حتی در این حالت از دست بدهد. چنین سرریزی نمی تواند دلیل تخریب حافظه باشد، زیرا حافظه درون یک گرانول هرگز برای تخصیص چندگانه استفاده نمی شود. -
M_MEMTAG_TUNING_UAF
- برچسبهای تصادفی مستقل را برای احتمال یکنواخت 93% برای شناسایی اشکالات مکانی (سرریز بافر) و زمانی (استفاده پس از رایگان) فعال میکند.
علاوه بر 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
در اندروید 12، تعدادی از اجزای سیستم حیاتی امنیتی از MTE ASYNC برای شناسایی خرابیهای کاربر نهایی استفاده میکنند و به عنوان یک لایه اضافی دفاعی در عمق عمل میکنند. این اجزا عبارتند از:
- دیمون ها و ابزارهای شبکه (به استثنای
netd
) - بلوتوث، SecureElement، HAL های NFC و برنامه های سیستمی
- دیمون
statsd
-
system_server
-
zygote64
(برای اینکه برنامهها بتوانند از MTE استفاده کنند)
این اهداف بر اساس معیارهای زیر انتخاب شدند:
- یک فرآیند ممتاز (تعریف شده به عنوان فرآیندی که به چیزی دسترسی دارد که دامنه SELinux unprivileged_app به آن دسترسی ندارد)
- ورودی غیرقابل اعتماد فرآیندها ( قانون دو )
- کاهش عملکرد قابل قبول (کاهش سرعت تاخیر قابل مشاهده توسط کاربر ایجاد نمی کند)
ما فروشندگان را تشویق می کنیم تا MTE را در تولید قطعات بیشتر، با پیروی از معیارهای ذکر شده در بالا، فعال کنند. در طول توسعه، ما توصیه میکنیم این مؤلفهها را با استفاده از حالت SYNC آزمایش کنید تا باگها را به راحتی برطرف کنید و تأثیر ASYNC را بر عملکرد آنها ارزیابی کنید.
در آینده، اندروید قصد دارد فهرست اجزای سیستمی را که MTE روی آنها فعال است، با هدایت ویژگی های عملکرد طراحی های سخت افزاری آینده گسترش دهد.