Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
БІКС 2015_1 / Лек 6 Захист інформації на рівні операційної системи.doc
Скачиваний:
76
Добавлен:
12.02.2016
Размер:
3.66 Mб
Скачать

5. Керування оперативною пам'яттю

Як уже зазначалося, архітектура процесорів х8б передбачає сегментну і сегмент-но-сторінкову моделі розподілу пам'яті. Засоби сегментної організації формують верхній рівень керування пам'яттю, а сторінкової — нижній (який можна вмикати та вимикати за допомогою прапорця pg в регістрі сгО) [63, 92].

5.1. Сегментний розподіл пам'яті

У сегментній моделі нам яті кожний сегмент утворює свій окремий адресний простір (див. рис. 10.1). Кількість сегментів визначається максимальною кількі­стю дескрипторів, яку може обробити процесор. Як уже зазначалося, кожний процес використовує одночасно дві таблиці — LDT і GDT; максимальна кількість дескрипторів у кожній із них визначається розрядністю індексу з селектора — 13 розрядів. Тобто в кожній таблиці може міститися до 213 дескрипторів, загалом — 16k (16 384) сегментів. З цього випливає, що в такому режимі кожний процес мо­же мати 16k х 4 Гбайт ~ 64 Тбайт віртуального адресного простору.

Розглянемо механізм трансляції адреси, коли процесор працюєв такому ре­жимі (рис. 10.10,10.11).

Цей механізм ініціюється за спроби звернутися до будь-яких даних у пам'яті (наприклад, коли дані завантажуються в регістр процесора чи записуються з регі­стра в пам'ять, та під час роботи зі стеком) або до нового сегмента (завантаження селектора в сегментний регістр). Принципово цей механізм відповідає схемі, наве­деній на рис. 10.3. Насправді ж перша частина алгоритму виконується лише під час завантаження селектора в сегментний регістр. Якщо здійснюється доступ до даних всередині сегмента, пошук дескриптора сегмента не виконується, позаяк процесор має спеціальні 64-розрядні регістри для зберігання дескрипторів, що відповідають завантаженим у сегментні регістри селекторам. Ці дескрипторні регістри є тіньови­ми, програмно недоступними. Дескриптор завантажується разом із селектором.

Завантаження селектора в сегментний регістр

Розглянемо процедуру завантаження селектора в сегментний регістр. Спочатку про­цесор має знайти у пам'яті відповідний дескриптор і здійснити необхідні перевірки.

Якщо у селекторі прапорець ТІ « 0, то дескриптор міститься в глобальній таблиці дескрипторів GDT. Базова адреса і межа (тобто розмір) таблиці GDT ви­значаються з регістра gdtr. Для вибору потрібного дескриптора використовується індекс, що міститься в селекторі. Індекс — це фактично номер дескриптора в таблиці. Оскільки адресація здійснюється побайтово, індекс необхідно помножи­ти на 8 (розмір дескриптора в байтах), що досягається зміщенням уліво на три розряди. Насправді ж, через те що індекс у селекторі займає 13 старших розрядів, він вже фактично зсунутий на три розряди вліво, тому достатньо обнулити три молодших розряди селектора і додати останній до базової адреси таблиці. Далі здійснюється перша операція, що стосується захисту сегментів пам'яті, — переві­ряється, чи не виходить дескриптор за встановлену межу таблиці GDT. Якщо ні — відбувається звернення до дескриптора. У разі виходу за межу генерується внутрішнє переривання процесу — виняткова ситуація 11.

Якщо ж у селекторі прапорець ТІ = 1, дескриптор міститься в таблиці LDT. Тоді спочатку визначається поточна таблиця LDT, для чого як селектор викори­стовують уміст регістра Idtr. Після виконання операції, аналогічної описаній вище, з таблиці GDT вибирається дескриптор, що описує таблицю LDT (нагадаємо, що таблиця дескрипторів - це спеціальний вид сегмента). При цьому перевіряється, чи відповідає тип дескриптора таблиці дескрипторів (див. табл. 10.4) та чи є таб­лиця в пам'яті (біт Р байта AR дескриптора дорівнює 1). З дескриптора таблиці LDT визначаються базова адреса таблиці та її межа. Потім із цієї таблиці оби­рається потрібний дескриптор, так само, як із таблиці GDT і з тими самими перевірками. (На рис, 10.10 і 10.11 операції перевірки виходу поза межі таблиць і сегментів не показано.)

В обох випадках було розглянуто процедуру до моменту звернення до деск­риптора сегмента, селектор якого ми завантажуємо в регістр.

Далі здійснюється перевірка сумісності типів селектора і дескриптора. Дес­криптор має описувати сегмент у пам'яті (бітS = 1). Якщо селектор завантажу­ється в регістр, що вказує на сегмент даних, то несумісним буде дескриптор, що описує сегмент коду із захистом від читання (біт Е w 1, біт R == 0). Якщо селек­тор завантажується в регістр cs, то сумісним буде лише сегмент коду, і ана­логічно під час завантаження селектора в регістр ss сумісним буде лише сегмент стека (табл. 10.6). Очевидно, більш суворі умови сумісності для сегментів стека і коду спрямовані на запобігання «підсовування» процесору зловмисного коду через сегменти даних, У випадку коли перевірка дає негативний результат, фік­сується несумісність типів — генерується виняткова ситуація 13 (загальна по­милка захисту).

Потім перевіряються привілеї доступу до сегмента. Для цього порівнюються значення RPL (рівень привілеїв селектора, який ми завантажуємо в сегментний регістр процесора), DPL (рівень привілеїв дескриптора, на який посилається се­лектор, що ми його завантажуємо) і CPL (поточний рівень привілеїв, тобто рі­вень привілеїв процесу, що виконується), який дорівнює RPL селектора, що зна­ходиться в регістрі cs). Для сегмента стека (за спроби завантажиш селектор у регістр ss) має виконуватися рівність DPL ш RPL = CPL. Для решти сегментів рі­вень DPL має бути не вищим за рівні RPL і CPL, тобто DPL > RPL і DPL > CPL (на­гадаємо, що найвищому рівню привілеїв відповідає значення 0, а найнижчому — 3). Якщо потрібне співвідношення не виконується, фіксується недостатній рівень привілеїв — виняткова ситуація 13 (загальна помилка захисту).

Розглянемо приклад [91]. Зауважимо, що, описуючи послідовність перевірок, ми припускалися, що у разі фіксації помилки виконання алгоритму припиняєть­ся і викликається оброблювач відповідного переривання.

Приклад 1. Завантаження селектора в сегментний регістр

Виконується команда

mov ds, ах

Регістр ах містить значення 0x37 * 0000000000110111. Процес виконується в нульовому кільці захисту, тобто CPL = 0.

  1. Аналізується біт ТІ селектора. ТІ - 1 (тобто дескриптор знаходиться в LDT).

  2. Обчислюється фізична адреса дескриптора dt локальної таблиці дескрипторів LDT, що відповідає поточному процесу (дескриптор dt знаходиться в таблиці GDT).

  3. З дескриптора dt добувається межа LDT ldtjimit.

  4. Якщо в dt G=l, то ldt_limit Ьш 4096 (межа у 4-кілобітових сторінках).

  5. Із селектора добувається індекс дескриптора: index = 6

  6. Перевіряється, чи не виходить індекс за межі таблиці LDT: (index +1) * 8 - 1 = 55

Якщо Idt limit < 55, фіксується некоректність селектора (помилка 11).

7. З таблиці LDT добувається дескриптор d сегмента:

offset = index * 8 = 48; d_addr = Idt_base + offset

  1. Якщо в d біт S = 0 або одночасно E * 1 і R e 0, фіксується несумісність типів се­лектора і регістра (помилка 13).

  2. Із селектора добувається RPL:

RPL f З