См 8) Механизм шлюзов для передачи управления на сегменты кода с другими уровнями привилегий



Поскольку межсегментные переходы контролируются с использованием уровней привилегий и существует потребность в передаче управления с одного уровня привилегий на другой уровень, в микропроцессорах i80x86 реализован механизм шлюзов, который мы поясним с помощью рис. 3.9. Шлюзование позволяет организовать обращение к так называемым подчиненным сегментам кода, которые выполняют часто встречающиеся функции и должны быть доступны многим задачам, располагающимся на том же или более низком уровне привилегии.


Рис. 3.9. Механизм шлюзов для перехода на другой уровень привилегий

Помимо дескрипторов сегментов системными объектами, с которыми работает микропроцессор, являются специальные системные дескрипторы, названные шлюзами или вентилями. Главное различие между дескриптором сегмента и шлюзом вызова заключается в том, что содержимое дескриптора указывает на сегмент в памяти, а шлюз обращается к дескриптору. Другими словами, если дескриптор служит механизмом отображения памяти, то шлюз служит механизмом перенаправления.
Для получения доступа к более привилегированному коду задача должна обратиться к нему не непосредственно (путем указания дескриптора этого кода), а обращением к шлюзу этого сегмента (рис. 3.10).
В этом дескрипторе вместо адреса сегмента указываются селектор, позволяющий найти дескриптор искомого сегмента кода, и адрес (смещение назначения), с которого будет выполняться подчиненный сегмент, то есть полный 32-битный адрес. Формат дескриптора шлюза приведен на рис. 3.11. Адресовать шлюз вызова можно с помощью команды CALL. По существу, дескрипторы шлюзов вызова не являются дескрипторами (сегментов), но они могут быть расположены среди обычных дескрипторов в дескрипторных таблицах процесса. Смещение, указываемое в команде перехода на другой сегмент (FAR CALL), игнорируется, и фактически осуществляется переход на команду, адрес которой определяется через смещение из шлюза вызова. Этим гарантируется попадание только на разрешенные точки входа в подчиненные сегменты.


Рис. 3.10. Переход на сегмент более привилегированного кода


Рис. 3.11. Формат дескриптора шлюза

Введены следующие правила использования шлюзов:

  • значение DPL шлюза вызова должно быть больше или равно значению текущего уровня привилегий CPL;
  • значение DPL шлюза вызова должно быть больше или равно значению поля RPL селектора шлюза;
  • значение DPL шлюза вызова должно быть больше или равно значению DPL целевого сегмента кода;
  • значение DPL целевого сегмента кода должно быть меньше или равно значению текущего уровня привилегий CPL.

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

  • привилегированный код надежно защищен и вызывающие его программы не могут его разрушить. Естественно, что такой системный код должен быть особенно тщательно отлаженным, не содержать ошибок, быть максимально эффективным;
  • шлюзы межсегментных переходов для вызова системных функций делают эти самые системные функции невидимыми для программных модулей, расположенных на внешних (более низких) уровнях привилегий;
  • поскольку вызывающая программа непосредственно адресует только шлюз вызова, реализуемые вызываемым модулем (сегментным кодом) функции можно изменить или переместить в адресном пространстве, не затрагивая интерфейс со шлюзом;
  • программные модули вызываются с более привилегированного уровня.

Изложенный коротко аппаратный механизм защиты по привилегиям оказывается довольно сложным и жестким. Однако поскольку все практические ситуации учесть в схемах микропроцессора невозможно, то при разработке процедур операционных систем и иного высоко привилегированного кода следует придерживаться приведенных ниже рекомендаций, заимствованных из книги [22].
Основной риск связан с передачей управления через шлюз вызова более привилегированной процедуре. Нельзя предоставлять вызывающей программе никаких преимуществ, вытекающих из-за временного повышения привилегий. Это замечание особенно важно для процедур нулевого уровня привилегий (PL0-процедур).
Вызывающая программа может нарушить работу процедуры, передавая ей "плохие" параметры. Поэтому целесообразно как можно раньше проконтролировать передаваемые процедуре параметры. Шлюз вызова сам по себе не проверяет значений параметров, которые копируются в новый стек, поэтому достоверность каждого передаваемого параметра должна контролировать вызванная процедура. Вот некоторые способы контроля передаваемых параметров.

1. Следует проверять счетчики циклов и повторений на минимальные и максимальные значения.

2. Необходимо проверить 8- и 16-битные параметры, передаваемые в 32-битных регистрах. Когда процедуре передается короткий параметр, его следует расширить со знаком или нулем для заполнения всего 32-битного регистра.

3. Следует стремиться свести к минимуму время работы процессора с запрещенными прерываниями. Если процедуре требуется запрещать прерывания, необходимо, чтобы вызывающая программа не могла влиять на время нахождения процессора с запрещенными прерываниями (флажок IF=0).

4. Процедура никогда не должна воспринимать как параметр код или указатель кода.

5. В операциях процессора следует явно задавать состояние флажка направления DF для цепочечных команд.

6. Заключительная команда RET или RETn в процедуре должна точно соответствовать полю счетчика WC шлюза вызова; при этом n = 4x, так как счетчик задает число двойных слов, а n соответствует байтам.

7. Не следует применять шлюзы вызовов для функций, которым передается переменное число параметров (см. рекомендацию 6). При необходимости нужно воспользоваться счетчиком и указателем параметров.

8. Функции не могут возвращать значения в стеке (см. рекомендацию 6), так как после возврата стеки процедуры и вызывающей программы находятся точно в таком состоянии, в каком они были до вызова.

9. В процедуре следует сохранять и восстанавливать все сегментные регистры. Иначе, если какой-либо сегментный регистр привлекался для адресации данных, недоступных вызывающей программе, процессор автоматически загрузит в него пустой селектор.

Рекомендуется контролировать все обращения к памяти. Нетрудно представить себе, что РL3-программа передаст PL0-процедуре указатель селектор:смещение и запросит считывание или запись нескольких байтов по этому адресу. Типичным примером может служить процедура дискового ввода/вывода, которая воспринимает как параметр системный номер файла, счетчик байт и адрес, по которому записываются данные с диска. Хотя PL0-процедура имеет привилегии для производства такой операции, но у РL3-программы разрешения на это может не быть.


Дата добавления: 2018-05-12; просмотров: 276; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!