Предотвращение доступа из режима супервизора
Предотвращение доступа из режима супервизора (англ. Supervisor Mode Access Prevention, SMAP) — это функция некоторых реализаций процессоров, таких как Intel: Broadwell (микроархитектура), которая позволяет программам, работающим в режиме супервизора, при необходимости задавать отображения памяти в пользовательское пространство таким образом, чтобы доступ к этим отображениям из режима супервизора вызывал исключение. Это усложняет злоумышленникам использование зловредных программ для «обмана» ядра с целью выполнения инструкций или работы с данными пользовательских программ[1][2].
История
Предотвращение доступа из режима супервизора было разработано как дополнение к механизму предотвращения выполнения из режима супервизора (SMEP). SMEP позволяет препятствовать непреднамеренному выполнению кода пользовательского пространства режимом супервизора, в то время как SMAP расширяет эту защиту на чтение и запись данных[2].
Преимущества
Без механизма предотвращения доступа из режима супервизора код, выполняющийся в режиме супервизора, обычно обладает полным доступом на чтение и запись к отображениям памяти пользовательского пространства (см. возможность получения полного доступа). Это привело к созданию ряда эксплойтов и методик повышения привилегий, основанных на принуждении ядра к неосознанному доступу к пользовательской памяти[3].
Операционные системы могут блокировать такие эксплойты, используя SMAP для того, чтобы любые непреднамеренные обращения к пользовательской памяти вызывали ошибки страниц. Кроме того, SMAP может выявлять дефектный код ядра, не использующий корректные процедуры доступа к пользовательской памяти[1].
Однако использование SMAP в операционной системе может приводить к росту объёма кода ядра и снижению производительности при доступе к пользовательской памяти из режима супервизора. Для намеренного доступа режиму супервизора требуется временно отключать SMAP, что тоже замедляет выполнение[4].
Технические особенности
О поддержке SMAP процессорами сигнализирует расширенный лист возможностей CPUID.
SMAP активируется, когда пагинация памяти включена и установлен бит SMAP в регистре CR4. Для явного доступа к пользовательской памяти SMAP можно временно отключать, устанавливая флаг AC (Auxiliary Carry — контроль выравнивания) в регистре EFLAGS. Для простой установки и сброса этого флага применяются инструкции stac («установить AC») и clac («сбросить AC»)[5].
Когда бит SMAP в CR4 установлен, явные чтения и записи памяти по пользовательским страницам из кода с уровнем привилегий ниже 3 всегда приводят к исключению страницы, если флаг AC в EFLAGS не установлен. Неявные обращения (например, операции с таблицами дескрипторов) по пользовательским страницам вызовут исключение страницы при включённом SMAP, вне зависимости от состояния флага AC в EFLAGS[5].
Поддержка в операционных системах
Поддержка SMAP в ядре Linux была реализована H. Peter Anvin[1]. Эта функция была включена в основную ветку ядра Linux начиная с версии 3.7 и по умолчанию активируется для процессоров, поддерживающих SMAP[4].
FreeBSD поддерживает механизм предотвращения выполнения из режима супервизора (SMEP) с 2012 года[6], а поддержку SMAP — с 2018 года[7].
В OpenBSD поддержка SMAP и связанного механизма SMEP реализована с 2012 года[8]. Первая версия с включённой поддержкой — OpenBSD 5.3[9].
В NetBSD поддержка SMEP была реализована Максимом Вийяром (Maxime Villard) в декабре 2015 года[10]; поддержка SMAP также добавлена Максимом Вийяром в августе 2017 года[11]. Первая версия NetBSD с поддержкой и SMEP, и SMAP — NetBSD 8.0[12].
В Haiku поддержка механизма предотвращения выполнения из режима супервизора (SMEP) реализована Жеромом Дювалем (Jérôme Duval) в январе 2018 года[13].
macOS поддерживает SMAP по крайней мере начиная с выхода версии macOS 10.13 в 2017 году[14].