Глава 1. Проверки, обеспечивающие защиту.
Когда используется механизм защиты, каждое обращение к памяти должно удовлетворять целому ряду условий защиты. Все проверки выполняются до начала обращения к памяти и любые нарушения приводят к генерации исключений. Эти проверки происходят одновременно с трансляцией адреса и не приводят к потере производительности.
Проверки защиты делятся на следующие категории:
Проверка предела.
| Проверка типа.
| Проверка уровня привилегий.
| Ограничение адресного пространства.
| Ограничение входных точек процедуры.
| Ограничение набора команд.
| |
В данном разделе рассматривается механизм защиты, применяемый в защищённом режиме. Защита в режиме реальных адресов и виртуального 8086 рассматривается в разделе "Режим виртуального процессора 8086".
1.1. Разрешение и запрещение защиты сегментов и страниц.
Установка флага PE в регистре CR0 заставляет процессор переключиться в защищённый режим, который в свою очередь автоматически обеспечивает механизм защиты, причём та его часть, которая отвечает за защиту по привилегиям, может вообще не использоваться, если программа, работающая в защищённом режиме использует все дескрипторы и селекторы на нулевом уровне привилегий.
Защита на уровне страниц автоматически обеспечивается при включении страничного преобразования установкой бита PG в CR0. Эту защиту можно отключить, выполнив следующие операции:
Сбросить флаг WP в регистре CR0.
| Установить флаги R/W и (U/S) в каждом элементе каталога и таблиц страниц.
| |
Эти действия делают каждую страницу доступной для чтения и записи с любого уровня привилегий, что отменяет защиту на уровне страниц.
1.2. Поля и флаги, используемые для защиты на уровне сегментов и страниц.
Флаг типа дескриптора (S) - (4-й бит байта прав доступа дескриптора). Определяет вид дескриптора - если 0, то он описывает системный объект, если 1, то сегмент кода или данных.
| Поле типа дескриптора - (Биты 0..3 байта прав доступа). Определяет тип системного объекта, сегмента кода или данных.
| Поле предела дескриптора - (Биты 0..15 и 48..51 в дескрипторе). Определяют размер сегмента в единицах размера (байтах или 4Кб страницах).
| Флаг гранулярности G - (Бит 55 дескриптора). Определяет единицы измерения размера сегмента: 0 - сегмент измеряется в байтах, 1 - в 4Кб страницах.
| Флаг E - (Бит 2 байта прав доступа дескриптора сегмента данных). Определяет расширение сегмента: 0 - адреса растут вверх (как в обычном сегменте), 1 - вниз (т.е. наоборот).
| Поле уровня привилегий дескриптора (DPL) - (Биты 5 и 6 байта прав доступа). Определяют уровень привилегий сегмента.
| Поле запрошенного уровня привилегий (RPL) - (Биты 0 и 1 любого селектора сегмента). Содержат запрашиваемый уровень привилегий при обращении к дескриптору.
| Поле текущего уровня привилегий (CPL) - (Биты 0 и 1 регистра CS). Содержат уровень привилегий текущей процедуры.
| Флаг пользователя/системы (User/Supervisor) (U/S) - (Бит 2 элемента каталога или таблицы страниц). Определяют тип страницы: 0 - системный, 1 - пользовательский.
| Поле чтения/записи (Read/write) (R/W) - (Бит 1 элемента каталога или таблицы страниц). Определяет тип доступа к странице: 0 - только чтение, 1 - чтение и запись.
| |
1.3. Проверка предела.
Проверка предела дескриптора сегмента не позволяет программе обращаться за пределы сегмента. Значение предела зависит от флага гранулярности (G) дескриптора. Предел определяет максимальное значение смещения в сегменте.
Для сегментов данных, расширяющихся вниз, предел определяет последний адрес, доступ к которому запрещён внутри сегмента. Допустимыми будут адреса в диапазоне от (предел + 1) до FFFFh, если флаг D=0 и от (предел + 1) до FFFFFFFFh, если D=1. Максимальный размер такие сегменты имеют с пределом, равным нулю.
Процессор также проверяет пределы дескрипторных таблиц GDT, IDT, LDT и текущего сегмента TSS, не позволяя обращаться за их пределы.
1.4. Проверка типа
Дескриптор сегмента содержит информацию о типе в двух элементах:
Флаг S (тип дескриптора).
| Поле типа.
| |
Процессор использует эту информацию для определения ошибочных действий программ, когда они пытаются использовать сегмент или шлюз неправильным или несоответствующим образом.
Флаг S определяет, описывает дескриптор системный объект или сегмент кода или данных. Поле типа содержит 4 дополнительных бита, определяя различные типы дескрипторов.
В таблице 1-1 приведены значения поля типа дескрипторов, в таблице 1-2 приведены значения полей для системных дескрипторов.
Процессор проверяет значение типа несколько раз, когда оперирует селекторами и дескрипторами. Далее приведены примеры типичных операций, где происходит проверка типов:
- | В регистр CS можно загрузить только селектор сегмента кода. |
- | Селектор сегмента нечитаемого кода нельзя загружать в сегментные регистры данных (DS, ES, FS и GS). |
- | В регистр SS можно загружать только селектор сегмента данных, разрешённого для записи. |
- | В LDTR можно загрузить можно загрузить только селектор для LDT. |
- | В TR можно загрузить можно загрузить только селектор для TSS. |
- | Нельзя записывать в сегмент кода. |
- | Нельзя записывать в сегмент данных, предназначенный только для чтения. |
- | Нельзя читать из сегмента кода, предназначенного только для выполнения. |
- | Команда LAR должна обращаться к дескриптору сегмента или шлюза для сегментов LDT, TSS, шлюзу вызова, шлюзу задачи, сегменту кода или данных. |
- | Команда LSL должна обращаться к дескриптору сегмента LDT, TSS, кода или данных. |
- | Элементом IDT может быть только шлюзы прерывания, ловушки или вызова. |
- | При выполнении команд FAR CALL и FAR JMP процессор проверяет тип дескриптора, селектор которого содержится в адресе назначения этих команд. Если это дескриптор сегмента кода или шлюза вызова, то происходит передача управления по этому адресу; если дескриптор описывает TSS или шлюз задачи, то происходит переключение задач. |
Бит # | 11 | 10 | 9 | Тип | |
Название | E | W | |||
0 | 0 | 0 | Данные | Только чтение | |
0 | 0 | 1 | Данные | Чтение и запись | |
0 | 1 | 0 | Данные | Только чтение, расширяется вниз | |
0 | 1 | 1 | Данные | Чтение и запись, расширяется вниз | |
1 | 0 | 0 | Код | Только выполнение | |
1 | 0 | 1 | Код | Только выполнение | |
1 | 1 | 0 | Код | Только выполнение, согласованный | |
1 | 1 | 1 | Код | Выполнение и считывание, согласованный |
Значе- ние | Поле типа1
биты: 3 2 1 0 | Системный объект
0
| 0 0 0 0
| Зарезервировано
| 1
| 0 0 0 1
| 16-разрядный TSS (Свободный)2
| 2
| 0 0 1 0
| LDT
| 3
| 0 0 1 1
| 16-разрядный TSS (Занятый)2
| 4
| 0 1 0 0
| 16-разрядный шлюз вызова (call gate)
| 5
| 0 1 0 1
| Шлюз задачи (task gate)
| 6
| 0 1 1 0
| 16-разрядный шлюз прерывания (interrupt gate)
| 7
| 0 1 1 1
| 16-разрядный шлюз ловушки (trap gate)
| 8
| 1 0 0 0
| Зарезервировано
| 9
| 1 0 0 1
| 32-разрядный TSS (Свободный)2
| 10
| 1 0 1 0
| Зарезервировано
| 11
| 1 0 1 1
| 32-разрядный TSS (Занятый)2
| 12
| 1 1 0 0
| 32-разрядный шлюз вызова (call gate)
| 13
| 1 1 0 1
| Зарезервировано
| 14
| 1 1 1 0
| 32-разрядный шлюз прерывания (interrupt gate)
| 15
| 1 1 1 1
| 32-разрядный шлюз ловушки (trap gate)
| |
Примечания:
1. | Полем типа в дескрипторе системного объекта являются 4 бита в 5-м байте дескриптора или его битами 40..43. |
2. | Для дескрипторов TSS второй по счёту бит в поле типа называется B от слова "Busy" и этот бит отражает занятость задачи: 1/0 - задача занята / свободна. |
1.5. Проверка нулевого селектора сегмента.
Попытка загрузки нулевого селектора в регистр CS или SS приводит к генерации исключение общей защиты (#GP). Этот селектор можно загружать в регистры DS, ES, FS или GS, но тогда обращение через них к памяти приводит к генерации такого же исключения.
Следующая глава | Оглавление | Вопросы? Замечания? Пишите: sasm@narod.ru |
Copyright © Александр Семенко. |