на основе процессоров с архитектурой IA32.




Процессор Pentium при работе в сегментном режиме предоставляет операционной системе следующие средства, направленные на обеспечение защиты процессов друг от друга.

Процессор Pentium поддерживает для каждого процесса отдельную таблицу дескрипторов сегментов LDT. Эта таблица формируется операционной системой на этапе создания процесса. После активизации процесса в регистр LDTR заносится адрес (селектор) его таблицы LDT. Тем самым система делает недоступным для процесса локальные сегменты других процессов, описанные в их таблицах LDT.

Вместе с тем таблица GDT, в которой хранятся дескрипторы сегментов операционной системы, а также сегменты, используемые несколькими процессами совместно, доступна всем процессам, а следовательно, не защищена от их несанкционированного вмешательства. Для решения этой проблемы в процессоре Pentium предусмотрена поддержка системы безопасности на основе привилегий. Каждый сегмент памяти наделяется атрибутами безопасности, которые характеризуют степень защищенности данного сегмента. Процессы также наделяются атрибутами безопасности, которые в этом случае характеризуют степень привилегированности процесса. Уровень привилегий процесса определяется уровнем привилегий его кодового сегмента. Доступ к сегменту регулируется в зависимости от его защищенности и уровня привилегированности запроса. Это позволяет защитить от несанкционированного доступа сегменты GDT, а также обеспечить дифференцированный доступ к локальным сегментам процесса.

Само по себе наличие отдельных таблиц дескрипторов для каждого процесса еще не обеспечивает надежной защиты процессов друг от друга. Действительно, что мешает одному пользовательскому процессу изменить содержимое регистра LDTR так, чтобы он указывал на таблицу другого процесса? Аналогично никакие значения атрибутов безопасности не смогут защитить от несанкционированного доступа сегменты, описанные в таблице GDT, если процесс имеет возможность по своей инициативе устанавливать желаемый уровень привилегий для себя. Поэтому необходимым элементом защиты является наличие аппаратных ограничений в наборе инструкций, разрешенных для выполнения процессу. Некоторые инструкции, имеющие критически важное значение для функционирования системы, такие, например, как останов процессора, загрузка регистра GDTR, загрузка регистра LDTR, являются привилегированными как раз по этой причине — процесс может выполнять их, только обладая наивысшим уровнем привилегий.

Еще одним механизмом защиты, поддерживаемым в процессоре Pentium, является ограничение на способ использования сегмента. В зависимости от того, к какому типу относится сегмент — сегмент данных, кодовый сегмент или системный сегмент, — некоторые действия по отношению к нему могут быть запрещены. Например, в кодовый сегмент нельзя записывать какие-либо данные, а сегменту данных нельзя передать управление, даже если загрузить его селектор в регистр CS.

В процессоре Pentium используется мандатный способ определения прав доступа к сегментам памяти (называемый также механизмом колец защиты), при котором имеется несколько уровней привилегий и объекты каждого уровня имеют доступ ко всем объектам равного уровня или более низких уровней, но не имеют доступа к объектам более высоких уровней. В процессоре Pentium существует четыре уровня привилегий — от нулевого, который является самым высоким, до третьего — самого низкого (рис. 6.7). Очевидно, что операционная система может использовать механизм колец защиты по своему усмотрению. Однако предполагается, что нулевой уровень доступен для ядра операционной системы, третий уровень — для прикладных программ, а промежуточные уровни — для утилит и подсистем операционной системы, менее привилегированных, чем ядро.

Рис. 6.7. Кольца защиты

Система защиты манипулирует несколькими переменными, характеризующими уровень привилегий:

· DPL (Descriptor Privilege Level) — уровень привилегий дескриптора, задается полем DPL в дескрипторе сегмента;

· RPL (Requested Privilege Level) — запрашиваемый уровень привилегий, задается полем RPL селектора сегмента;

· CPL (Current Privilege Level) — текущий уровень привилегий выполняемого кода, задается полем RPL селектора кодового сегмента;

· EPL (Effective Privilege Level) — эффективный уровень привилегий запроса.

Под запросом здесь понимается любое обращение к памяти независимо от того, произошло ли оно при выполнении кода, оформленного в виде процесса, или вне рамок процесса, как это бывает при выполнении кодов операционной системы.

Поле уровня привилегий является частью двух информационных структур — дескриптора и селектора. В том и другом случае оно задается двумя битами: 00, 01, 10 и 11, характеризуя четыре степени привилегированности, от самой низкой 11 до самой высокой 00.

Уровни привилегий назначаются дескрипторам и селекторам. Во время загрузки операционной системы в память, а также при создании новых процессов операционная система назначает процессу сегменты кода и данных, генерирует дескрипторы этих сегментов и помещает их в таблицы GDT или LDT. Конкретные значения уровней привилегий DPL и RPL задаются операционной системой и транслятором либо по умолчанию, либо на основании указаний программиста. Значения DPL и RPL определяют возможности создаваемого процесса.

Уровень привилегий дескриптора DPL является в некотором смысле первичной характеристикой, которая «переносится» на соответствующие сегменты и запросы. Сегмент обладает тем уровнем привилегий, который записан в поле DPL его дескриптора. DPL определяет степень защищенности сегмента. Уровень привилегий сегмента данных учитывается системой защиты, когда она принимает решения о возможности выполнения для этого сегмента чтения или записи. Уровень привилегий кодового сегмента используется системой защиты при проверке возможности чтения или выполнения кода для данного сегмента.

Уровень привилегий кодового сегмента определяет не только степень защищенности этого сегмента, но и текущий уровень привилегий CPL всех запросов к памяти (на чтение, запись или выполнение), которые возникнут при выполнении этого кодового сегмента. Другими словами, уровень привилегий кодового сегмента DPL характеризует текущий уровень привилегий GPL выполняемого кода. При запуске кода на выполнение значение DPL из дескриптора копируется в поле RPL селектора кодового сегмента, загружаемого в регистр сегмента команд CS. Значение поля RPL кодового сегмента, собственно, и является текущим уровнем привилегий выполняемого кода, то есть уровнем CPL.

От того, какой уровень привилегий имеет выполняемый код, зависят не только возможности его доступа к сегментам и дескрипторам, но и разрешенный ему набор инструкций.

Во время приостановки процесса его текущий уровень привилегий сохраняется в контексте, роль которого в процессоре Pentium играет системный сегмент состояния задачи (Task State Segment, TSS). Если какой-либо процесс имеет несколько кодовых сегментов с разными уровнями привилегий, то поле RPL регистра CS позволяет узнать значение текущего уровня привилегий процесса. Заметим, что пользовательский процесс не может изменить значение поля привилегий в дескрипторе, так как необходимые для этого инструкции ему недоступны. В дальнейшем уровень привилегий процесса может измениться только в случае передачи управления другому кодовому сегменту путем использования особого дескриптора — шлюза.

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

EPL=max{CPL.RPL}

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

max{CPL.RPL) <= DPL

Уровень привилегий дескриптора DPL определяет степень защищенности сегмента. Значение DPL говорит о том, каким эффективным уровнем привилегий должен обладать запрос, чтобы получить доступ к данному сегменту. Например, если дескриптор имеет DPL=2, то к нему разрешено обращаться всем процессам, имеющим уровень привилегий EPL, равный О, 1 или 2, а для процессов с EPL, равным 3, доступ запрещен.

Правило вычисления эффективного уровня привилегий показывает, что он не может быть выше уровня привилегий кодового сегмента. Поэтому загрузка в регистр DS (или любой другой сегментный регистр данных) селектора с высоким уровнем привилегий (например, с RPL = 0) при низком значении уровня CPL (например, 3) ничего нового не даст — если сегмент данных, на который указывает DS, имеет высокий уровень привилегий (например, 1), то в доступе к нему будет отказано (так как EPL будет равен max {3,0}, то есть 3). По этой причине команды загрузки сегментных регистров не являются привилегированными.

Если запрос обращен к сегменту данных, обладающему более высоким, чем EPL, уровнем привилегий, то происходит прерывание.

Задавая в поле RPL селекторов, ссылающихся на сегменты данных, различные значения, программист может управлять доступом выполняемого кода к этим сегментам. Так, при RPL=0 эффективный уровень привилегий будет всецело определяться только текущим уровнем привилегий CPL. А если поместить в селектор RPL=3, то это означает снижение эффективного уровня привилегий до самого низкого значения, при котором процессу разрешен доступ только к наименее защищенным сегментам с DPL=3.

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

Контроль доступа процесса к кодовому сегменту производится путем сопоставления уровня привилегий дескриптора этого кодового сегмента DPL с текущим уровнем привилегий выполняемого кода CPL. В зависимости от того, какой способ обращения к кодовому сегменту используется, выполняется внутрисегментная или межсегментная передача управления, вызывается подчиненный или неподчиненный сегмент — по-разному формулируются правила контроля доступа. Эти вопросы будут рассмотрены в разделе «Средства вызова процедур и задач».

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

Способ, с помощью которого разрешено осуществлять доступ к сегменту того или иного типа, определяется несколькими битами байта доступа дескриптора сегмента. Как уже было сказано, старший, седьмой бит байта доступа является признаком Р присутствия сегмента в памяти, а шестой и пятый биты отведены для хранения уровня привилегий DPL. На рис. 6.8 показаны оставшиеся пять битов байта доступа, смысл которых зависит от типа сегмента.

Рис. 6.8. Признаки, задающие тип сегмента и права доступа

Поле S занимает 1 бит и определяет, является ли сегмент системным (5=0) или сегментом кода или данных (S=l).

Системные сегменты предназначены для хранения служебной информации операционной системы. Примерами системных сегментов являются сегменты, хранящие таблицы LDT, или рассматриваемые ниже сегменты состояния задачи TSS. Конкретный тип системного сегмента указывается в четырех младших битах байта доступа, например, если это поле содержит значение 2, это означает, что данный дескриптор описывает сегмент LDT.

Признак Е позволяет отличить сегмент данных (Е=0) от сегмента кода (Е=1). Для сегмента данных определяются следующие поля:

· ED (Expand Down) — направления распространения сегмента (ED=0 для обычного сегмента данных, распространяющегося в сторону увеличения адресов, Е0=1 для стекового сегмента данных, распространяющегося в сторону уменьшения адресов);

· W (Writeable) — бит разрешения записи в сегмент (при W=l запись разрешена, при W=0 — запрещена);

· A (Accessed) — признак обращения к сегменту (1 означает, что после очистки этого поля к сегменту было обращение по чтению или записи, это поле может использоваться операционной системой для реализации ее стратегии замены сегментов в оперативной памяти).

·

Если признак W запрещает запись в сегмент данных, то разрешается только чтение сегмента. Выполнение сегмента данных запрещено всегда, независимо от значения признака W.

Для сегмента кода используются следующие признаки:

· С (Conforming) — бит подчинения, определяет возможность вызова кода на выполнение из других сегментов; при С=1 (подчиненный сегмент) сегмент может выполняться в том случае, если текущий уровень привилегий вызывающего процесса CPL не выше уровня привилегий DPL данного кодового сегмента, то есть в арифметическом смысле CPL > DPL; после передачи управления новый кодовый сегмент начинает выполняться с уровнем привилегий вызвавшего сегмента, то есть с более низкими или теми же привилегиями; при С=0 (неподчиненный сегмент) код может быть выполнен только при CPL=DPL;

· R (Readable) — бит разрешения (R=l) или запрета (R=0) чтения из кодового сегмента;

· A (Accessed) — признак обращения, имеет смысл, аналогичный полю А сегмента данных.

Если признак R запрещает чтение кодового сегмента, то разрешается только его выполнение. Запись в кодовый сегмент запрещена всегда, независимо от значения признака R.

Выполнение многих операций в процессоре Pentium сопровождается проверкой их допустимости для данного типа сегмента. Первый этап проверки выполняется при загрузке селекторов в сегментные регистры. Так, диагностируется ошибка, если в сегментный регистр CS загружается селектор, ссылающийся на дескриптор сегмента данных, и наоборот, если в регистр сегмента данных DS загружается селектор, указывающий на дескриптор кодового сегмента. Ошибка возникает также, если в регистр стекового сегмента загружается селектор, ссылающийся на дескриптор сегмента данных, который допускает только чтение.

Вторым этапом является проверка ссылок операндов во время выполнения команд записи или чтения. Прерывания происходят в следующих случаях:

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

· делается попытка записать данные по адресу, принадлежащему кодовому сегменту;

· делается попытка записать данные в сегмент данных, который допускает только чтение.

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

 


18. Смешанная сегментно-страничная организация памяти



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: