7.4.6.1.5. Защита
Для облегчения обнаружения и идентификации ошибок МП
80386 сконструирован со
встроенными методами защиты. Основной единицей защиты является сегмент, и
дескрипторы сегментов хранят необходимые параметры защиты. На рис. 6.2 показаны имеющие отношение к защите поля дескрипторов
сегментов.
Поля типа сегментов данных и исполняемой программы
содержат биты, которые
в дальнейшем определяют цель использования данного сегмента. Бит 9
интерпретируется по-разному в сегменте исполняемой программы и в сегменте данных.
Бит разрешения чтения. В сегменте исполняемой программы бит 9 показывает, разрешается ли командам
считывать данные из этого сегмента. Чтение из исполнительного сегмента может быть осуществлено
либо через регистр CS путем использования префикса «CS», либо загрузкой селектора его дескриптора в один
из регистров сегмента данных (DS, ES, FS, GS).
Бит разрешения записи. В сегменте данных бит 9 определяет, могут ли команды осуществлять запись в этот сегмент.

Рис. 6.2. Поля защиты
дескрипторов сегментов.
Перед началом цикла обмена с памятью аппаратным путем
проверяется каждая ссылка
в память для верификации того, что эта ссылка удовлетворяет критерию защиты. Любое нарушение предотвращает начало цикла
обмена и приводит к обработке исключения.
Так как эти проверки и трансляция адреса осуществляются одновременно
друг с другом, то потери производительности малы или отсутствуют.
Параметры защиты запоминаются в дескрипторах сегментов во
время их создания системными программами.
Когда программа загружает селектор в регистр
сегмента, то МП 80386 загружает не только базовый адрес сегмента, но также
информацию о защите. Каждый регистр сегмента в своей невидимой программисту
части имеет биты для хранения базы, границы, типа и уровня привилегий. Любые последовательные проверки защиты того же самого
сегмента не требуют дополнительных
циклов обращения к памяти.
Защита имеет восемь аспектов: проверку типа, проверку
границы, ограничение доступа
к данным, ограничение точек входа в процедуру, ограничение набора
команд, проверку достоверности указателя и дескриптора,
защиту страницы и сегмента.
Проверка поля TYPE. Поле TYPE (тип) дескриптора различно для
дескрипторов разного формата и
определяет желаемый способ использования сегмента. Проверка типа может быть использована для обнаружения программных
ошибок, которые представляют собой попытки использовать сегмент способом,
неожиданным для программиста.
Процессор проверяет информацию о типе в двух случаях.
1. Если команда
явно или неявно обращается к регистру сегмента. Некоторые сегменты могут использоваться командами только
предопределенными способами. Например:
если бит разрешения записи не установлен, то ни одна
команда не может записывать в сегмент
данных;
до
тех пор, пока не установлен бит разрешения чтения, ни одна команда не может
читать из исполнительного сегмента;
ни одна команда не может записывать в исполнительный
сегмент.
2. Если
селектор дескриптора загружается в регистр сегмента. Некоторые регистры сегментов могут содержать дескрипторы
только определенных типов. Например:
в регистр SS могут быть загружены селекторы сегментов данных
только с разрешением
записи;
регистр CS может загружаться селектором только
исполнительного сегмента;
селекторы исполнительных сегментов с защитой от чтения не
могут быть загружены в регистры
сегментов данных.
Проверка границы. Проверка границы обнаруживает такие программные
ошибки, как
неверные вычисления значения указателя адреса или выход за допустимые пределы индексов массива. Эти
ошибки обнаруживаются в момент возникновения, что существенно облегчает определение их причины.
Без проверки границы такие ошибки могли бы исказить другие модули. Это
искажение обнаружилось бы позднее по аномальной работе искаженного модуля, но
идентифицировать ошибку в этот момент
уже намного труднее.
В дескрипторе сегмента процессор использует поле LIMIT
(граница) для того, чтобы
предотвратить адресацию из программы в область вне сегмента. При интерпретации поля LIMIT процессор
использует бит дробности G. Для сегментов данных процессор использует также бит направления
расширения Е и бит большого сегмента В.
В табл. 6.1 приведены некоторые комбинации этих битов.
Если бит G = 0, границей является
значение 20-разрядного поля границы дескриптора. Граница может изменяться от 0 до OFFFFFH (220
— 1 или 1 Мбайт). Если
бит G = 1, то МП 80386 присоединяет 12 младших единичных битов к значению поля границы. В этом
случае реальная граница может изменяться от OFFFH (212 - 1 или 4
Кбайт) до OFFFFFFH (232 - 1 или 4 Гбайт).
Процессор использует поле LIMIT в таблицах дескрипторов для
того, чтобы предотвратить выбор программами входа в таблицу, расположенного вне
таблицы. Поле LIMIT определяет последний достоверный байт последнего
дескриптора в этой таблице. Поскольку
дескриптор имеет в длину восемь байтов, то значение границы для таблицы, содержащей N дескрипторов,
равно (N*8 — 1).
Свойство расширения вниз позволяет расширить стек путем
копирования его в сегмент большего размера без необходимости обновления также и
внутристековых указателей.
Для всех типов сегментов, кроме расширяемых вниз
сегментов данных, значение границы на единицу меньше размера сегмента в байтах. В МП 80386
вызывается обработка исключения в любом
из следующих случаев:

Таблица 6.1. Комбинации битов
Е, G, В
попытка обращения к двойному слову памяти по адресу,
большему или равному
значению LIMIT минус два;
попытка обращения к слову памяти по адресу, большему или
равному значению LIMIT;
- попытка
обращения к байту памяти по адресу, большему значения LIMIT.Для расширяемых вниз сегментов данных поле LIMIT имеет
ту же самую
функцию, но интерпретируется по-другому. Для этих
сегментов данных диапазон достоверных адресов простирается от значения (LIMIT + 1)
вплоть до 64К — 1 или 4Г — 1 в зависимости от значения бита В. Расширяемый вниз сегмент
достигает максимального
размера, когда значение LIMIT равно нулю. Бит В управляет также форматом обмена
со стеком по умолчанию. Если В = 1, то используется 32-разрядное значение, иначе-16-разрядное.
Ограничение доступа к данным. Перед тем как процессор
сможет адресовать операнды в памяти,
программа МП 80386 загружает селектор сегмента данных в один из регистров
сегмента данных (DS, ES, FS, GS или SS). Затем МП
80386 сравнивает уровни привилегий для того,
чтобы оценить возможность доступа к этим
данным. Как показано на рис. 6.3, в эту проверку входят три различных уровня
привилегий: текущий уровень привилегий (CPL), уровень привилегий
инициатора запроса
(RPL) селектора, использованного для спецификации целевого сегмента, и уровень привилегий дескриптора (DPL) целевого сегмента.

Рис. 6.3. Проверка
привилегий доступа к данным.
Командам разрешается загружать регистр сегмента данных и
получать доступ к соответствующему
сегменту только в том случае, если уровень DPL целевого сегмента численно больше
(меньший уровень привилегий) или равен большему из значений уровня CPL и уровня
RPL селектора. Это может быть использовано для предотвращения изменения или
чтения таблиц операционной системы прикладными программами.
Менее распространенным является использование сегмента
программы для хранения
данных. Сегменты программы могут содержать константы, однако невозможно
записать что-либо в сегмент, определенный как сегмент программы. Существуют три способа чтения данных из
сегмента программы
Использовать префикс «CS» для чтения разрешенного к
чтению исполнительного
сегмента, чей селектор уже загружен в регистр CS.
Загрузить один из регистров сегмента данных селектором
несогласованного, разрешенного
к чтению исполнительного сегмента.
Загрузить
один из регистров сегмента данных селектором согласованного, разрешенного к чтению исполнительного сегмента.
Способ 1 можно использовать всегда, так как по
определению уровень DPL сегмента программы по регистру CS равен
уровню CPL. Способ 2 основан на тех же правилах, что и для доступа к данным. Способ 3 также
всегда пригоден, так как уровень привилегий сегмента, чей бит согласованности установлен,
совпадает с уровнем CPL независимо от уровня DPL.
Передачи управления. В МП 80386 управление передается
путем использования исключений,
прерываний, а также с помощью команд CALL, JMP, INT, IRET, RET. Исключения и прерывания являются специальными
случаями и рассмотрены в гл. 3. В этом же разделе обсуждаются формы команд.
Существуют как «ближние», так и «дальние» формы команд CALL, JMP, RET.
«Ближняя» форма передает управление внутри текущего
сегмента программы и поэтому
является предметом проверки только на превышение границы. Процессор просто
удостоверяется, что приемник команды находится в пределах текущего исполнительного сегмента. Так как
эта граница кэшируется в регистр CS, то
проверки защиты для ближних передач не требуют
дополнительных тактов генератора.
«Дальние»
команды CALL и JMP передают управление в другие сегменты, из-за чего МП 80386 проверяет уровни привилегий.
Существуют два способа, которыми команда
CALL или JMP может ссылаться на другой сегмент: операнд выбирает дескриптор вентиля вызова или
дескриптор другого исполнительного сегмента.
Два разных уровня привилегий входят в проверку привилегий
для передачи управления,
которая не использует вентиль вызова: текущий уровень привилегий CPL и
уровень привилегий дескриптора DPL целевого сегмента. Обычно уровень CPL равен
уровню DPL исполняемого в данный момент сегмента. Однако уровень CPL может
быть больше уровня DPL, если установлен бит согласованности в дескрипторе
исполняемого сегмента.
Исполнительный сегмент, в дескрипторе которого бит
согласованности (бит 10) установлен, называется согласованным сегментом. Согласованный сегмент
позволяет использовать процедуры, которые могут вызываться с различных уровней привилегий, но должны исполняться на уровне
привилегий вызывающей процедуры. Если
управление передается в согласованный сегмент, уровень CPL не изменяется. Это единственный случай, когда
уровень CPL может быть не равным уровню DPL исполняемого в данный момент сегмента.
Процессор позволяет осуществить командами CALL или JMP
соответственно вызов
или переход в другой сегмент, только если: установлен бит согласованности в дескрипторе целевого сегмента
программы и уровень DPL целевого сегмента меньше или равен уровню CPL; или уровень целевого сегмента
равен уровню CPL.
Большинство сегментов программы являются
несогласованными. Для этих сегментов управление может быть передано к исполнительному сегменту
только на том же
самом уровне привилегий. Для передачи управления к численно меньшим уровням привилегий команда CALL
используется с дескрипторами вентиля вызова. Команда JMP никогда не может передать
управление к несогласованному сегменту, чей уровень DPL не равен уровню CPL.
С помощью дескрипторов вентиля МП 80386 обеспечивает
защиту передач управления между исполнительными сегментами с различными
уровнями привилегий.
Существуют четыре типа вентилей: вентили задачи, вентили ловушки, вентили прерывания и вентили вызова.
Вентили задачи используются для переключения задач и рассмотрены в другом разделе. Вентили
ловушки и вентили прерывания используются исключениями и прерываниями и описаны в соответствующих
разделах. В этом
разделе мы рассмотрим только вентили вызова.
Вентиль вызова используется для описания уровня
привилегий и определения точки входа в процедуру. Дескрипторы вентиля вызова используются
командами CALL и JMP таким же способом, что и дескрипторы сегмента программы. Когда аппаратно выявляется, что
селектор приемника ссылается на дескриптор вентиля, то команда исполняется в зависимости
от содержимого вентиля вызова.
При использовании защиты гарантируется, что селектор и
относительный адрес образуют
указатель точки входа процедуры. Все передачи управления из другого сегмента направляются в
достоверную точку входа, а не в середину процедуры или в середину команды, что возможно.
Дело в том, что операционная система управляет всеми действиями в целом и может удостовериться,
что будет исполняться программа, имеющая необходимую степень доверия. Это позволяет правильным образом
предоставлять
увеличивающиеся привилегии.
Процессор проверяет четыре уровня привилегий для
санкционирования передачи управления через вентиль вызова: текущий уровень привилегий CPL, уровень привилегий дескриптора DPL вентиля,
уровень привилегий инициатора запроса
RPL селектора, который определяет
вентиль вызова, и уровень DPL дескриптора целевого исполнительного сегмента.
Из всех команд только CALL может использовать вентили для
передачи управления
к меньшим уровням привилегий. Командой JMP вентиль может быть использован только для передачи
управления к исполнительному сегменту с тем же самым уровнем привилегий или же к согласованному
сегменту.
Межуровневая передача запрашивается в том случае, если
сегмент программы, являющийся
пунктом назначения вентиля вызова, имеет уровень привилегий, отличный от уровня CPL. Для поддержания целостности
системы каждый уровень привилегий имеет отдельный стек. Эти стеки гарантируют, что для вызовов процессов с меньших уровней
привилегий зарезервирована достаточная по объему область стека. Без такого
стека процедура с достаточным уровнем доверия работала бы неправильно, в случае
если вызываемой процедуре не обеспечивается достаточное пространство в стеке
вызывающей процедуры.
Процессор находит эти стеки через сегмент TSS. Поскольку каждая задача имеет отдельный сегмент TSS, то она
соответственно имеет и отдельный стек. Системные программы создают сегменты TSS и
располагают в них правильные указатели стеков; начальные указатели являются значениями, разрешенными
только к чтению. Процессор никогда не изменяет их во время исполнения
программы. Системные
программы гарантируют также, что каждый стек обладает пространством, достаточным для размещения
полного старого указателя стека SS:ESP (указателя сегмента стека и
расширенного указателя стека), адреса возврата, всех параметров и локальных
переменных, которые могут быть нужны для вызова процесса.
Если для изменения уровня привилегий используется вентиль
вызова, то новый стек
выбирается путем загрузки значения указателя из сегмента TSS. Процесс использует уровень DPL целевого
сегмента программы (который является новым уровнем CPL) для присвоения начальному указателю
стека уровня привилегий О, 1 или 2. Сегмент TSS не может иметь указателя стека
с уровнем привилегий 3 потому, что этот уровень не может быть вызван ни одной процедурой
с другим уровнем привилегий. Если уровень DPL нового сегмента стековых данных не
равен уровню CPL, то возникает обработка исключения по стеку.
Для облегчения предоставления привилегий МП 80386 копирует
параметры в новый стек. Он использует поле счетчика в вентиле вызова для
указания, сколько двойных
слов (максимум равен 31) нужно скопировать из стека вызывающей процедуры в новый стек. Если поле
счетчика равно нулю, то копирование параметров не производится. Процедуры, вызванные с другого
уровня привилегий и требующие
копирования более 31 двойного слова, должны использовать сохраняемую связь в виде указателя стека
SS:ESP для того, чтобы получить доступ ко всем параметрам за последним скопированным двойным
словом.
«Ближние» формы команды RET передают управление внутри
текущего сегмента
программы. Поэтому они являются предметом проверки только на превышение границы. Для этого из стека
выбирается относительный адрес команды, следующей за командой CALL, и процессор проверяет,
превышает или нет этот адрес границу текущего исполняемого сегмента.
«Дальняя» форма команды RET в свою очередь выбирает из стека
указатель возврата,
который был в него загружен предыдущей «дальней» командой CALL. Обычно этот указатель возврата
бывает достоверным благодаря его связи с предыдущей командой CALL или INT. Процессор, несмотря на это,
выполняет проверку привилегий
из-за того, что текущая процедура может неверно обслуживать стек или изменить его указатель. Уровень RPL
селектора сегмента программы, выбираемый из, стека по команде возврата, определяет уровень
привилегий вызываемой процедуры. Межсегментная команда возврата может изменить уровни привилегий, но только в направлении процедур с меньшими
привилегиями.
Ограничение набора команд. Определенные команды могут
повлиять на механизм
защиты и вмешаться в обычный порядок работы системы. Эти команды могут исполняться только процедурами
с достаточным уровнем доверия. Процессор имеет два класса команд ограниченного применения:
привилегированные команды и чувствительные команды. Более подробно эти команды описаны в предыдущем
разделе, касающемся привилегий.
Проверка достоверности указателя. Проверка достоверности сводится
к нахождению границ, в которых могут
находиться данные. Достоверность указателей является
важной частью выявления программных ошибок. Она необходима также для
поддержания изоляции между уровнями привилегий и состоит из следующих трех
шагов: 1) проверки соответствия типа сегмента его ожидаемому использованию, 2) проверки превышения указателем границы
сегмента, 3) проверки полномочий
задатчика указателя обращаться к данному сегменту.
Процессор автоматически выполняет первый и второй шаги
проверки во время исполнения
команды, но в выполнении третьего шага ему должны помочь программные средства. Это делает
непривилегированная команда ARPL настройки поля RPL селектора. Выполнить первый и
второй шаги проверки можно также и программными
средствами, а не ожидать обработки исключения. Сделать это помогают непривилегированные команды LAR загрузки
байта прав доступа, LSL загрузки границы сегмента, VERR
верификации сегмента для чтения, VERW верификации сегмента для
записи. Команда LAR верифицирует, что указатель ссылается на сегмент с
соответствующими уровнями привилегий и типов. Команда LSL позволяет программно проверить
границу дескриптора. Команды VERR и VERW определяют, указывает ли
селектор на сегмент, из которого можно считывать или в который можно записывать
на текущем уровне привилегий. Ни одна из этих команд не вызывает обработки исключения по защите в
случае отрицательного результата проверки.
Уровень привилегий инициатора запроса RPL может
иметь своей целью предотвращение ложного использования указателей, которые с
меньшего уровня привилегий
могут исказить данные или работу программы с большими привилегиями. Поле RPL
позволяет присвоить селектору атрибут привилегий, который обычно показывает уровень привилегий программы,
порождаемой этим селектором.
Процессор автоматически проверяет поле RPL любого селектора, загружаемого
в один из регистров сегмента, для верификации того, что уровень RPL
позволяет осуществить доступ к этому
сегменту.
Защита страниц и каталогов. Каждый вход в таблицу страниц
имеет два бита, связанных
с типом защиты: U/S и R/W. Бит присутствия может быть
использован для
ограничения адресуемой области. На уровне адресации страниц определены два типа доступа: доступ только по
чтению (R/W = 0) и доступ по чтению и по записи (R/W = 1).
Если
процессор работает на уровне супервизора (уровень CPL меньше 3), состояния
битов U/S и R/W игнорируются. Все страницы
разрешены как по чтению, так и по записи. На уровне пользователя (уровень CPL равен 3)
записывать можно только
те страницы, которые принадлежат 'уровню пользователя (U/S =1) и помечены как доступные по
записи (R/W = 1). Страницы, принадлежащие уровню супервизора, не доступны с уровня пользователя ни по
чтению, ни по записи. «Право собственности» на страницы устанавливается через ограничение
доступа к страницам.
Ограничение доступа к страницам реализовано присвоением
каждой странице одного из двух уровней.
Уровень пользователя (бит 2 входа в таблицу страниц, бит U/S =1). Этот уровень предназначен для
прикладных программ и данных.
Уровень супервизора (бит 2 входа в таблицу страниц, бит U/S = 0). Этот уровень предназначен для
операционной системы и других системных программ, а также связанных с ними данных.
Текущий уровень (пользователя или супервизора) относится
к уровню CPL. Если уровень CPL равен О, 1 или 2, процессор работает на уровне
супервизора. Если же уровень CPL равен 3,
процессор работает на уровне пользователя. На уровне супервизора все страницы
адресуемы, на уровне пользователя адресовать можно только страницы, принадлежащие
этому уровню.
Процессор вычисляет эффективные атрибуты защиты путем
проверки атрибутов
защиты как в каталоге страниц, так и в таблице страниц. Для любой страницы
атрибуты защиты при обращении к каталогу страниц могут отличаться от атрибутов при обращении к таблице
страниц.
Существуют возможности обойти защиту страниц. Определенные
доступы проверяются так, как будто они являются ссылками с уровнем привилегий
0, даже если
уровень CPL равен 3. К таким доступам относятся любые ссылки на таблицы LDT, GDT, IDT, TSS или же доступ к внутреннему стеку
в кольце чередующихся команд CALL и INT.
В режиме разбиения на страницы процессор сначала проверяет
защиту сегментов, а затем оценивает защиту страниц. Если МП 80386 обнаруживает
нарушение защиты
либо на уровне сегментов, либо на уровне страниц, он запрещает дальнейшее выполнение запрашиваемой
операции и вызывает обработку исключения по защите.