Зачем иметь два перекрывающихся сегмента данных (например, в ядре Linux)?

В ядре Linux, а также во многих онлайн-учебниках по x86 я вижу, что люди рекомендуют использовать два сегмента кода и два сегмента данных. Я понимаю необходимость двух сегментов кода, поскольку CPL должен точно соответствовать DPL (для несоответствующих сегментов).

Однако ни в одном из этих руководств (и ни в одном из связанных вопросов о StackOverflow) конкретно не говорится, зачем нам нужны два сегмента данных. Они работают иначе, чем сегменты кода, поскольку процесс с CPL=0 может получить доступ к сегменту данных с DPL=3.

Недостатком наличия двух сегментов данных является необходимость перезагрузки регистров DS, ES и т. д., если у нас есть переключение между процессами с разными уровнями привилегий.

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


person Brandon Pickering    schedule 04.08.2016    source источник


Ответы (1)


Объяснение есть здесь.

Цитата из руководств Intel (раздел 5.7)

Проверка уровня привилегий также происходит, когда в регистр SS загружается селектор сегмента для сегмента стека.
Здесь все уровни привилегий, относящиеся к сегменту стека, должны соответствовать CPL; то есть CPL, RPL селектора сегмента стека и DPL дескриптора сегмента стека должны быть одинаковыми. Если RPL и DPL не равны CPL, генерируется исключение общей защиты (#GP).

Внимание мое

То есть для SS требуется сегмент данных с DPL равным 0 при загрузке из ядра (или во время переключения).
Это верно для 32-битного режима.

В 64-битном режиме можно использовать селектор NULL для подавления любой проверки во время выполнения (включая предыдущую)1

В 64-битном режиме процессор не выполняет проверку селекторов сегментов NULL во время выполнения. Процессор не вызывает ошибку #GP при попытке доступа к памяти, где регистр сегмента, на который ссылаются, имеет селектор сегмента NULL.

Из полноты, при выполнении операции со стеком вся соответствующая информация, размер адреса, размер операнда и размер адреса стека, либо восстанавливается из сегмент кода или неявно установлены на 64 бита.


1 Если я правильно помню, 64-битный режим по-прежнему использует сегмент данных ядра из соображений совместимости.

person Margaret Bloom    schedule 04.08.2016