Memory Tagging Extension (MTE)

Підтримайте HackTricks

Основна інформація

Розширення позначення пам'яті (MTE) призначене для підвищення надійності та безпеки програмного забезпечення шляхом виявлення та запобігання помилкам, пов'язаним з пам'яттю, таким як переповнення буфера та вразливості типу використання після вивільнення. MTE, як частина архітектури ARM, надає механізм для прикріплення невеликого тегу до кожного виділення пам'яті та відповідного тегу до кожного вказівника, який посилається на цю пам'ять. Цей підхід дозволяє виявляти недопустимі доступи до пам'яті під час виконання, значно зменшуючи ризик використання таких вразливостей для виконання довільного коду.

Як працює розширення позначення пам'яті

MTE працює шляхом розділення пам'яті на невеликі блоки фіксованого розміру, кожному блоку призначається тег, який, як правило, має декілька бітів.

Коли створюється вказівник для посилання на цю пам'ять, він отримує той самий тег. Цей тег зберігається в невикористаних бітах вказівника пам'яті, ефективно пов'язуючи вказівник з відповідним блоком пам'яті.

Коли програма отримує доступ до пам'яті через вказівник, апаратне забезпечення MTE перевіряє, що тег вказівника відповідає тегу блоку пам'яті. Якщо теги не відповідають, це вказує на недопустимий доступ до пам'яті.

Теги вказівників MTE

Теги всередині вказівника зберігаються в 4 бітах всередині верхнього байта:

Отже, це дозволяє до 16 різних значень тегів.

Теги пам'яті MTE

Кожні 16 байт фізичної пам'яті мають відповідний тег пам'яті.

Теги пам'яті зберігаються в окремій області ОЗУ (недоступній для звичайного використання). За наявності тегів розміром 4 біти для кожних 16 байт теги пам'яті займають до 3% ОЗУ.

ARM вводить наступні інструкції для маніпулювання цими тегами в окремій області ОЗУ:

STG [<Xn/SP>], #<simm>    Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>]       Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP>      Insert Random [pointer] Tag
...

Режими перевірки

Синхронний

CPU перевіряє теги під час виконання інструкції, якщо відбувається неспівпадання, воно викликає виняток. Це найповільніший і найбільш безпечний режим.

Асинхронний

CPU перевіряє теги асинхронно, і коли виявляється неспівпадання, воно встановлює біт винятку в одному з системних регістрів. Це швидше за попередній, але не може вказати точну інструкцію, що спричинила неспівпадання, і не викликає виняток негайно, давши трохи часу атакуючому завершити свій напад.

Змішаний

???

Приклади реалізації та виявлення

Називається апаратний KASAN на основі тегів, MTE-базовий KASAN або внутрішній MTE. Аллокатори ядра (наприклад, kmalloc) будуть викликати цей модуль, який підготує тег для використання (випадково) прикріпить його до виділеного простору ядра та до поверненого вказівника.

Зауважте, що він позначатиме лише достатньо пам'яті (16B кожен) для запитаного розміру. Тому, якщо запитаний розмір був 35, і було надано плитку розміром 60B, він позначить перші 16*3 = 48B цим тегом, а решта буде позначена так званим недійсним тегом (0xE).

Тег 0xF - це відповідний всім вказівникам. Пам'ять з цим вказівником дозволяє використовувати будь-який тег для доступу до своєї пам'яті (немає неспівпадань). Це може запобігти виявленню атаки MET, якщо цей тег використовується в атакованій пам'яті.

Тому є лише 14 значень, які можна використовувати для генерації тегів, оскільки 0xE та 0xF зарезервовані, що дає ймовірність повторного використання тегів 1/17 -> близько 7%.

Якщо ядро отримує доступ до недійсного тегового гранулу, буде виявлено неспівпадання. Якщо воно отримує доступ до іншої області пам'яті, якщо пам'ять має інший тег (або недійсний тег), буде виявлено неспівпадання. Якщо атакуючому пощастить, і пам'ять використовує той самий тег, не буде виявлено неспівпадання. Ймовірність становить близько 7%.

Інша помилка виникає в останній гранулі виділеної пам'яті. Якщо додаток запросив 35B, йому була надана гранула від 32 до 48. Тому байти з 36 по 47 використовують той самий тег, але їх не запитували. Якщо атакуючий отримує доступ до цих додаткових байтів, це не виявляється.

Коли виконується kfree(), пам'ять повторно позначається недійсним тегом пам'яті, тому в використання після вивільнення, коли пам'ять знову доступна, виявляється неспівпадання.

Однак у використанні після вивільнення, якщо той самий чанк знову виділяється з ТИМ САМИМ тегом, як раніше, атакуючий зможе використовувати цей доступ, і це не буде виявлено (імовірність близько 7%).

Більше того, лише slab та page_alloc використовують позначену пам'ять, але у майбутньому це також буде використовуватися в vmalloc, stack та globals (на момент відео цими можна було зловживати).

Коли виявляється неспівпадання, ядро панікує, щоб запобігти подальшому зловживанню та спробам використання уразливості (MTE не має помилкових позитивів).

Посилання

Last updated