Методы защиты в процессорах семейства Х86, страница 5

2.  Шлюзы вызова делают программу процедуры невидимой для программ на внешних уровнях привилегий.

3.  При использовании новой версии операционной системы не требуется корректировать старые пользовательские программы. Дело в том, что пользовательская программа при вызове процедур операционной системы обращается всегда только к шлюзам, которые могут оставаться по старым адресам. Следовательно, при изменении адресов процедур обслуживания операционных систем, достаточно только изменить их виртуальный адрес (селектор и смещение) в  дескрипторах шлюзов вызова, что выполняется достаточно легко.

                     Рис.VI.5. Схема передачи управления вызываемой процедуре

                                            через шлюз вызова.

Как это уже было отмечено выше, передача управления через шлюзы вызова может осуществляться только к тем сегментам, уровень привилегий которых выше или равен уровню привилегий текущей программы. Однако, при этом, уровень привилегий самих использованных шлюзов должен быть ниже или равен уровню привилегий текущей программы. Таким образом, правила разрешения вызова через шлюз имеет вид:

1. DPL целевого сегмента кода  ≤  CPL;

2. DPLцелевого сегмента кода ≤ DPLшлюза;

3. max (RPL, CPL) ≤ DPLшлюза.

Иллюстрация этого правила отображена на рис.VI.6.

 

Рис.VI.6. Разрешенные варианты передачи управления через шлюзы.

Если все указанные выше правила соблюдаются, то после вызова дескриптора шлюза в сегментный регистр CS из него загружается селектор, который хранится во 2 и 3 байте этого дескриптора. По этому селектору из  соответствующей дескрипторной таблицы (чаще всего LDT) выбирается дескриптор требуемого сегмента. При этом младшие два бита (поле RPL) селектора игнорируются, а вместо них в регистр CS в качестве CPL заносится значение DPL из дескриптора вызываемого сегмента.

Заметим, что правила передачи управления через шлюз включает в себя случай, когда сегмент вызываемой процедуры имеет тот же уровень привилегий, что и сегмент текущей выполняемой программы. Но в таких случаях использовать шлюзы нет никакой необходимости, так как гораздо проще передать управление непосредственно по адресу процедуры, причем в этом случае можно использовать не только команды FAR CALL, но и команды безусловного перехода FAR JMP во всех моделях процессоров семейства Х86.

                                 Переключение стека.

При передаче через шлюз вызова управления программе или процедуре, находящейся на другом уровне привилегий, встает проблема использования стека. Дело в том, что одно из основных правил системы защиты по привилегиям заключается в том, чтобы уровень привилегий стека всегда должен быть равен уровню привилегий исполняемой программы, т.е. CPL. Следовательно, если управление передается программе, находящейся на другом, более привилегированном уровне, то использование ею старого стека, т.е. стека основной программы – запрещается. Этот запрет вызван двумя следующими причинами:

·  вызывающая, основная, программа может иметь недостаточное стековое адресное пространство, и тогда вызываемая программа, (процедура), может вызвать переполнение стека;

·  этот сегмент стека, который будет использоваться привилегированной процедурой, может быть искажен какой либо менее привилегированной программой, которая использует этот же стек совместно с вызывающей программой на исходном уровне привилегий.

Чтобы избежать этих неприятных возможностей, при передаче управления программам, находящимся на более привилегированном уровне, на этом уровне создается новый стек, который и будет использован при исполнении вызываемой программы. При его организации, в него первым делом записывается селектор старого стека SS и его указатель SP, чтобы возобновить функционирование старого стека после возврата в основную, вызывающую, программу. Кроме того, вызванная процедура часто для своего исполнения нуждается в некоторых параметрах, занесенных в старый стек вызывающей программы. Поэтому процессор сразу же анализирует поле WC дескриптора шлюза вызова, после чего  автоматически копирует из старого стека в новый, указанное в этом поле число 32-х разрядных двоичных кодов. Эти коды и представляют собой параметры, необходимые для передачи вызываемой процедуре. После этого в  новый стек включается адрес возврата, т.е. содержимое сегментного регистра CS и указателя инструкций EIP.

Иллюстрация переключения стека при передаче управления через шлюз вызова от пользовательской программы, расположенной на третьем уровне привилегий, к процедуре операционной системы, размещенной на первом уровне, приведена на рис.VI.7. 

Рис.VI.7. Переключение стека при передаче управления через

                                    шлюз вызова

После организации на уровне вызываемой процедуры нового стека, для инициирования выполнения этой процедуры, остается только загрузить значение селектора и смещения из дескриптора шлюза вызова соответственно в регистры CS и EIP.

Естественно встает вопрос, где организуется стек на этом новом привилегированном уровне, куда передается управление. Размещение стека на привилегированных уровнях 0, 1, 2, определяется системным программистом на все время инициализации системы и заносится в соответствующие ячейки памяти сегмента состояния задачи TSS,  который подробно будет описан в разделе, посвященном принципам организации многозадачного (мультизадачного) режима работы процессоров семейства Х86. Этот сегмент имеет минимальный размер 68h байт и, вообще говоря, служит для хранения информации о состоянии  задачи на момент ее переключения на другую задачу. Но в начале этого сегмента 24 байта выделено для постоянного хранения трех полных логических адресов стеков на каждом из указанных выше уровнях привилегий. Для уровня привилегий 3 такой адрес не определен, поскольку менее привилегированного уровня не существует. Размещение этих адресов в сегменте TSS приведено на рис.VI.8. При этом код, размещаемый в двух младших байтах сегмента - «Обратная связь» («Back link») является селектором TSS предыдущей задачи.