Защита.

Глава 4. Шлюз вызова.

        Для обеспечения контролируемого доступа к сегменту кода на другом уровне привилегий, процессор предоставляет 4 специальных типа дескрипторов, так называемых шлюзов:
  • Шлюз вызова (Call gate)
  • Шлюз ловушки (Trap gate)
  • Шлюз прерывания (Interrupt gate)
  • Шлюз задачи (Task gate)

            Шлюзы ловушки и прерывания используются в дескрипторной таблице прерываний (IDT) и описаны в разделе "Прерывания в защищённом режиме". Шлюз задачи используется для передачи управления задаче и подробно описан в разделе "Мультизадачность". Здесь же описан только шлюз вызова.

            Шлюз вызова позволяет передавать управление с одного уровня привилегий на другой. Также шлюз вызова полезен при передаче управления между 16- и 32-разрядным кодом.
            На рис. 4-1 приведен формат дескриптора шлюза вызова.


    Рисунок 4-1. Формат дескриптора шлюза вызова

            Этот дескриптор можно размещать в GDT и LDT, но не в IDT. Дескриптор шлюза вызова выполняет 6 функций:
  • Определяет сегмент кода, к которому будет доступ.
  • Определяет точку входа в этом сегменте.
  • Определяет уровень привилегий, который должна иметь вызывающая процедура.
  • При смене стека, он указывает число необязательных параметров, копируемых процессором из одного стека в другой.
  • Определяет размер значений, записываемых в целевой стек: 16-разрядный шлюз использует 16-разрядные значения, 32-разрядный - 32-разрядные.
  • Определяет присутствие шлюза вызова.

            Поле селектора в шлюзе вызова определяет целевой сегмент кода, смещение задаёт точку входа. DPL определяет уровень привилегий шлюза вызова, который должна иметь процедура, чтобы передать управление через него.
            Флаг P определяет присутствие дескриптора шлюза вызова в памяти. Поле счётчика определяет число параметров (16- или 32-разрядных, в зависимости от разрядности шлюза), копируемых из стека вызывающей процедуры в стек вызываемой процедуры (если происходит смена стека).
            Как правило, флаг P (присутствие дескриптора) всегда установлен, если же он сброшен (т.е. равен 0), то при обращении к шлюзу процессор генерирует исключение неприсутствующего сегмента (#NP). Используя бит P система может определить число переходов через этот шлюз. Для этого бит присутствия шлюза сбрасывается, а функции обработчика исключения #NP сводятся к увеличению на 1 счётчика переходов через шлюз и установке бита P. После возврата из такого обработчика процессор снова попытается передать управление через шлюз и сделает это, если больше никаких нарушений в нём не обнаружит.

            Шлюз вызова по сути определяет дальнюю точку входа (селектор:смещение) для процедуры. При передаче управления через шлюз вызова, вызывающая процедура должна использовать далёкий адрес, селектор которого указывает на шлюз, смещение при этом будет проигнорировано процессором (см. рис. 4-2). Селектор, указанный в шлюзе вызова, может выбирать дескриптор из GDT или LDT.


    Рисунок 4-2. Использование шлюза вызова

            При передаче управления через шлюз вызова, используются 4 типа уровней привилегий:
  • CPL,
  • RPL селектора шлюза вызова,
  • DPL дескриптора шлюза вызова,
  • DPL дескриптора целевого сегмента кода.

            Также учитывается флаг C (подчинение) в дескрипторе сегмента кода.

            Правила проверки уровня привилегий отличаются, в зависимости от того, какой командой было передано управление (см. таб. 4-1):

    Таблица 4-1. Правила проверки уровня
    привилегий для шлюза вызова.
    Команда Правила проверки привилегий
    CALL CPL ≤ DPL шлюза вызова
    RPL ≤ DPL шлюза вызова
    DPL целевого подчинённого сегмента ≤ CPL
    DPL целевого неподчинённого сегмента ≤ CPL
    JMP CPL ≤ DPL шлюза вызова
    RPL ≤ DPL шлюза вызова
    DPL целевого подчинённого сегмента ≤ CPL
    DPL целевого неподчинённого сегмента = CPL

            Поле DPL дескриптора шлюза вызова определяет наибольший номер уровня привилегий, с которого вызывающая процедура может обращаться к шлюзу. Таким образом, для доступа к шлюзу CPL вызывающей процедуры должен быть не больше DPL шлюза.
            RPL селектора шлюза вызова должен удовлетворять тем же условиям, что и CPL вызывающей процедуры, т.е. RPL должен быть не больше DPL шлюза.

            Если проверка уровня привилегий между вызывающей процедурой и шлюзом вызова успешна, то процессор проверяет DPL дескриптора сегмента кода, сравнивая его с CPL вызывающей процедуры.
            Правила проверки уровня привилегий отличаются для команд JMP и CALL. Только команда CALL может использовать шлюз вызова для передачи управления более привилегированному неподчинённому сегменту кода (т.е., чей DPL ≤ CPL). Команда JMP может использовать шлюз вызова только для передачи управления в неподчинённый сегмент кода с DPL = CPL. Команды JMP и CALL обе могут передавать управление более привилегированному подчинённому сегменту кода (т.е., чей DPL ≤ CPL).
            Если вызов производится на более привилегированный неподчинённый сегмент кода, то CPL опускается до значения DPL и производится переключение стека. Если же передача управления происходит в подчинённый сегмент кода, то CPL не меняется и стек не переключается.

            Шлюзы вызова позволяют одному сегменту кода иметь доступ к процедурам, располагающимся на разных уровнях привилегий. Например, операционная система, находящаяся в сегменте кода, может иметь некоторые сервисы, которые могут использоваться как ею самой, так и прикладными программами (например, процедуры по обработке ввода/вывода символов).

    Следующая глава Оглавление Вопросы? Замечания? Пишите: sasm@narod.ru

      Copyright © Александр Семенко.
    TopList

    Hosted by uCoz