ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.


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

 

Часть 7

Глава 6  Защита
-----------------------------------------------------------------
Защита необходима при работе в мультизадачном режиме. Средства
защиты могут быть использованы для предотвращения взаимного
влияния одновременно выполняемых задач. Например, может
выполняться защита от затирания одной задачей команд и данных
другой задачи.
При разработке программы механизм защиты поможет получить более
четкую картину программных ошибок. Когда программа выполняет
неожиданную ссылку к недопустимой в данный момент области
памяти, механизм защиты может блокировать данное событие и
сообщить о нем.
В системах, предназначенных для конечных пользователей механизм
защиты может предохранять систему от программных сбоев,
вызываемых невыявленными ошибками в программах. При сбое в
программе действие его распространится таким образом лишь на
ограниченный домен памяти. Операционная система при этом может
быть защищена от нарушений ее областей, что позволяет
зарегистрировать диагностическое сообщение об ошибке и сделать
попытку автоматического восстановления программы.
Защита может применяться к сегментам и страницам памяти. Два
бита регистра процессора определяют уровень привилегированности
текущей выполняемой программы (этот уровень называется текущим
уровнем привилегированности, или CPL). Во время трансляции
адреса для доступа к сегменту или странице выполняется проверка
CPL.
Хотя для выключения механизма защиты специального управляющего
регистра или бита режима не предусмотрено, тот же эффект можно
получить, назначив уровень привилегированности 0 (это старший
уровень привилегированности) всем селекторам сегментов,
дескрипторам сегментов и элементам страничной таблицы.
6.1  Защита на уровне сегментов
-----------------------------------------------------------------
Механизм защиты позволяет ограничить влияние неправильно
работающей программы на другие выполняемые программы и их
данные. Защита представляет собой ценное свойство при разработке
программных продуктов, поскольку она обеспечивает сохранность в
памяти при любых ситуациях средств разработки программного
обеспечения (операционной системы, отладчика). При сбое в
прикладной программе в полной исправности сохраняется
программное обеспечение, позволяющее выдать диагностические
сообщения, а отладчик имеет возможность произвести "посмертный"
анализ содержимого памяти и регистров сбойной программы. В
системах, эксплуатирующих готовое программное обеспечение,
защита позволяет повысить его надежность и дает возможность
инициировать восстановительные процедуры в системе.
Каждая ссылка к памяти контролируется с точки зрения
удовлетворения защитным проверкам. Все проверки выполняются до
начала цикла обращения к памяти; любые нарушения защиты
предотвращают начало цикла доступа к памяти и генерируют
исключение. Поскольку проверки защиты выполняются параллельно с
трансляцией адреса, они не влияют на характеристики
быстродействия системы. Существует пять проверок:
     1. Проверка типа
     2. Проверка границы
     3. Ограничение адресуемого домена
     4. Ограничение точек входа в процедуру
     5. Ограничение набора команд
Нарушение защиты ведет к генерации исключения. Механизм
исключений описан в Главе 9. В данной главе описаны нарушения
защиты памяти, ведущие к генерации исключений.
6.2  Дескрипторы сегмента и защита
-----------------------------------------------------------------
На Рисунке 6-1 показаны поля дескриптора сегмента, используемые
механизмом защиты. Отдельные биты поля Типа именуются по
выполняемым ими функциям.
Параметры защиты помещаются в дескриптор при его создании. В
целом, прикладным программистам эти параметры знать не
требуется.
               Дескриптор сегмента данных
                       2 1 1 1 1 1 1 1 1 1 1
31                     0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
----------------------------------------------------------------
|               | | | | |       | | D | | | | | |              |
| BASE  31:24   | | | | |LIMIT  | | P |1|0|E|W|A|  BASE 23:16  | 
+4
|               | | | | |19:16  | | L | | | | | |              |
|--------------------------------------------------------------|
|      База сегмента 15:00      |    Граница сегмента 15:00    | 
+0
----------------------------------------------------------------
               Дескриптор сегмента кода
                       2 1 1 1 1 1 1 1 1 1 1
31                     0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
----------------------------------------------------------------
|               | | | | |       | | D | | | | | |              |
| BASE  31:24   | | | | |LIMIT  | | P |1|1|C|R|A|  BASE 23:16  | 
+4
|               | | | | |19:16  | | L | | | | | |              |
|--------------------------------------------------------------|
|      База сегмента 15:00      |    Граница сегмента 15:00    | 
+0
----------------------------------------------------------------
A         Доступ произошел
C         Конформный
DPL       Уровень привилегированности дескриптора
E         Расширение вниз
R         Доступный для чтения
LIMIT     Граница сегмента
W         Доступный для записи
     Рисунок 6-1. Поля дескриптора, используемые для защиты
                         (Часть 1 из 2)
               Дескриптор системного сегмента
                       2 1 1 1 1 1 1 1 1 1 1
31                     0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
----------------------------------------------------------------
|               | | | | |       | | D | |       |              |
| BASE  31:24   | | | | |LIMIT  | | P |0|  Тип  |  BASE 23:16  | 
+4
|               | | | | |19:16  | | L | |       |              |
|--------------------------------------------------------------|
|      База сегмента 15:00      |    Граница сегмента 15:00    | 
+0
----------------------------------------------------------------
DPL       Уровень привилегированности дескриптора
LIMIT     Граница сегмента
     Рисунок 6-2. Поля дескриптора, используемые для защиты
                         (Часть 2 из 2)
Когда программа загружает в сегментный регистр селектор
сегмента, процессор автоматически загружает туда базовый адрес
этого сегмента и информацию о его защите. Невидимая часть
каждого сегментного регистра хранит базовый адрес, границу, тип
и уровень привилегированности. Благодаря тому, что эта
информация резидентно находится в сегментном регистре, все
последующие проверки защиты для этого регистра могут быть
выполнены без дополнительных затрат времени на ее поиск.
6.2.1  Проверка типа
-----------------------------------------------------------------
Помимо дескрипторов для сегментов кода и данных прикладной
программы, процессор i486 имеет дескрипторы для системных
сегментов и шлюзов. Это структуры данных, используемые для
организации выполнения задач (Глава 7), также исключений и
прерываний (Глава 9). В Таблице 6-1 перечислены все типы,
определенные для системных сегментов и шлюзов. Отметим, что не
все дескрипторы определяют сегменты: дескрипторы шлюзов содержат
точки входа в процедуры.
Поля Типа дескрипторов сегментов кода и данных включают в себя
биты, более подробно определяющие назначение сегмента (см.
Рисунок 6-1):
- Бит "Доступный для записи" в дескрипторе сегмента данных
  управляет возможностью выполнения записи из программ в данный
  сегмент.
- Бит "Доступный для чтения" дескриптора выполняемого сегмента
  задает возможность выполнения чтения программами из данного
  сегмента (например для доступа к константам, записанным
  непосредственно в область кода). Доступный для чтения
  выполняемый сегмент может быть прочитан двумя способами:
     1. С помощью регистра CS, используя префикс переопределения
        сегмента CS.
     2. С помощью загрузки селектора для данного дескриптора в
        регистр сегмента данных (DS, ES, FS или GS).
         Таблица 6-1. Типы системных сегментов и шлюзов
-----------------------------------------------------------------
     Тип                             Описание
-----------------------------------------------------------------
      0         Резервируется
      1         Доступный сегмент состояния задачи (TSS) 80286
      2         LDT
      3         Занятый сегмент состояния задачи (TSS) 80286
      4         Шлюз вызова
      5         Шлюз задачи
      6         Шлюз прерываний 80286
      7         Шлюз ловушек 80286
      8         Резервируется
      9         Доступный TSS ЦПУ i486
     10         Резервируется
     11         Занятый TSS ЦПУ i486
     12         Шлюз вызова ЦПУ i486
     13         Резервируется
     14         Шлюз прерываний ЦПУ i486
     15         Шлюз задачи ЦПУ i486
-----------------------------------------------------------------
Проверка типа может использоваться для определения программных
ошибок, состоящих в попытке использования сегментов способом, не
подразумевавшимся программистом. Процессор рассматривает
информацию о типе в двух возможных случаях:
     1. Когда селектор для дескриптора загружается в сегментный
        регистр. Конкретные сегментные регистры могут содержать
        только конкретные типы дескрипторов; например:
        - Регистр CS может быть загружен только селектором
          выполняемого сегмента.
        - Селекторы выполняемых сегментов, не являющиеся
          "Доступными для чтения", не могут быть загружены в
          регистры сегментов данных.
        - В регистр SS могут быть загружены только селекторы
          сегментов данных, "Доступных для записи".
     2. Конкретные сегменты могут использоваться командами
        только конкретными, предопределенными способами;
        например:
        - Никакая команда не может выполнять запись в
          выполняемый сегмент.
        - Никакая команда не может выполнять запись в сегмент
          данных, если для него не установлен бит "Доступен для
          записи".
        - Никакая команда не может выполнять чтение
          выполняемого сегмента, если для него не установлен бит
          "Доступен для чтения".
6.2.2  Проверка границы
-----------------------------------------------------------------
Поле Границы дескриптора сегмента не дает программам выполнить
адресацию вне сегмента. Действующее значение границы зависит от
установки бита G (бит грануляции). Для сегментов данных граница
также зависит от бита E (бит направления расширения сегмента). В
качестве бита E назначается один из битов поля Типа при ссылках
к дескрипторам сегментов данных.
     Когда бит G очищен, граница сегмента равна значению
20-разрядного поля Границы дескриптора. В этом случае граница
может изменяться в диапазоне от 0 до 0FFFFFH (2**20-1, или 1
мегабайт). Если бит G установлен, то процессор умножает значение
поля Границы на масштабный коэффициент 2**12. В этом случае
граница будет изменяться в диапазоне от 0FFFH (2**12-1, или 4K),
до 0FFFFFFFFH (2**32-1, или 4 гигабайта).Отметим, что при
использовании такого масштабирования, проверка границы для
младших 12 битов адреса не выполняется; когда бит G установлен,
а граница сегмента равна 0, допустимые значения смещения в
сегменте лежат в диапазоне от 0 до 4095.
Для всех типов сегментов, за исключением сегментов, расширяемых
вниз (т.е. стековых сегментов), значение границы на единицу
меньше размера сегмента в байтах. Процессор генерирует
исключение общей защиты в любом из следующих случаев:
     - Попытка доступа к байту памяти по адресу, превышающему
       границу сегмента.
     - Попытка доступа к слову памяти по адресу, превышающему
       границу сегмента - 1.
     - Попытка доступа к двойному слову памяти по адресу,
       превышающему границу сегмента - 3.
     Для сегментов, расширяющихся вниз, граница служит для той
же функции проверки, но интерпретируется иначе. В этом случае
диапазон допустимых значений адреса определяется от (граница+1)
до 2** 32-1. Сегмент с расширением вниз имеет максимальный
размер при значении границы, равном 0.
Контроль границы позволяет отлавливать такие программные ошибки,
как неверно вычисленные индексы массивов и недопустимые
указатели. Эти ошибки определяются сразу же, как только они
произошли, поэтому идентификация вызвавшей их причины
существенно упрощается. Без такого контроля границ указанные
ошибки могут иметь следствием разрушение важных областей памяти
в других модулях, а их существование невозможно обнаружить, пока
не произойдет сбой в испорченном таким образом модуле, а такое
событие может наступить намного позже, чем фактическая вызвавшая
его ошибка. Защита позволяет блокировать такие ошибки и сообщить
об их источнике.
     В дополнение к проверке границ сегментов существует также
проверка границ таблиц дескрипторов. Регистры GDTR и IDTR
содержат 16-разрядное значение границы. Оно используется
процессором для защиты программ от выбора дескриптора сегмента
из области, лежащей вне данной таблицы. Граница таблицы
дескрипторов идентифицирует последний допустимый байт этой
таблицы. Поскольку каждый дескриптор имеет длину восемь байтов,
таблица, содержащая до N дескрипторов, должна иметь значение
Границы, равное 8N-1.
Дескриптору может быть задано нулевое значение. Это относится к
первому дескриптору в таблице GDT, который не используется. Хотя
этот дескриптор может быть загружен в сегментный регистр, любая
попытка ссылки к памяти при помощи этого дескриптора приведет к
генерации исключения общей защиты.
6.2.3  Уровни привилегированности
-----------------------------------------------------------------
     Механизм защиты распознает четыре уровня привилегированности
нумеруемые от 0 до 3. Чем больше номер, тем ниже уровень
привилегированности. При удовлетворении всех прочих проверок
защиты исключение общей защиты генерируется при попытке
программы доступа к сегменту с меньшим уровнем
привилегированности (т.е. с большим числом, задающим уровень),
чем имеет данный сегмент.
Хотя для отмены механизма защиты никакого управляющего регистра
или бита режима не предусмотрено, того же эффекта можно
достигнуть путем присвоения всем уровням привилегированности
значения 0. (Бит PE регистра CR0 не является разрешающим битом
собственно для механизма защиты; он используется для включения
"защищенного режима", режима выполнения программы, в котором
доступной является вся 32-разрядная архитектура процессора в
целом. Если защищенный режим выключен, то процессор работает в
режиме "реальных адресов", который просто реализует возможности
обладающего более высоким быстродействием и улучшенного
процессора 8086).
Уровни привилегированности могут использоваться для повышения
надежности операционной системы. В случае присвоения
операционной системе наивысшего уровня привилегированности она
становится защищенной от сбоев в случае ошибок в других
программах. При таких программных сбоях операционная система
имеет возможность сгенерировать соответствующие диагностические
сообщения и попытаться выполнить восстановительные процедуры.
Следующий уровень привилегированности может быть установлен для
других частей программного обеспечения, таких как программы,
управляющие периферийными устройствами, которые называются
драйверами устройств. При сбое в драйвере устройства
операционная система должна иметь возможность выдать
диагностическое сообщение, поэтому имеет смысл защитить
операционную систему от возможных сбоев драйверов устройств.
Однако, драйвер устройства может работать с важным периферийным
оборудованием, например с дисководом. Сбои прикладных программ
не должны приводить к разрушению структуры директорий на диске,
поэтому имеет смысл защищать драйверы устройств от сбоев
прикладных программ. Драйверы устройств должны иметь уровень
привилегированности промежуточный, между операционной системой и
прикладными программами. Прикладным программам присваивается
самый низкий уровень привилегированности.
На Рисунке 6-2 показано, как эти уровни привилегированности
могут быть интерпретированы в качестве колец защиты. Центральное
кольцо защиты содержит сегменты, в которых находится наиболее
важное программное оеспечение, обычно ядро операционной системы.
Прочие кольца используются для менее важного программного
обеспечения.
Уровни привилегированности хранятся в следующих структурах
данных:
     - Два младших бита сегментного регистра CS содержат текущий
       уровень привилегированности (CPL). Это уровень
       привилегированности выполняемой в текущий момент
       программы. Младшие два бита регистра SS также содержат
       копию CPL. Обычно CPL равен уровню привилегированности
       кодового сегмента, из которого происходит выборка команд
       программы. CPL изменяется при передаче управления
       кодовуму сегменту с другим уровнем привилегированности.
     - Дескрипторы сегмента содержат поле, которое называется
       уровнем привилегированности дескриптора (DPL). DPL
       представляет собой уровень привилегированности
       применительно к сегменту.
     - Селекторы сегмента содержат поле, которое называется
       запрошенным уровнем привилегированности (RPL) RPL
       представляет собой уровень привилегированности процедуры,
       создавшей данный селектор. Если RPL имеет меньший уровень
       привилегированности, чем CPL, то он замещает CPL. Когда
       более привилегированная программа принимает селектор
       сегмента из менее привилегированной программы, RPL
       вызывает доступ к памяти с меньшим уровнем
       привилегированности.
Уровни привилегированности проверяются, когда селектор
дескриптора загружается в сегментный регистр. Проверки,
используемые для доступа к данным, отличаются от проверок при
передаче выполнения между выполняемыми сегментами;
следовательно, существует два типа доступа, рассматриваемые в
следующих разделах в отдельности.
                       Кольца  защиты
                             **
                         *        *
                             **
                    *    *        *    *
                             **
                  *   *   *      *   *    *
Ядро           *   *   *     * *     *   *   *
операционной -----------> *      *
системы       *   *   *  *Уровень 0*  *  *  *
                          *      *
               *   *   *     * *     *  *   *
Вспомогательные --------> Уровень 1
средства                 *         *
операционной      *   *       **       *   *
системы (драйверы ------> Уровень 2
устройств и т.д.)   *    *         *     *
                              **
Прикладные программы----> Уровень 3
                         *         *
                              **
                   Рисунок 6-2. Кольца защиты
6.3  Ограничения доступа к данным
-----------------------------------------------------------------
Для адресации операнда в памяти селектор сегмента данных должен
быть загружен в регистр сегмента данных (регистры DS, ES, FS, GS
или SS). Процессор проверяет уровни привилегированности
сегментов. Проверка выполняется при загрузке селектора сегмента.
Как показано на Рисунке 6-3, в проверке привилегированности
этого типа участвуют три различных уровня привилегированности.
Три проверяемых уровня привилегированности:
1. CPL (текущий уровень привилегированности программы). Он
   хранится в двух младших битах регистра CS.
2. DPL (уровень привилегированности дескриптора) дескриптора
   сегмента, содержащего операнд.
3. RPL (уровень привилегированности источника запроса) из
   селектора, используемого для задания сегмента, содержащего
   операнд. Этот уровень хранится в двух младших битах
   сегментного регистра, используемого для доступа к операнду
   (регистра SS, DS, ES, FS или GS). Если операнд находится в
   стековом сегменте, то RPL и CPL совпадают.
               Дескриптор сегмента, содержащего операнд
                                   1 1
31                                 4 3           7            0
----------------------------------------------------------------
|               | | | | |       | | D | | | | | |              |
|               | | | | |       | | P | | | | | |              | 
+4
|               | | | | |       | | L | | | | | |              |
|--------------------------------------------------------------|
|                               |   |__________________        | 
+0
-------------------------------------------------------|--------
                                                       |
                Текущий кодовый сегментный регистр     |
                                                       |
--------------------                                   |
|            | CPL |------------------------------     |
--------------------                              |    |
                Селектор сегмента, содержащего    |    |
--------------------               операнд        |    |
|            | RPL |-------------------------     |    |
--------------------                         |    |    |
                                             |    |    |
                                             \/   \/   \/
                                         ---------------------
                                         |      Проверка     |
                                         |привилегированности|
                                         ---------------------
CPL       Текущий уровень привилегированности
DPL       Уровень привилегированности дескриптора
RPL       Запрошенный уровень привилегированности
 Рисунок 6-3. Проверка привилегированности при доступе к данным
Команды могут загружать сегментный регистр только если DPL
сегмента имеет такой же или меньший уровень привилегированности
(больший номер привилегированности), чем у наименее
привилегированного CPL и RPL селектора.
Адресуемый домен задачи изменяется при изменении его CPL. Если
CPL равен 0, то сегменты данных всех уровней привилегированности
доступны; когда CPL равен 1, то доступны только сегменты данных
с уровнями привилегированности от 1 до 3; а когда CPL равен 3,
то доступны только сегменты данных с уровнем привилегированности
3.
Доступ к данным в кодовых сегментах
-----------------------------------------------------------------
Может оказаться желательным хранить данные в кодовом сегменте;
например, когда и код, и данные хранятся в ПЗУ. Кодовые сегменты
вполне допускают хранение там констант, однако выполнять запись
в сегмент, определенный в качестве кодового сегмента,
недопустимо, если в том же адресном пространстве не отображен
сегмент данных. Возможны следующие способы доступа к данным в
кодовом сегменте:
1. Загрузка в регистр сегмента данных селектора неконформного,
   доступного для чтения выполняемого сегмента.
2. Загрузка в регистр сегмента данных селектора комформного,
   доступного для чтения выполняемого сегмента.
3. Использование префикса переопределения сегмента для чтения из
   доступного для чтения выполняемого сегмента, селектор
   которого уже загружен в регистр CS.
Для случая 1 применимы те же правила доступа, что и для сегмента
данных. Случай 2 допустим всегда, поскольку уровень
привилегированности кодового сегмента с установленным битом
Конформности такой же, как и CPL, независимо от его DPL. Случай
3 также допустим всегда, поскольку DPL кодового сегмента,
выбранного при помощи регистра CS, совпадает с CPL.
6.4  Ограничения передачи управления
-----------------------------------------------------------------
В процессоре i486 передача управления выполняется командами JMP,
CALL, RET, INT и IRET, а также механизмами исключений и
прерываний. Исключения и прерывания - это особые случаи и они
рассматриваются в Главе 9. В данной же главе обсуждаются только
команды JMP, CALL и RET.
"Ближние" формы команд JMP, CALL и RET передают управление в
пределах содержащего их кодового сегмента, и следовательно,
подлежат только проверки границы перехода. Процессор проверяет,
чтобы адрес назначения команд JMP, CALL и RET не выходил за
границу текущего сегмента кода. Граница кешируется в регистре
CS, поэтому проверка границы для ближних переходов не требует
дополнительных затрат времени.
Операнды "дальних" форм команд JMP и CALL ссылаются на другие
сегменты, поэтому процессор выполняет проверку
привилегированности. Существует два способа ссылки из команд JMP
или CALL на другие сегменты:
1. Операнд выбирает дескриптор другого выполняемого сегмента.
2. Операнд выбирает дескриптор шлюза вызова. Такая форма
   передачи управления с использованием шлюзования
   рассматривается в Главе 7.
Как показано на Рисунке 6-4, два различных уровня
привилегированности вызывают проверку привилегированности
передачи управления без использования шлюза вызова:
1. CPL (текущий уровень привилегированности).
2. DPL дескриптора кодового сегмента назначения перехода.
Обычно CPL равен DPL сегмента, выполняемого процессором в
текущий момент. CPL может быть, однако, больше (т.е. менее
привилегированным), чем DPL, если текущий кодовый сегмент
является конформным сегментом (конформность указывается в поле
Типа сегментного дескриптора). Конформный сегмент выполняется на
уровне привилегированности вызывающей процедуры. Процессор все
время кеширует CPL в регистре CS; это значение может быть
отличным от значения DPL в сегментном дескрипторе текущего
кодового сегмента.
               Дескриптор кодового сегмента назначения перехода
                                 1 1 1 1 1 1
31                               5 4 3 2 1 0 9 8 7            0
----------------------------------------------------------------
|               | | | | |       | | D |  Тип    |              |
|               | | | | |       | | P | | | | | |              | 
+4
|               | | | | |       | | L |1|1|C|R|A|              |
|--------------------------------------------------------------|
|                               |   |      |___________        |
|                               |   |_____________     |       | 
+0
--------------------------------------------------|----|--------
                                                  |    |
            Текущий кодовый сегментный регистр    |    |
                                                  |    |
--------------------                              |    |
|            | CPL |--------------------------    |    |
--------------------                         |    |    |
                                             |    |    |
                                             \/   \/   \/
                                         ---------------------
                                         |      Проверка     |
                                         |привилегированности|
                                         ---------------------
C         Бит конформности
CPL       Текущий уровень привилегированности
DPL       Уровень привилегированности дескриптора
     Рисунок 6-4. Проверка привилегированности при передаче
                   управления без шлюзования
Процессор разрешает передачу управления командами JMP или CALL
напрямую в другой сегмент только в том случае, если выполняются
следующие правила привилегированности:
- DPL сегмента равен текущему CPL.
- Сегмент является конформным кодовым сегментом, и его DPL
  меньше (привилегированность выше), чем текущий CPL.
Конформные сегменты используются для таких программ, как
библиотеки математических функций или некоторые виды
обработчиков прерываний, которые поддерживают прикладные
программы, но не требуют доступа к защищенным системным
средствам. При передаче управления конформному сегменту CPL не
изменяется, даже если селектор, использованный для адресации
сегмента, имеет другой RPL. Это единственное условие, когда CPL
может быть отличным от DPL текущего кодового сегмента.
Большинство кодовых сегментов является не-конформными. Для таких
сегментов управление может передаваться без шлюзования только к
другим кодовым сегментам, имеющим тот же уровень
привилегированности. Однако, иногда бывает необходимо передавать
управление сегментам с высшими уровнями привилегированности. Это
выполняется при помощи команды CALL, использующей дескрипторы
шлюза вызова, которые рассматриваются в Главе 7. Команда JMP
никогда не может передавать управление не-конформным сегментам,
DPL которых не равен CPL.
6.5  Шлюзовые дескрипторы
-----------------------------------------------------------------
Для обеспечения защиты при передаче управления между
выполняемыми сегментами с разными уровнями привилегированности
процессор i486 использует шлюзовые дескрипторы. Существует
четыре типа шлюзовых дескрипторов:
- Шлюзы вызова
- Шлюзы ловушки
- Шлюзы прерываний
- Шлюзы задач
Шлюзы задач используются для переключения задач и описываются в
Главе 7. В Главе 9 объясняется, как шлюзы ловушек и прерываний
используются для обработки исключений и прерываний. В данной
главе рассматриваются только шлюзы вызова. Шлюзы вызовов
представляют собой некоторую форму защищенной передачи
управления. Они используются для передачи управления между
различными уровнями привилегированности. Их использование
необходимо только в системах, где имеется более одного уровня
привилегированности. На Рисунок 6-5 показан формат шлюза вызова.
Шлюз вызова имеет две основные функции:
1. Определение точки входа в процедуру.
2. Задание уровня привилегированности, требуемого для входа в
   процедуру.
                   32-битовый шлюз вызова
31                          6 5 4 3 2 1 0 9 8 7 6 5 4 3       3
----------------------------------------------------------------
|                            | | D | | | | | | | | | |Счетчик  |
| Смещение в сегменте  31:16 |P| P |0|1|1|0|0|0|0|0|0|двойных  |+
|                            | | L | | | | | | | | | |слов     |
|                            | |   | | | | | | | | | |         |
----------------------------------------------------------------
|   Селектор сегмента        |     Смещение в сегменте 15:00   |+
----------------------------------------------------------------
DPL    Уровень привилегированности дескриптора
P      Присутствие сегмента
                   Рисунок 6-5.  Шлюз вызова
Дескрипторы шлюзов вызова используются командами CALL и JUMP
используются аналогичным способом, что и дескрипторы кодовых
сегментов. Когда аппаратная часть распознает, что селектор
сегмента назначения ссылается к шлюзовому дескриптору,
выполнение команды определяется содержимым шлюза вызова.
Дескриптор шлюза вызова может находиться в GDT или в LDT, но не
в таблице дескрипторов прерывания (IDT).
Поля Селектора и Смещения в шлюзе образуют указатель на точку
входа в процедуру. Шлюз вызова гарантирует, что любые передачи
управления другим сегментам будут происходить в правильные точки
входа процедуры, а не куда-нибудь в середину процедуры (или, что
еще хуже, в середину команды). Операнд команды передачи
управления не является селектором сегмента и смещением в
сегменте точки входа желаемой процедуры. Вместо этого селектор
сегмента указывает на шлюзовой селектор, а смещение не
используется. Такая форма адресации показана на Рисунке 6-6.
|<---------------- Адрес назначения --------------->|
15           0     31                              0
---------------    ----------------------------------
|   Селектор  |    |    Смещение в сегменте         |
---------------    ----------------------------------
         \                         |
          \                        \/
           \                 Не используется
            \
             \
              \           Таблица дескрипторов
               \   ----------------------------------
                \  |        |       |       |       |
                 \ |--------------------------------|
                  \|                |               |
                   |--------------------------------|
  -----------------|    Смещение    |  DPL  |Счетчик| Дескриптор
  |                |--------------------------------| шлюза
  |      ----------|    Селектор    |  Смещение     |
  |      |         |--------------------------------|
  |      |         |        |       |       |       |
  |      |         |--------------------------------|
  |      |         |                |               |
  |      |-----    |--------------------------------|
  |            \   |        |       |       |       |
  |             \  |--------------------------------|
  |              \ |                |               |
  |               \|--------------------------------| Дескриптор
  |                | База   |       |  DPL  | База  | кодового
-----              |--------------------------------| сегмента
| + |<------------ |      База      |               |
-----              |--------------------------------|
  |                |        |       |       |       |
  |                |--------------------------------|
  \/               |                |               |
Точка входа        ----------------------------------
в процедуру
              Рисунок 6-6. Механизм шлюза вызова
Как показано на Рисунке 6-7, для проверки допустимости передачи
управления через шлюз вызова используется четыре различных
уровня привилегированности.
Уровни привилегированности, проверяемые при передаче управления
шерез шлюз вызова, это:
1. CPL (текущий уровень привилегированности).
2. RPL (уровень привилегированности источника запроса) селектора
   сегмента, который был использован для задания шлюза вызова.
3. DPL (уровень привилегированности дескриптора) дескриптора
   шлюза.
4. DPL дескриптора сегмента кодового сегмента назначения
   перехода.
Поле DPL дескриптора шлюза определяет, из каких уровней
привилегированности может использоваться данный шлюз. Один
кодовый сегмент может содержать несколько различных процедур,
предназначенных для использования из различных уровней
привилегированности. Так, операционная система может иметь
некоторые служные процедуры, используемые как прикладными
программами, так и самой операционной системой, например,
подпрограммы ввода/вывода символов, тогда как другие служебные
процедуры могут быть предназначены только для использования их
операционной системы, например, подпрограммы инициализации
драйверов устройств.
Шлюзы могут использоваться для передачи управления как на более
привилегированные уровни, так и на тот же уровень
привилегированности (хотя в последнем случае их использование не
обязательно). Для передачи управления на менее привилегированные
уровни шлюзы могут использоваться только командами CALL. Команда
JMP может использовать шлюз только для передачи управления либо
кодовому сегменту с тем же уровнем привилегированности, либо
конформному кодовому сегменту с тем же или более высоким уровнем
привилегированности.
Для команды перехода JMP к неконформному сегменту должны
удовлетворяться следующие два правила привилегированности (в
противном случае генерируется исключение общей защиты):
MAX(CPL,RPL) <= DPL шлюза
DPL кодового сегмента назначения = CPL
Для команды CALL (или команды перехода JMP к конформному
сегменту) должны удовлетворяться следующие два правила
привилегированности (в противном случае генерируется исключение
общей защиты):
MAX(CPL,RPL) <= DPL шлюза
DPL кодового сегмента назначения <= CPL
6.5.1  Переключение стека
-----------------------------------------------------------------
При вызове процедуры более привилегированного уровня выполняется
следующее:
1. Изменяется CPL.
2. Передается управление (выполнением).
3. Происходит переключение стеков.
               Шлюз вызова
31                               15              7            0
----------------------------------------------------------------
|                               | | D |         |     |        |
|                               | | P |         |     |        | 
+4
|                               | | L |         |     |        |
|--------------------------------------------------------------|
|                               |   |__________________        | 
+0
-------------------------------------------------------|--------
                                                       |
                                                       |
               Дескриптор сегмента кода назначения     |
                                                       |
                                                       |
31                               15              7     |      0
-------------------------------------------------------|--------
|               | | | | |       | | D |         |      |       |
|               | | | | |       | | P |         |      |       | 
+4
|               | | | | |       | | L |         |      |       |
|------------------------------------------------------|-------|
|                               |   |_______________   |       | 
+0
----------------------------------------------------|--|--------
                                                    |  |
                Текущий регистр кодового сегмента   |  |
                                                    |  |
--------------------                                |  |
|            | CPL |-----------------------------   |  |
--------------------                            |   |  |
                Селектор шлюза вызова           |   |  |
--------------------                            |   |  |
|            | RPL |-------------------------   |   |  |
--------------------                         |  |   |  |
                                             |  |   |  |
                                             \/ \/  \/ \/
                                         ---------------------
                                         |      Проверка     |
                                         |привилегированности|
                                         ---------------------
CPL       Текущий уровень привилегированности
DPL       Уровень привилегированности дескриптора
RPL       Запрошенный уровень привилегированности
         Рисунок 6-7. Проверка привилегированности при
          передаче управления при помощи шлюза вызова
Внутренние кольца защиты (уровень привилегированности 0, 1 и 2)
имеют свои собственные стеки для приема вызовов из менее
привилегированных уровней. Если стек должна была обеспечить
вызывающая процедура, и стек оказался слишком мал, то в
результате недостаточного размера стека может произойти сбой
вызываемой процедуры. Поэтому обеспечивается защита более
привилегированных программ от сбоя вследствие менее
привилегированных программ путем создания нового стека при
вызове менее привилегированными процедурами более
привилегированных. Создается новый стек, параметры вызова
копируются из старого стека в новый, а значения регистров
сохраняются, после чего продолжается обычное выполнение
вызванной процедуры. При возврате из этой процедуры содержимое
сохраненных регистров восстанавливается в исходном стеке. Полное
описание механизма переключения задач приводится в Главе 7.
Процессор находит место для создания новых стеков при помощи
сегмента состояния задачи (TSS), как показано на Рисунке 6-8.
Каждая задача имеет собственный TSS. TSS содержит исходные
указатели стека для внутренних колец защиты. Операционная
система отвечает за создание каждого TSS и инициализацию
соответствующих им указателей стека. Исходный указатель стека
состоит из селектора сегмента и исходного значения регистра ESP
(исходное смещение в сегменте). Исходные указатели стеков
представляют собой значения, предназначенные исключительно для
чтения. Процессор не изменяет их во время выполнения задач. Эти
указатели стеков используются только для создания новых стеков
при выполнении вызовов процедур с более высоким уровнем
привилегированности. При возврате из вызванных процедур эти
стеки исчезают. При следующем вызове процедуры происходит
создание нового стека с использованием для этого исходного
указателя стека.
          32-разрядный сегмент состояния задачи
31                                                 0
----------------------------------------------------
|                                                  | 64
|                                                  |
|                                                  |
|                                                  |
|                                                  |
|--------------------------------------------------|
|                         |         SS2            | 18
|--------------------------------------------------|
|                        ESP2                      | 14
|--------------------------------------------------|
|                         |         SS1            | 10
|--------------------------------------------------|
|                        ESP1                      | 0C
|--------------------------------------------------|
|                         |         SS0            | 8
|--------------------------------------------------|
|                        ESP0                      | 4
|--------------------------------------------------|
|                         |         SS2            | 0
----------------------------------------------------
Примечание:  адреса приведены в шестнадцатиричном формате
     Рисунок 6-8. Исходные указатели стека в TSS
При использовании шлюза вызова для изменения уровней
привилегированности новый стек создается загрузкой адреса из
TSS. Процессор использует DPL кодового сегмента назначения
(новый CPL) для выбора исходного указателя стека для уровней
привилегированности 0, 1 или 2.
DPL нового стекового сегмента должен быть равен новому CPL: в
противном случае генерируется исключение сбоя в стеке.
Ответственность за создание стеков и дескрипторов стекового
сегмента для всех используемых уровней привилегированности лежит
на операционной системе. Стеки должны быть доступны для
чтения/записи, как задано в поле Типа соответствующих сегментных
дескрипторов. Они должны содержать достаточно памяти, как задано
полем Граница, чтобы там могло поместиться содержимое регистров
SS и ESP, адрес возврата, параметры и временные переменные,
требуемые для работы вызываемой процедуры.
Как и при вызове в пределах одного уровня привилегированности,
параметры для всех процедур помещаются в стек. Затем эти
параметры копируются в новый стек. Доступ к этим параметрам из
вызываемой процедуры происходит по тем же адресам, по которым
эти параметры находились бы без переключения стека. Поле Счетчика
шлюза вызова сообщает процессору, сколько двойных слов (до 31)
должно копироваться из стека вызывающей процедуры в стек
вызываемой процедуры. Если этот счетчик равен 0, то копирования
параметров не происходит.
Если требуется передать в вызываемую процедуру более 31 двойного
слова данных, то один из параметров можно сделать указателем на
структуру данных, либо сохраненные в нем значения регистров SS и
ESP могут использоваться для доступа к параметрам в старой
области стека.
Во время вызова процедуры с другим уровнем привилегированности
процессор выполняет следующие связанные со стеком действия:
1. Проверяется стек вызываемой процедуры, чтобы убедиться, что
   он достаточно велик для того, чтобы хранить параметры и
   сохраняемые значения регистров; в противном случае
   генерируется исключение переполнения стека.
2. Старое содержимое регистров SS и ESP помещается в стек
   вызываемой процедуры в виде двух двойных слов (16-разрядный
   регистр SS расширяется нулем до 32 битов; это заполненное
   нулем старшее слово резервировано Intel для внутреннего
   пользования; не должно использоваться).
3. Параметры копируются из стека вызывающей программы в стек
   вызываемой программы.
4. В новый стек помещается указатель команды, находящейся после
   команды CALL (старое содержимое регистров CS и IP).
   Содержимое регистров SS и ESP после вызова указывает на этот
   указатель адреса возврата в стеке.
На Рисунке 6-9 показаны кадры стека до, во время и после
успешного вызова и возврата между процедурами с разными уровнями
привилегированности.
TSS не имеет указателя стека для стека с уровнем
привилегированности 3, поскольку процедура с уровнем
привилегированности 3 не может быть вызвана процедурой с еще
более низким уровнем. Стек для уровня привилегированности 3
предохраняется содержимым регистров SS и EIP, которые
сохраняются в стеке привилегированного уровня, вызванного из
уровня 3.
  Старый стек         Новый стек           Старый стек
  до вызова           после вызова,        после возврата
                      до возврата
                      ----------------
|             |       | Старый SS    |     |             |
|-------------|       |--------------|     |-------------|
|             |       | Старый ESP   |     |             |<-ESP
|-------------|       |--------------|     |-------------|
| Параметр 1  |       | Параметр 1   |     |             |
|-------------|       |--------------|     |-------------|
| Параметр 2  |       | Параметр 2   |     |             |
|-------------|       |--------------|     |-------------|
| Параметр 3  |<-ESP  | Параметр 3   |     |             |
|-------------|       |--------------|     |-------------|
|             |       | Старый CS    |     |             |
|-------------|       |--------------|     |-------------|
                      | Старый EIP   |<-ESP
                      |--------------|
                      |              |
                      |--------------|
         Рисунок 6-9. Кадры стека при вызове процедуры
              с другим уровнем привилегированности
Вызов, использующий шлюз вызова, не проверяет значений слов,
копируемых в новый стек. Вызванная процедура должна проверять
допустимость каждого параметра. В следующих разделах обсуждается
использование команд ARPL, VERR, VERW, LSL и LAR для проверки
значений указателей.
6.5.2  Возврат из процедуры
-----------------------------------------------------------------
"Ближние" формы команды RET выполняют передачу управления только
в пределах текущего кодового сегмента, и следовательно, для них
выполняется только контроль границ. Смещение для команды,
следующей после команды вызова CALL, извлекается из стека и
помещается в регистр EIP. Процессор контролирует, чтобы это
смещение не превосходило границу текущего кодового сегмента.
"Дальняя" форма команды RET извлекает адрес возврата, помещенный
в стек предыдущей командой CALL. В нормальных условиях указатель
возврата всегда достоверен, поскольку он был сгенерирован
командой CALL или INT. Тем не менее, процессор выполняет
проверку привилегированности вследствие возможности того, что
текущая процедура изменила указатель или не смогла правильно
обработать стек. RPL селектора кодового сегмента, извлеченный из
стека командой возврата, должен иметь уровень
привилегированности вызывающей процедуры.
Возврат в другой сегмент может изменить уровни
привилегированности, но только в сторону более низких уровней.
Когда команда RET встречает сохраненное значение CS, RPL
которого численно больше CPL (т.е. имеет более привилегированный
уровень), происходит возврат через уровни привилегированности.
Такого рода возврат выполняет следующие шаги:
1. Выполняются проверки, показанные в Таблице 6-2 и регистры CS,
   EIP, SS и ESP загружаются их предыдущими значениями, которые
   были сохранены в стеке.
2. Старое содержимое регистров SS и ESP (из вершины текущего
   стека) настраивается по размеру в байтах, заданному в команде
   RET. Результирующее значение ESP не проверяется на границу
   стекового сегмента. Если значение ESP выходит за эту границу,
   то этот факт не распознается процессором до следующей
   стековой операции. (Содержимое регистров SS и ESP для
   возвращаемой процедуры не сохраняются; обычно их значения те
   же, что и хранимые в TSS).
3. Проверяется содержимое сегментных регистров DS, ES, FS и GS.
   Если хоть один из этих регистров ссылается на сегмент, DPL
   которого меньше нового CPL (включая конформные кодовые
   сегменты), сегментный регистр загружается пустым селектором
   (Индекс=0, TI=0). Сама команда RET в таких случаях не
   сообщает об исключениях; однако любые последующие ссылки к
   памяти при помощи сегментного регистра, содержпщего пустой
   селектор, вызовут исключение общей защиты. Это не позволяет
   менее привилегированным кодам обращаться к более
   привилегированным сегментам посредством селекторов,
   оставленных в сегментных регистрах более привилегированной
   процедурой.
      Таблица 6-2. Проверки при возврате между процедурами
             с разными уровнями привилегированности
-----------------------------------------------------------------
|Тип проверки |                  Тип особой ситуации | Код ошибки
-----------------------------------------------------------------
|Вершина стека должна быть                                       
|в пределах границы сегмента                                     
|стека                            Стек                 0         
|                                                                
|Адрес Вершины стека+7 должен быть                               
|в пределах границы сегмента                                     
|стека                            Стек                 0         
|                                                                
|RPL кодового сегмента возврата                                  
|должен превышать CPL             Защита              CS возврата
|                                                                
|Селектор кодового сегмента                                      
|возврата не должен быть пустым   Защита              CS возврата
|                                                                
|Дескриптор кодового сегмента                                    
|возврата должен быть в пределах                                 
|границы таблицы дескрипторов     Защита              CS возврата
|                                                                
|Дескриптор сегмента возврата                                    
|должен относиться к кодовому                                    
|сегменту                         Защита              CS возврата
|                                                                
|Присутствие кодового сегмента    Сегмент не                     
|возврата                         присутствует        CS возврата
|                                                                
|DPL не-конформного кодового                                     
|сегмента возвратв должен быть                                   
|равен RPL селектора кодового                                    
|сегмента возврата, либо DPL                                     
|конформного кодового сегмента                                   
|возврата должен быть меньше                                     
|или равен RPL селектора кодового                                
|сегмента возврата                Защита              CS возврата
|                                                                
|ESP+N+15*  должно находиться                                    
|в пределах границы сегмента                                     
|стека                            Сбой в стеке        CS возврата
|                                                                
|Селектор сегмента в ESP+N+12*                                   
|не должен быть пустым            Защита              CS возврата
|                                                                
|Дескриптор сегмента в ESP+N+12*                                 
|должен находиться в пределах                                    
|границы таблицы дескрипторов     Защита              CS возврата
|                                                                
|Дескриптор стекового сегмента                                   
|должен быть доступен для                                        
|чтения/записи                    Защита              CS возврата
|                                                                
|Должен присутствовать стековый                                  
|сегмент                          Сбой в стеке        CS возврата
|                                                                
|DPL старого стекового сегмента                                  
|должен быть равен RPL старого                                   
|кодового сегмента                Защита              CS возврата
|                                                                
|Селектор старого стекового                                      
|сегмента должен иметь RPL,                                      
|равный DPL старого стекового                                    
|сегмента                         Защита              CS сегмента
-----------------------------------------------------------------
* N - это значение непосредственного операнда, заданного в
  команде RET.
6.6  Команды, зарезервированные для работы операционной системы
-----------------------------------------------------------------
Команды, которые могут воздействовать на механизм защиты или
повлиять на общие характеристики производительности системы,
могут выполняться только наиболее проверенными процедурами.
Процессор i486 имеет два класса таких команд:
1. Привилегированные команды - команды, используемые для
   управления системой.
2. Чувствительные команды - команды, используемые для ввода/
   вывода и действий, связанных с вводом/выводом.
6.6.1  Привилегированные команды
-----------------------------------------------------------------
Команды, которые оказывают влияние на средства защиты системы,
могут быть выполнены только при CPL равном 0 (наивысший уровень
привилегированности). Если какая-либо из этих команд выполняется
при CPL не равном 0, генерируется исключение общей защиты. В
число этих команд входят:
CLTS               - Очистить флаг переключения задачи
HLT                - Выполнить останов процессора
LGDT               - Загрузить регистр GDT
LIDT               - Загрузить регистр IDT
LLDT               - Загрузить регистр LDT
LMSW               - Загрузить слово состояния машины
LTR                - Загрузить регистр задачи
MOV в/из CR0       - Пересылка с управляющим регистром 0
MOV в/из DRn       - Пересылка с отладочным регистром n
MOV в/из TRn       - Пересылка с тестовым регистром n
6.6.2  Чувствительные команды
-----------------------------------------------------------------
Команды, работающие с вводом/выводом, должны быть защищенными,
но они также должны давать возможность выполнения их и из
уровней привилегированности, не равных 0 (т.е выполнения их не
из наиболее привилегированного уровня). Механизмы защиты
операций ввода/вывода подробно описаны в Главе 8.
6.6  Команды проверки достоверности указателей
-----------------------------------------------------------------
Проверка достоверности указателей необходима для поддержания
изолированности разных уровней привилегированности. Она состоит
из следующих шагов:
1. Проверка того, что процедура, создавшая данный указатель,
   имеет права доступа к данному сегменту.
2. Проверка того, что тип сегмента совместим с запрошенным
   способом его использования.
3. Проверка того, что смещение указателя не превышает границу
   сегмента.
Хотя процессор i486 автоматически выполняет проверки 2 и 3 при
выполнении команды, в выполнении первой проверки должно
участвовать программное обеспечение. Для этого предназначена
команда ARPL. Программное обеспечение может также выполнять
проверки 2 и 3 не дожидаясь, пока будет сгенерировано исключение
процессора. Для этого предназначены команды LAR, LSL, VERR и
VERW.
В режиме пользователя может выполняться дополнительная проверка
выравнивания. Когда одновременно установлены бит AM регистра CR0
и флаг AC, невыравненные ссылки к памяти ведут к генерации
исключения. Это свойство полезно для программ, которые
используют два младшие бита указателя для идентификации типа
данных адресуемой указателем структуры. Например, подпрограмма в
библиотеке математических функций может принимать указатели на
числовые структуры данных. Если типу такой структуры присвоен
код 10 (двоичный), записанный в двух младших битах указателей на
этот тип, то математические подпрограммы могут выполнять
коррекцию по коду типа, прибавляя смещение -10 (двоичное). При
получении подпрограммой неверного указателя типа ссылка будет
невыравненной, что приведет к генерации исключения. Проверка
выравнивания ускоряет работу программ, написанных на языках
искуственного интеллекта, таких как Lisp, Prolog, Smalltalk и
C++. Она также может использоваться для ускорения проверки
признака типа указателя.
LAR (Загрузить права доступа) используется для верификации того,
что указатель ссылается на сегмент с совместимостью по уровню
привилегированности и типу. Команда LAR имеет один операнд -
селектор сегмента для дескриптора, права доступа которого должны
быть проверены. Дескриптор сегмента должен быть доступным для
чтения на уровне привилегированности, численно большем (т.е.
менее привилегированном), чем CPL и RPL селектора. Если
дескриптор доступен для чтения, то команда LAR принимает второе
двойное слово дескриптора, маскирует его значением 00FxFF00H,
записывает результат в заданный 32-разрядный регистр назначения
и устанавливает флаг ZF. (x означает, что соответствующие четыре
бита записанного значения неопределены). Будучи однажды
загруженным, прова доступа могут быть затем проверены. Команда
LAR позволяет тестировать все допустимыке типы дескрипторов.
Если RPL или CPL превышает DPL, или если селектор сегмента
превышает границу для таблицы дескрипторов, права доступа не
возвращаются, и флаг ZF очищается. Доступ к конформным кодовым
сегментам допускается из любых уровней привилегированности.
LSL (Загрузить границу сегмента) позволяет программно
тестировать границу дескриптора сегмента, если дескриптор, на
который ссылается селектор сегмента (в памяти или в регистре),
доступен для чтения на текущем CPL. Команда LSL загружает
заданнный 32-разрядный регистр 32-разрядным гранулированным
побайтно значением границы, вычисленным на основе
конкатенированных полей границы и бита грануляции G дескриптора.
Это может быть сделано только для дескрипторов, описывающих
сегменты (данных, кода, состояния задачи и таблиц дескрипторов);
дескрипторы шлюзов таким способом недоступны. (В таблице 6-3
подробно перечислено, какие типы допустимы, а какие нет).
Интерпретация границы зависит от типа сегмента. Например,
сегменты данных, расширяющиеся вниз (стековые сегменты)
рассматривают границу иначе, чем все прочие типы сегментов. Для
обеих команд, LAR и LSL, флаг ZF устанавливается в том случае,
если загрузка была выполнена успешно; в противном случае флаг ZF
очищается.
     Таблица 6-3. Допустимые типы дескрипторов команды LSL
-----------------------------------------------------------------
Код типа             Тип дескриптора                  Допустим?
-----------------------------------------------------------------
   0                 Зарезервирован                   Нет
   1                 Зарезервирован                   Нет
   2                 LDT                              Да
   3                 Зарезервирован                   Нет
   4                 Зарезервирован                   Нет
   5                 Шлюз задачи                      Нет
   6                 Зарезервирован                   Нет
   7                 Зарезервирован                   Нет
   8                 Зарезервирован                   Нет
   9                 Доступен TSS центрального
                     процессора i486                  Да
   A                 Зарезервирован                   Нет
   B                 Занят TSS центрального
                     процессора i486                  Да
   С                 Шлюз вызова центрального
                     процессора i486                  Нет
   D                 Зарезервирован                   Нет
   E                 Шлюз прерывания центрального
                     процессора i486                  Нет
   С                 Шлюз ловушки центрального
                     процессора i486                  Нет
-----------------------------------------------------------------
6.7.1  Проверка достоверности дескриптора
-----------------------------------------------------------------
Процессор i486 имеет две команды, VERR и VERW, которые
определяют, указывает ли селектор сегмента на сегмент, который
доступен для чтения или записи для текущего CPL. Ни одна их этих
команд не вызывает защитного исключения, если сегмент
недоступен.
VERR (Верификация доступности чтения) выполняет верификацию
доступности сегмента для чтения и устанавливает флаг ZF, если
для текущего CPL этот сегмент доступен для чтения. Команда VERR
проверяет следующее:
- Селектор сегмента указывает на дескриптор сегмента в пределах
  границ GDT или LDT.
- Селектор сегмента индексирует дескриптор сегмента кода или
  данных.
- Сегмент доступен для чтения и  имеет  совместимый  уровень
  привилегированности.
Проверка привилегированности для сегментов данных и
не-конформных кодовых сегментов удостоверяет, что DPL имеет
меньший уровень привилегированности, чем CPL или RPL селектора.
Конформные сегменты на уровень привилегированности не
проверяются.
VERW (Верификация доступности записи) аналогична команде VERR :
она выполняет верификацию доступности сегмента для записи и
устанавливает флаг ZF, если этот сегмент доступен для чтения.
Команда VERW удостоверяет, что дескриптор попадает в нужные
границы, действительно является дескриптором сегмента, сегмент
доступен для чтения и имеет DPL с менее привилегированным
уровнем, нежели CPL или RPL селектора. Кодовые сегменты никогда
не бывают доступными для записи: как конформные, так и
не-конформные.
6.7.2  Целостность указателя и RPL
-----------------------------------------------------------------
Запрошенный уровень привилегированности (RPL) может
предотвратить случайное использование указателей, разрушающих
более привилегированный код из кода с меньшим уровнем
привилегированности.
Распространенным примером может служить файловая системная
процедура FREAD (идентификатор_файла, n_байтов,
указатель_буфера). Эта гипотетическая процедура считывает данные
из дискового файла в буфер, затирая любое ранее записаное
содержимое этого буфера. Она обслуживает запросы программ,
работающих на прикладном уровне, но сама должна работать на
привилегированном уровне, чтобы всегда иметь возможность
обслуживать ввод/вывод операционной системы. Если прикладная
программа передаст этой процедуре неверный указатель буфера,
который указывает на важные участки кода или данных в
привилегированном адресном пространстве, процедура может
выполнить действия, ведущие к разрушению системы.
Избежать подобной проблемы позволяет использование RPL. RPL
позволяет назначить селектору переопределенную
привилегированность. Такая переопределенная привилегированность
представляет собой уровень привилегированности кодового
сегмента, сгенерировавшего данный селектор сегмента. В
вышеприведенном примере RPL должен представлять собой CPL
прикладной программы, вызвавшей процедуру системного уровня.
Процессор i486 автоматически проверяет любой загруженный в
сегментный регистр селектор, определяя, допускает ли его RPL
выполнить запрошенный доступ.
Для того, чтобы воспользоваться преимуществами, даваемыми такой
проверкой процессором RPL, вызываемая процедура должна только
проверять, чтобы все передаваемые ей селекторы сегмента имели
RPL с тем же или меньшим уровнем привилегированности, что и CPL
исходного источника запроса. Если селектор используется для
доступа к сегменту, к которому источник запроса не может
обратиться напрямую, т.е. RPL которого имеет меньшую
привилегированность, чем DPL запрошенного сегмента, то при
загрузке селектора в сегментный регистр генерируется исключение
общей защиты.
ARPL (Настроить запрошенный уровень привилегированности)
настраивает поле RPL селектора сегмента в большее из значений
(меньший уровень привилегированности), выбирая из его исходного
значения и значения поля RPL для селектора сегмента, записанного
в регистр общего назначения. Поля RPL находятся в двух младших
битах селектора сегмента и регистра. Последний обычно
представляет собой копию регистра CS вызывающей процедуры в
стеке. Если при такой настройке RPL селектора изменяется, то
происходит установка флага ZF; в противном случае флаг ZF
очищается.
6.8  Защита на уровне страниц
-----------------------------------------------------------------
Защита работает как на уровне сегментов, так и на уровне
страниц. При использовании плоской модели сегментации памяти
защита на уровне страниц также предотвращает недопустимое
взаимное влияние между программами.
Каждая ссылка к памяти контролируется на удовлетворение проверок
защиты. Все проверки выполняются до начала цикла обращения к
памяти; любое нарушение защиты предотвращает начало этого цикла
и генерирует исключение. Поскольку эти проверки выполняются
параллельно с трансляцией адреса, они не влекут дополнительных
затрат времени процессора. Существует два вида проверки защиты
на уровне страниц:
1. Ограничения на адресуемый домен памяти.
2. Проверка типа.
Нарушение защиты приводит к генерации исключения. Механизм
исключений описан в Главе 9. В данной главе описаны нарушения
защиты, ведущие к исключениям.
6.8.1  Элементы страничных таблиц содержат параметры защиты
-----------------------------------------------------------------
На Рисунке 6-10 показаны поля элемента страничной таблицы,
которые управляют доступом к странице. Проверки защиты
применяются к страничным таблицам как первого, так и второго
уровня.
6.8.1.1  Ограничения адресуемого домена памяти
-----------------------------------------------------------------
Для страниц и сегментов понятие привилегированности
интерпретируется по-разному. Для сегментов существует четыре
уровня привилегированности, лежащих в диапазоне от 0 (высший
уровень привилегированности) до 3 (низший уровень
привилегированности). для страниц существует два уровня
привилегированности:
1. Уровень супервизора (U/S=0) - для операционной системы,
   прочего системного программного обеспечения (например,
   драйверов устройств), а также для защищаемых системных данных
   (например, страничных таблиц).
2. Уровень пользователя (U/S=1) - для прикладных кодов и данных.
Уровни привилегированности, используемые в сегментации,
отображаются в уровнях привилегированности страниц. Если CPL
равен 0, 1 или 2, то процессор работает на уровне супервизора.
Если же CPL равен 3, то процессор работает на уровне
пользователя. Когда процессор работает на уровне супервизора,
все страницы являются доступными. Когда процессор работает на
уровне пользователя, доступны только страницы, имеющие уровень
пользователя.
31                               12 11                      0
--------------------------------------------------------------
|                                  |       |   | | |P|P|U|R| |
| Адрес страничного блока 31...12  |Доступн|0 0|D|A|C|W|/|/|P|
|                                  |       |   | | |D|T|S|W| |
--------------------------------------------------------------
R/W   Чтение/Запись
U/S   пользователь/Супервизор
     Рисунок 6-10. Поля защиты элемента страничной таблицы
6.8.1.2  Проверка типа
-----------------------------------------------------------------
Механизмом защиты распознаются только два вида страниц:
1. Доступ Только для Чтения (R/W=0)
2. Доступ на Чтение/Запись (R/W=1).
Когда процессор работает на уровне супервизора при очищенном
бите WP в регистре CR0 (в состоянии бита, соответствующем
инициализации при сбросе системы), все страницы являются
одновременно доступными для чтения и записи (признак защиты
записи игнорируется). Когда процессор работает на уровне
пользователя, то для записи доступны лишь страницы уровня
пользователя, помеченные признаком Чтение/Запись. Страницы
уровня пользователя, помеченные для Чтения/Записи или Только для
Чтения, являются доступными для чтения. Страницы уровня
супервизора с уровня пользователя недоступны ни для чтения, ни
для записи. При попытке нарушения прав доступа к защищенным
страницам генерируется исключение общей защиты.
В отличие от процессора 386 DX процессор i486 позволяет защищать
страницы уровня пользователя от записи в режиме доступа
супервизора. Установка бита WP в регистре CR0 включает
чувствительность режима супервизора к защите страниц от записи в
режиме пользователя. Это средство полезно для реализации
стратегии "записи-на-копии", используемой некоторыми
операционными системами, например UNIX, для создания задачи (это
средство также называется порождением параллельных процессов или
просто порождением).
При создании новой задачи можно скопировать все адресное
пространство порождающей задачи. Это дает порожденной задаче
полный, дубликатный набор сегментов и страниц порождающей
задачи. Стратегия "записи-на-копии" экономит область памяти и
время, отображая порожденные сегменты и страницы в тех же
сегментах и страницах, что используются порождающей задачей.
Частная копия страницы создается только в случае, когда одна из
задач выполняет запись в эту страницу.
6.8.2  Объединение защиты страничных таблиц обоих уровней
-----------------------------------------------------------------
Для каждой отдельной страницы аттрибуты защиты соответствующего
ей элемента каталога страниц (таблицы страниц первого уровня)
могут отличаться от аттрибутов защиты элемента таблицы страниц
второго уровня. Процессор i486 проверяет защиту страницы,
рассматривая атртрибуты защиты, заданные в таблицах обоих
уровней. В Таблице 6-4 показана защита, обеспечиваемая
возможными комбинациями аттрибутов защиты при очищенном бите WP.
       Таблица 6-4. Объединенная защита каталога страниц
                       и таблицы страниц
----------------------------------------------------------------
|  Элемент каталога     Элемент таблицы       Объединенный     |
|      страниц              страниц               эффект       |
|--------------------------------------------------------------|
|Привиле|Тип         |Привеле|Тип         |Привеле|Тип         |
|гирован|доступа     |гирован|доступа     |гирован|доступа     |
|ность  |            |ность  |            |ность  |            |
|--------------------------------------------------------------|
|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|
|Пользов|ТолькоЧтение|Пользов|ЧтениеЗапись|Пользов|ТолькоЧтение|
|Пользов|ЧтениеЗапись|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|
|Пользов|ЧтениеЗапись|Пользов|ЧтениеЗапись|Пользов|ЧтениеЗапись|
|Пользов|ТолькоЧтение|Суперв |ТолькоЧтение|Пользов|ТолькоЧтение|
|Пользов|ТолькоЧтение|Суперв |ЧтениеЗапись|Пользов|ТолькоЧтение|
|Пользов|ЧтениеЗапись|Суперв |ТолькоЧтение|Пользов|ТолькоЧтение|
|Пользов|ЧтениеЗапись|Суперв |ЧтениеЗапись|Пользов|ЧтениеЗапись|
|Суперв |ТолькоЧтение|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|
|Суперв |ТолькоЧтение|Пользов|ЧтениеЗапись|Пользов|ТолькоЧтение|
|Суперв |ЧтениеЗапись|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|
|Суперв |ЧтениеЗапись|Пользов|ЧтениеЗапись|Пользов|ЧтениеЗапись|
|Суперв |ТолькоЧтение|Суперв |ТолькоЧтение|Суперв |ЧтениеЗапись|
|Суперв |ТолькоЧтение|Суперв |ЧтениеЗапись|Суперв |ЧтениеЗапись|
|Суперв |ЧтениеЗапись|Суперв |ТолькоЧтение|Суперв |ЧтениеЗапись|
|Суперв |ЧтениеЗапись|Суперв |ЧтениеЗапись|Суперв |ЧтениеЗапись|
----------------------------------------------------------------
6.8.3  Переопредлеление защиты страниц
-----------------------------------------------------------------
Некоторые виды доступа проверяются, как имеющие уровень
привилегированности 0, для любых значений CPL:
- Доступ к дескрипторам сегментов (LDT, GDT, TSS и IDT).
- Доступ к внутреннему стеку по время выполнения команды CALL,
  или исключений и прерываний, когда происходит изменение уровня
  привилегированности.
6.9 Объединение защиты сегментов и страниц
-----------------------------------------------------------------
При разрешенном механизме подкачки страниц процессор i486
сначала выполняет проверки защиты сегмента, а затем проверки
защиты страницы. Если процессор обнаруживает нарушение защиты на
любом из уровней защиты, как сегмента, так и страницы,
выполнение не продолжается: генерируется исключение. Если
исключение генерируется механизмом защиты сегментов, исключение
защиты страниц не генерируется.
Например, можно определить большой сегмент данных, имеющий
некоторые части с аттрибутом доступа Только для Чтения, а другие
части - для Чтения/Записи. В этом случае элементы каталога
страниц (или таблицы страниц) для частей с доступом Только для
Чтения будут иметь биты U/S и R/W, задающие отсутствие прав
доступа ко всем страницам, описанным данным элементом каталога
(или отдельным страницам, заданным в страничных таблицах второго
уровня). Данный метод может быть использован, например, для
определения большого сегмента данных, часть которого
предназначена Только для Чтения (для разделяемых или
ПЗУ-резидентных данных). Тем самым определяется "плоское"
пространство данных как один большой сегмент, с "плоскими"
указателями, используемыми для доступа к этому "плоскому"
пространство, с защитой разделяемых данных, разделяемых файлов,
отображаемых в виртуальном пространстве, а также областей
супервизора.


Яндекс цитирования