3. Защита памяти

3.1 Защита по уровню привилегий.

3.2 Защита по функциональному назначению.

 

3.1 Защита по уровню привилегий.

 

В защищенном режиме процессор имеет четырехуровневую систему привиле­гий, которая управляет использованием привилегированных инструкций и до­ступом к сегментам памяти. Уровень привилегии сегмента указывается в его дескрипторе. Нумерация уровней происходит от 0 до 3, высшие привилегии соответствуют нулевому уровню. Для наглядности их принято изображать в виде колец.

 

 

Уровни привилегий обеспечивают защиту целостности операционной системы от «недружелюбных» программ. А также защиту адресных пространств одновременно выполняемых задач. Сервисы операционной системы, обра­ботчики прерываний и другое системное обеспечение могут включаться в вир­туальное адресное пространство каждой задачи и защищаться системой приви­легий. Как правило, назначение уровней следующее. Нулевой уровень – уровень операционной системы (ядро операционной системы). Уровни 1 и 2 – программы системного назначения. Уровень 3 – прочие прикладные программы (уровень прикладных программ). Дескрипторы (сегменты) и селекторы имеют свои атрибуты привилегий.

 

Привилегии задач оказывают влияние на выполнение инст­рукций и использование дескрипторов. Текущий уровень привилегии задачи CPL (Current Privilege Level) определяется двумя младшими битами регист­ра CS.

CPL задачи может изменяться только при передаче управления к новому сегменту через дескриптор шлюза (см. главу 5). Задача начинает выполняться с уровня CPL, указанного селектором кодового сегмента внутри TSS, когда задача иницииру­ется посредством операции переключения задач. Задача, выполняемая на нуле­вом уровне привилегий, имеет доступ ко всем сегментам, описанным в GDT, и является самой привилегированной. Задача, выполняемая на уровне 3, имеет самые ограниченные права доступа. Текущий уровень привилегии задачи может изме­няться только при передаче управления через шлюзы.

Привилегии сегмента задаются полем DPL байта управления доступом.

DPL определяет наибольший номер уровня привилегий (фактически, наименьшие привилегии), с которым возможен доступ к данному дескриптору. Самый защищенный (привилегированный) дескриптор имеет DPL=0, к нему имеют до­ступ только задачи с CPL=0. Самый общедоступный  дескриптор имеет DPL=3, его могут использовать задачи с CPL=0, 1, 2, 3. Это правило применимо ко всем дескрипторам, за исключением дескриптора LDT.

Привилегии селектора задаются полем RPL (Requested Privilege Level) — двумя младшими битами селектора.

 При обращении в сегмент данных с помощью RPL можно ограничить привилегии (относительно CPL), вводится понятие эффективный уровень привилегий EPL (Effective Privilege Level), ко­торый определяется как максимальное из значений CPL и RPL, Селектор с RPL=0 не вводит дополнительных ограничений.

 

EPL = MAX ( CPL, RPL )

 

Контроль доступа к сегментам данных производится при исполнении команд, загружающих селекторы в SS, DS, ES, FS и GS. Команды загрузки DS, ES, FS и GS должны ссылаться на дескрипторы сегментов данных или сегментов кодов, допус­кающих чтение. Для получения доступа эффективный уровень привилегий EPL должен быть равным или меньшим (арифметически) уровня привилегий DPL де­скриптора.

 

EPL £ DPL

 

Исключением из этого правила является читаемый подчиненный сег­мент кода, который может быть прочитан задачей с любым CPL. Если эффектив­ный уровень привилегий не разрешает доступ или ссылка производится на некорректный тип дескриптора (на дескриптор шлюза или на дескриптор только исполняемого кодового сегмента), вырабатывается исключение #GP. При ссылке на несуществующий дескриптор вырабатывается исключение #NP.

Команды загрузки SS должны ссылаться на дескриптор сегмента данных, до­пускающий запись. При этом DPL и RPL должны быть равны CPL. Нарушение этого условия и ссылка на дескриптор другого типа порождают исключение #GP, при ссылке на несуществующий дескриптор вырабатывается исключение #SS.

Контроль типов и привилегий при передаче управления производится при загрузке селектора в регистр CS. Тип дескриптора, на который ссылается дан­ный селектор, должен соответствовать выполняемой инструкции. Нарушение типа (например, ссылка инструкции JMP на шлюз вызова) порождает исклю­чение #GP. При передаче управления действуют следующие правила привиле­гий, нарушение которых также приводит к исключению #GP:

 

· Команды JMP или CALL могут ссылаться либо на подчиненный сегмент кода с DPL, большим или равным CPL, либо на неподчиненный сегмент с DPL равным CPL;

· Прерывания внутри задачи или вызовы, которые могут изменить уровень привилегий, могут передавать управление кодовому сегменту с уровнем привилегий, равным или большим уровня привилегий CPL, только через шлюзы с тем же или меньшим уровнем привилегий, чем CPL;

· Инструкции возврата, которые не переключают задачи, могут передать управление только кодовому сегменту с таким же или меньшим уровнем привилегий;

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

 

Смена уровня привилегий, происходящая при передаче управления, автома­тически вызывает переопределение стека. Начальное значение указателя стека SS:SP  для уровня привилегий 0, 1, 2 содержится в TSS. При передаче управле­ния по командам JMP или CALL в CS:SP загружается новое значение указателя стека, а старые значения помещаются в новый стек. При возврате на прежний уро­вень привилегий его стек восстанавливается (как часть инструкции RЕТ или IRЕТ). Для вызовов подпрограмм с передачей параметров через стек и сменой уровня при­вилегий из предыдущего стека в новый копируется фиксированное число слов, заданное в шлюзе. Команда межсегментного возврата RET с выравниванием ука­зателя стека при возврате корректно восстановит значение предыдущего указателя.

Привилегии и битовая карта разрешения ввода/вывода контролируют воз­можность выполнения операций ввода/вывода и управления флагом пре­рываний IF. Уровень привилегий ввода/вывода определяется полем IOPL (Input/Output Privilege Level) регистра флагов. Значение IOPL можно изме­нить только при CPL=0 (только для операционной системы).

При CPL £ IOPL на операции ввода/вывода и управление флагом IF никаких ограничений не накладывается. При CPL > IOPL попытка ввода/вывода, выпол­ненная задачей с TSS класса 80286, вызывает исключение #GP (отказ). Если CPL > IOPL, а с задачей связан TSS 386+, инструкции ввода/вывода могут вы­полняться только по адресам портов, для которых установлены нулевые биты в карте разрешения ввода/вывода, имеющейся в TSS (см. главу 5). Попытки обращения к портам, которым соответствуют единичные биты карты или которые не попали в карту (ее размер может усекаться), вызывают исключение #GP.

При CPL > IOPL попытка выполнения инструкций CLI и STI вызывает исклю­чение #GP. Неявное управление флагом прерываний инструкциями загрузки или восстановления регистра флагов блокируется без генерации исключений. Вопросы виртуализации прерываний будут рассмотрены ниже.

 

3.2 Защита по функциональному назначению.

 

Для надежной работы многозадачных систем необходима защита задач друг от друга. Защита предназначена для предотвращения несанкционированного до­ступа к памяти и выполнения критических инструкций — команды HLT, которая останавливает процессор, команд ввода/вывода, управления флагом разреше­ния прерываний и команд, влияющих на сегменты кода и данных. Механизмы защиты вводят следующие ограничения:

 

· Ограничение использования сегментов (например, запрет записи в только читаемые сегменты данных или попытки исполнения данных как кода). Для использования доступны только сегменты, дескрипторы которых описаны в GDT и LDT;

· Ограничение доступа к сегментам через правила привилегий;

· Ограничение набора инструкций — выделение привилегированных инст­рукций или операций, которые можно выполнять только при определен­ных уровнях CPL и IOPL;

· Ограничение возможности межсегментных вызовов и передачи управле­ния.

 

В защищенном режиме при исполнении инструкций процессор выполняет проверки условий, порождающих исключения:

 

Проверка при загрузке сегментных регистров

 

· Превышение лимита таблицы дескрипторов — #GP;

· Несуществующий дескриптор сегмента — #NP или #SS;

· Нарушение привилегий — #GP;

· Загрузка неверного дескриптора или типа сегмента — #GP:

§ загрузка в SS сегмента кода или сегмента данных только для чтения;

§ загрузка управляющих дескрипторов в DS, ES или SS;

§ загрузка только исполняемых сегментов в DS, ES или SS;

§ загрузка сегмента данных в CS.

 

Проверка ссылок операндов

 

·  Запись в сегмент кода или сегмент данных только для чтения -#GP.

·  Чтение из только исполняемого сегмента кодов - #GP.

·  Превышение лимита сегмента — #SS или #GP.

 

Проверка привилегий инструкций

 

· CPL <> 0 при выполнении инструкций LIDT, LLDT, LGDT, LTR, LMSW, CTS, HLT, INVD, INVLPG, WBINVD, операции с регистрами DRn, TRn, CRn - #GP;

· CPL > IOPL при выполнении инструкций STI, CLI, а для 80286 еще и ин­струкции LOCK — #GP;

· CPL > IOPL при выполнении инструкций IN, INS, OUT, OUTS с портами, неразрешенными битовой картой ввода/вывода — #GP.

 

При выполнении команд IRET и POPF с недостаточным уровнем привилегий биты IF и IOPL в регистре флагов не изменяются, исключения не порождаются:

 

· IF не меняется, при CPL > IOPL;

· IOPL не меняется, если CPL > 0.

 

Проверки при передаче управления по инструкциям JMP, CALL, RET, INT и IRET включают как проверку ссылок по размеру (в «ближних» формах JMP, CALL и RET выполняются только эти проверки), так и проверку правил приви­легий при межсегментных передачах через шлюзы.

Для того чтобы задачи не «нарывались» на срабатывание защиты, в систему команд введены специальные инструкции тестирования указателей. Они поз­воляют быстро удостовериться в возможности использования селектора или сег­мента без риска порождения исключения:

 

· ARPL выравнивание RPL. При ее исполнении RPL селектора приравни­вается максимальному значению из текущего RPL селектора и поля RPL в указанном регистре. Если при этом RPL изменился, устанавливается ZF=1;

· VERR проверка возможности чтения: если сегмент, на который указы­вает селектор, допускает чтение, устанавливается ZF=1;

· VERW проверка возможности записи: если сегмент, на который указы­вает селектор, допускает запись, устанавливается ZF=1;

· LSL чтение лимита сегмента в регистр, если позволяют привилегии. При успехе устанавливается ZF=1;

· LAR чтение байта доступа дескриптора в регистр, если позволяют при­вилегии. При успехе устанавливается ZF=1.

 

Некоторые функции защиты выполняются и механизмом страничной пере­адресации, однако, в отличие от «непробиваемой» сегментной защиты, сущест­вуют способы обхода страничной защиты на уровне пользователя (CPL=3).