Архитектура и дизайн
С точки зрения защиты архитектура x86 основана на иерархических кольцах, согласно которым все пространство выполнения, предоставляемое процессором, делится на четыре иерархических домена защиты каждому из которых назначен собственный уровень привилегий.Этот дизайн предполагает, что большая часть временного кода будет выполняться в домене с наименьшими привилегиями, и иногда будут запрашиваться службы из более привилегированного домена безопасности, и эти службы будут выгружать менее стековые действия в стек, а затем восстанавливать его таким образом, чтобыполное вытеснение будет невидимым для менее привилегированного кода.
Конструкция иерархических доменов защиты предусматривает, что управление не может быть произвольно передано между различными доменами безопасности.
Шлюз является функциейАрхитектура x86 для передачи управления из менее привилегированных сегментов кода в более привилегированные, но не наоборот.Кроме того, точка в менее привилегированном сегменте, откуда будет передаваться управление, может быть произвольной, но строго указывается в более привилегированном сегменте, куда будет передаваться управление.Передача управления назад в менее привилегированный сегмент разрешается только с помощью инструкции IRET
.В этом отношении в заявлении руководства разработчика программного обеспечения Intel:
Модули кода в сегментах с более низкими привилегиями могут получать доступ только к модулям, работающим с сегментами с более высокими привилегиями, с помощью строго контролируемого и защищенного интерфейса, называемого шлюзом.Попытки получить доступ к сегментам с более высокими привилегиями без прохождения через защитный шлюз и без достаточных прав доступа приводят к генерации исключения общей защиты (#GP
).
Другими словами, шлюз являетсяточка входа в привилегированный домен с необходимыми правами доступа и целевым адресом.Таким образом, все шлюзы схожи и используются практически для одних и тех же целей, и все дескрипторы шлюза содержат поле DPL, которое используется процессором для управления правами доступа.Но обратите внимание, процессор проверяет DPL шлюза только в том случае, если источником вызова была программная инструкция CALL
, JMP
или INT
, и обходит эту проверку, если источником вызова является аппаратное обеспечение.
Типы ворот
Несмотря на то, что все ворота похожи, они имеют некоторые различия, потому что изначально инженеры Intel думали, что разные ворота будут использоваться для разных целей.
ЗадачаGate
Gate Gate может храниться только в IDT и GDT и вызываться командой INT
.Это очень особый тип шлюза, который значительно отличается от других.
Изначально инженеры Intel думали, что они революционизируют многозадачность, предоставляя функции на основе ЦП для переключения задач.Они представили TSS (сегмент состояния задачи), который хранит состояние регистров задачи и может использоваться для переключения аппаратных задач.Существует два способа запуска аппаратного переключения задач: с помощью самого TSS и с помощью Task Gate.Для переключения аппаратных задач вы можете использовать инструкции CALL
или JMP
.Если я правильно понимаю, главная причина введения шлюза задач состояла в том, чтобы иметь возможность запускать переключатели аппаратных задач в ответ на поступление прерывания, потому что переключение аппаратной задачи не может быть вызвано с помощью JMP
для селектора TSS.
На самом деле, никто не использует это, ни аппаратное переключение контекста.На практике эта функция не оптимальна с точки зрения производительности и не удобна в использовании.Например, принимая во внимание, что TSS может храниться только в GDT, а длина GDT не может превышать 8192, мы не можем иметь более 8 000 задач с аппаратной точки зрения.
Trap Gate
Trap Gate может храниться только в IDT и вызываться командой INT
.Это можно рассматривать как основной тип ворот.Он просто передает управление конкретному адресу, указанному в дескрипторе шлюза, в более привилегированном сегменте и ничего более.Ловушки активно используются для различных целей, которые могут включать в себя:
- реализация системного вызова (например, Linux использует
INT 0x80
и Windows использует INT 0x2E
для этих целей)
- Реализация обработки исключений (у нас нет никаких причин отключать прерывания в случае исключения).
- Реализация обработки прерываний на машинах с APIC (мы можем лучше контролировать стек ядра).
Ворота прерывания
Шлюз прерывания может храниться только в IDT и вызываться командой INT
. Это то же самое, что и у шлюза-ловушки, но, кроме того, вызов шлюза прерывания дополнительно запрещает дальнейшее принятие прерывания путем автоматической очистки флага IF в регистре EFLAGS.
Ворота прерываний активно используются для реализации обработки прерываний, особенно на машинах на основе PIC. Причиной является требование контролировать глубину стека. PIC не имеет функции приоритетов источников прерываний. Благодаря этому по умолчанию PIC отключает только те прерывания, которые уже есть при обработке в процессоре. Но другие прерывания все еще могут прибыть в середину и опередить обработку прерываний. Таким образом, в стеке ядра может одновременно находиться 15 обработчиков прерываний. В результате разработчики ядра вынуждены либо значительно увеличить размер стека ядра, что приводит к потере памяти, либо быть готовыми к случайным переполнениям стека ядра. Interrupt Gate может гарантировать, что в стеке ядра одновременно может находиться только один обработчик.
Call Gate
Шлюз вызовов может храниться в GDL и LDT и вызываться с помощью инструкций CALL
и JMP
. Похож на trap gate, но в дополнение может передавать количество параметров из стека задач режима пользователя в стек задач режима ядра. Количество передаваемых параметров указывается в дескрипторе шлюза вызова.
Ворота звонков никогда не были популярны. Для этого есть несколько причин:
- Их можно заменить на ворота-ловушки (бритва Оккама).
- Они не переносимы много. Другие процессоры не имеют таких функций, что означает, что поддержка шлюзов вызовов для системных вызовов является бременем при переносе операционной системы, поскольку эти вызовы должны быть переписаны.
- Они не слишком гибкие из-за того, что количество параметров, которые можно передавать между стеками, ограничено.
- Они не оптимальны с точки зрения производительности.
В конце 1990-х годов Intel и AMD представили дополнительные инструкции для системных вызовов: SYSENTER
/ SYSEXIT
(Intel) и SYSCALL
/ SYSRET
(AMD). В отличие от шлюзов, новые инструкции обеспечивают повышение производительности и нашли применение.
Резюме
Я не согласен с Майклом Фукаракисом. Извините, но между прерываниями и прерываниями нет никаких отличий, кроме влияющих на флаг IF
.
Теоретически каждый тип шлюза может служить интерфейсом, указывающим на сегмент с любым уровнем привилегий. На практике в современной операционной системе используются только прерывания и прерывания, которые используются в IDT для системных вызовов, прерываний и обработки исключений, и благодаря этому все они служат точкой входа в ядро.
Любой тип шлюза (включая прерывание, ловушку и задачу) может быть вызван программно с помощью инструкции INT
. Единственная функция, которая может запретить доступ кода режима пользователя к конкретному шлюзу, - это DPL. Например, когда операционная система собирает IDT, независимо от типов конкретных шлюзов, ядро устанавливает DPL шлюзов, которые будут использоваться для обработки аппаратных событий, до 0 и в соответствии с этим доступ к этим вентилям будет разрешен только из пространства ядра. (это работает в наиболее привилегированном домене), но когда он устанавливает шлюз для системного вызова, он устанавливает DPL равным 3, чтобы разрешить доступ к этому шлюзу из любого кода. В результате задача пользовательского режима может выполнять системный вызов с использованием шлюза с DPL = 3, но при попытке вызвать обработчик прерывания клавиатуры, например, будет обнаружена ошибка общей защиты.
Аппаратно может вызывать любой тип шлюза в IDT.Люди используют шлюзы прерываний для этой аппаратной обработки событий только в тех случаях, когда они хотят добиться некоторой синхронизации.Например, быть уверенным, что переполнение стека ядра невозможно.Например, у меня есть успешный опыт использования шлюзов для обработки аппаратных прерываний в системе на основе APIC.
Аналогичным образом, в программном обеспечении могут вызываться шлюзы любого типа в IDT.Причина использования шлюзов для системных вызовов и исключений проста.Нет причин отключать прерывания.Отключение прерываний - плохая вещь, потому что это увеличивает задержки обработки прерываний и увеличивает вероятность потери прерываний.Из-за этого никто не сможет отключить их без каких-либо серьезных оснований.
Обработчик прерываний, как правило, написан в строгом реентерабельном стиле.Таким образом, обработчики прерываний обычно не разделяют данные и могут прозрачно вытеснять друг друга.Даже когда нам необходимо взаимно исключить одновременный доступ к данным в обработчике прерываний, мы можем защитить только доступ к совместно используемым данным, используя инструкции cli и sti.Нет никаких причин рассматривать весь обработчик прерываний как критическую секцию.Нет никаких причин использовать шлюзы прерываний, кроме желания предотвратить возможное переполнение стека ядра в системах на основе PIC.
Ворота-ловушки - это стандартное решение для взаимодействия с ядром.Ворота прерывания можно использовать вместо шлюза-ловушки, если для этого есть серьезная причина.