Процессор INTEL в защищенном режиме

Выпуск №13

 

Zаshitа


Вновь приветствую тебя, уважаемый читатель! И пусть никого не отпугнет номер выпуска (кстати, сегодня еще к тому же и пятница тринадцатое); сегодня мы продолжим интереснейшую тему – а именно тему защиты в защищенном режиме (простите за каламбур), которую предоставляет любой современный процессор из семейства Intel (вид x86). Несмотря на номер выпуска, ничего общего с мистикой данная тема не имеет, все до безобразия просто и прозаично. В качестве развлечения в сегодняшнем выпуске объявляется начало конкурса на отыскание ошибки... в самОм официальном мануале от Intel-а! (см. в конце)

Небольшое отступление. Помниться мне, что когда я только-только познакомился с ассемблером и где-то спустя год захотел освоить защищенный режим – ничего не получалось. Никак не шли все эти дескрипторы и уровни привилегий – нужно было постоянно держать в голове кучу информации + запоминать еще большую кучу новой, все перемешивалось и в итоге представлялось нагромождением бестолковых технических терминов и определений. На некоторое время я забросил все попытки, а потом и вовсе забыл про все это дело. Лишь спустя еще год я как-то от нечего делать заказал техническую документацию от Intel-а, полистал, почесал репу – вроде пошел процесс. Единственное объяснение которое я вижу – в течении года «застоя» были накоплены некоторые знания в других областях, причем даже близко не смежных с защищенным режимом (в частности – это могли быть какие то прочитанные книги, просмотренные фильмы – неважно, главное что все это не имело никакого отношения не то что к защ. режиму или ассемблеру, но даже к техническим наукам).

Все это к чему – знания, приобретенные в одной области самым непредсказуемым образом могут повлиять на процесс приобретения оных в других (возможно, абсолютно не относящихся к данной) областях. Что тоже важно - возможен и обратный эффект: чрезмерное увлечение, например, ассемблером может вызвать беспокойный сон :).


 

ПРОВЕРКА ТИПА СЕГМЕНТА


Это небольшой и простой раздельчик УК IA-32. Теперь самое время вернуться во 2-ой выпуск и посмотреть на картинку с дескриптором. Здесь нас интересуют два поля: бит S (бит 12 второго двойного слова) и поле «Тип» (биты 8-11 второго двойного слова). Если кто-то забыл про их назначение – прошу в выпуск №4.
Итак, процессор проверят эти два поля в следующих двух случаях:

1. При загрузке селектора в сегментный регистр
2. При обращении к сегменту


Чтобы не растекаться мыслью по древу сразу скажу:
#GP возникнет если:

- в регистр CS загрузить селектор на дескриптор, который описывает отличный от сегмента кода сегмент;
- в регистры DS,ES,FS или GS загрузить селектор на дескриптор, который описывает «НЕЧИТАЕМЫЙ» сегмент кода;
- в регистр SS загрузить селектор на дескриптор, описывающий отличный от «ЧИТАЕМЫЙ сегмент ДАННЫХ» сегмент;
- в регистр LDTR загрузить селектор, не указывающий на LDT;
- в регистр TR загрузить селектор, не указывающий на TSS;


- при записи в «ИСПОЛНЯЕМЫЙ» сегмент (т.е. писать в сегмент кода нельзя через CS, через DS - пожалуйста);
- при записи в сегмент данных, который «ТОЛЬКО ДЛЯ ЧТЕНИЯ»;
- при чтении из «НЕЧИТАБЕЛЬНОГО ИСПОЛНИМОГО» сегмента;

- дескрипторы в таблице IDT должны быть шлюзами прерывания, ловушки или задачи;


список можно продолжить, но идея уже должна быть ясна. Бит S и поле «Тип» в дескрипторе говорят процессору, чего с сегментом делать можно, а чего нельзя. Если кто-то попытается сделать то, чего делать нельзя, то обработчик #GP (который мы сами и пишем) должен по идее нарушителя наказать.

 

НУЛЕВОЙ СЕЛЕКТОР


Это чуть ли не самый маленький раздел УК – содержит всего два положения:

Если в CS или SS загрузить селектор, который указывает на нулевой дескриптор (т.е. 16-разрядное число, биты 15-3 которого равны 0), то #GP возникнет немедленно;

Кстати, почему именно биты 15-3 – см. 5-й выпуск, а именно на картинку селектора.

Если нулевой селектор загрузить в DS,ES,FS или GS то #GP возникнет при попытке обращения к данным через такой селектор (иначе – он там может хоть сто лет пролежать). Вообще нулевой селектор придуман в качестве подстраховки от ненужных обращений к сегментам.

 

УРОВНИ ПРИВИЛЕГИЙ


Ну, вот мы и добрались до святая-святых механизма защиты – уровней привилегий. Иногда (в частности – в ОС Windows) их называют кольца защиты (Protection Rings). Как уже было неоднократно сказано – всего уровней привилегий 4: 0 – самый крутой, 3 – самый несчастный и забитый. В одном из предыдущих выпусков я уже разводил ахинею насчет Госдумы и других крутых ребятах, которых можно разместить в 0 кольце. В мире ОС в нулевом кольце располагается код ядра ОС, драйвера, обработчики исключений (тот же #GP). Хотя по задумке инженеров Intel дрова и другие сервисные программы должны располагаться в 1 или 2 кольце. Однако ОС Windows (кстати, и *nix тоже) используют только два кольца: 0 и 3. В третьем – пользовательские приложения и служебные сервисы ОС, в нулевом – все остальное (хотя это грубое разделение, но примерно так все и выглядит).

Здесь, во избежание дальнейших недоразумений, следует раз навсегда договориться: если я пишу «уровень привилегий задачи A БОЛЬШЕ уровня привилегий задачи B», то это значит, что численное значение привилегий задачи А МЕНЬШЕ чем у B (хотя это и так очевидно, 0<3, 0 круче 3).

С номерами разобрались. Поехали дальше. Всего существует три типа уровней привилегий (и их нужно знать как «Отче наш»): это CPL (Current Privilege Level), RPL (Requested Privilege Level) и DPL (Descriptor Privilege Level). Название каждого говорит само за себя (кроме, пожалуй, RPL – в смысл этого друга нужно еще попытаться въехать). Начнем по-порядку. Итак, CPL.

CPL – это текущий уровень привилегий, иначе говоря – уровень привилегий кода (задачи) исполняющейся в данный момент. Очень важно – именно в данный момент! Где же он храниться? Внимательный читатель сразу вспомнит формат селектора... Да. Именно в битах 1-0 он и храниться. Т.е. под CPL отведено 2 бита – всего могут принять 4 значения (0 – самый крутой, 3 – лоховской). Пока все сходиться. Теперь ВНИМАНИЕ! Где находиться сам селектор, хранящий CPL? В CS !!! В CS и нигде больше!!! (правда, он еще храниться и в SS, но пока, пожалуйста, представьте, что он только в CS). Т.е. если в данный момент исполняется код обработчика #GP (и он в раздумьях что сделать с нашалившей программой) то CPL кода (этого самого обработчика #GP) = 0 (хотя и необязательно – все зависит от фантазии разработчика ОС, но логично предположить, что CPL обработчика #GP равен 0). Пока про CPL информации хватит.

DPL – уровень привилегий СЕГМЕНТА. Храниться в дескрипторе каждого сегмента в таблице дескрипторов. Вообще вот посмотришь на предыдущий тип уровня привилегий – CPL. CPL – уровень привилегий кода, исполняющегося в данный момент. Но ведь код тоже находиться в каком-то сегменте! Так чем же они отличаются? Фразой «в данный момент». Вот их главное отличие. Ну и помимо того CPL относится ТОЛЬКО К СЕГМЕНТАМ КОДА (исполняющимся в данный момент :), а DPL содержится в КАЖДОМ ДЕСКРИПТОРЕ, неважно что описывает этот дескриптор (кстати, открываем второй выпуск и смотрим на картинку с дескриптором). Как ни странно, под него также отведено 2 бита. Процессор бросает свой гордый взор на поле DPL только при обращении к сегменту. Например, исполняется какая-то пользовательская программа. Все тихо и спокойно. Вдруг процессор встречает инструкцию:

mov dword ptr DS:[00000000h],0 ; программа хочет записать ноль по адресу DS:00000000h

(а DS равно все равно чему, например, 1234h)

Тут процессор естественно занервничает: а можно ли этой подозрительной программе с CPL=3 записывать данные туда, куда она намеревается это сделать? Тут же из селектора 1234h извлекается индекс (старшие 13 (!) бит - 246h) и в таблице дескрипторов (в данном случае – текущей LDT) находится нужный дескриптор, в котором процессор ищет в первую очередь поле DPL. И тут он видит, что в поле DPL содержится ноль! Т.е. уровень привилегий сегмента, в который хочет писать программа явно выше чем тот, который у подозрительной программы. Тут же генерируется #GP, обработчик которого приговаривает нарушителя к «...наказанию через расстреляние». У некоторых может возникнуть бестолковый вопрос: а если программа «успеет» записать нолик до тех пор, пока процессор соображает что к чему и возиться с привилегиями? Ответ: не успеет. #GP- это исключение типа ошибки (fault), оно ВСЕГДА генерируется ДО исполнения инструкции-нарушителя (об этом мы поговорим в выпуске про исключения).

И тут опять всплывает тот самый пресловутый «внимательный читатель рассылки», который в данной модели заприметит одно упущение: селектор храниться в КАЖДОМ сегментном регистре (будь то CS, SS, DS, FS…). С CS и SS вроде разобрались, а что же тогда хранят DS, FS, ES и GS ? Ведь даже в вышеприведенном примере использовался DS – так неужели же только для того чтобы посмотреть на DPL и найти нужный сегмент? Что хранят младшие два бита этого селектора??!!

RPL – уровень привилегий запроса. Мда. Здесь, чтобы понять для чего вообще нужен этот RPL, нужно немного поднапрячься. В принципе, возможно было построить процессор с архитектурой, использующей только два типа привилегий (CPL и DPL). Это доказывает хотя бы тот факт, что RPL в любом сегм. регистре любая пользовательская программа может изменить себе сама. Зачем Intel-овцы подмахнули RPL – скорее всего «для гибкости». В чем эта гибкость заключается – тема следующего выпуска.

На словах смысл CPL, DPL и RPL практически не улавливается (это нормально). Для понимания их сути идеально подходят зрительные образы. Следующий выпуск будет пестреть картинками, по которым даже школьник сможет понять смысл и суть этих наиважнейший понятий. Кроме того, в следующем выпуске мы найдем еще одну ошибку в книге Зубкова С.В. (а также опечатку в официальном мануале от Intel-а, из-за которой (возможно) и возникла ошибка у Зубкова). А посему пока объявляется обещанный конкурс на нахождение опечатки в официальном мануале Intel-а (подсказка: третий том (System Programming Guide), главы 4.8.1.1 и 4.8.1.2 (они небольшие, имена победителей будут объявлены в следующем выпуске).

И еще - я обзавелся сайтом (ну, это, конечно, громко сказано – сайт из серии «за 5 минут», пока что являет собой ссылки на все выпуски рассылки (наконец-то с картинками!) и некоторые мои поделки. Заходите, смотрите, может че полезного для себя и углядите: brokensword.narod.ru




© Broken Sword, 2003 - Рассылка

© Igoryk, 2003 - Дизайн


Hosted by uCoz