В информатике иерархические домены защиты , [1] [2] часто называемые кольцами защиты , представляют собой механизмы защиты данных и функциональности от сбоев (путем повышения отказоустойчивости ) и вредоносного поведения (путем обеспечения компьютерной безопасности ).
Компьютерные операционные системы предоставляют различные уровни доступа к ресурсам. Кольцо защиты — это один из двух или более иерархических уровней или слоев привилегий в архитектуре компьютерной системы . Обычно это обеспечивается аппаратно некоторыми архитектурами ЦП , которые предоставляют различные режимы ЦП на уровне оборудования или микрокода . Кольца организованы в иерархии от наиболее привилегированных (наиболее доверенных, обычно с номером ноль) до наименее привилегированных ( наименее доверенных, обычно с самым высоким номером кольца). В большинстве операционных систем кольцо 0 — это уровень с наибольшими привилегиями, который взаимодействует наиболее непосредственно с физическим оборудованием, таким как определенные функции ЦП (например, регистры управления) и контроллеры ввода-вывода.
Специальные механизмы предусмотрены для того, чтобы внешнее кольцо могло получать доступ к ресурсам внутреннего кольца предопределенным образом, в отличие от разрешения произвольного использования. Правильное ограничение доступа между кольцами может повысить безопасность, предотвращая программы из одного кольца или уровня привилегий от нецелевого использования ресурсов, предназначенных для программ из другого кольца. Например, шпионское ПО, работающее как пользовательская программа в кольце 3, должно быть лишено возможности включать веб-камеру без уведомления пользователя, поскольку доступ к оборудованию должен быть функцией кольца 1, зарезервированной для драйверов устройств . Такие программы, как веб-браузеры, работающие в кольцах с более высокими номерами, должны запрашивать доступ к сети, ресурсу, ограниченному кольцом с более низким номером.
X86S, недавно опубликованная архитектура Intel, имеет только кольцо 0 и кольцо 3. Кольца 1 и 2 будут удалены в X86S, поскольку современные ОС никогда их не используют. [3]
Несколько колец защиты были среди самых революционных концепций, представленных операционной системой Multics , высокозащищенным предшественником сегодняшнего семейства операционных систем Unix . Мейнфрейм-компьютер GE 645 имел некоторое аппаратное управление доступом, включая те же два режима, что и другие машины серии GE-600, и разрешения на уровне сегмента в его блоке управления памятью («Appending Unit»), но этого было недостаточно для обеспечения полной поддержки колец в оборудовании, поэтому Multics поддерживал их, перехватывая переходы колец в программном обеспечении; [4] его преемник, Honeywell 6180 , реализовал их в оборудовании с поддержкой восьми колец; [5] Кольца защиты в Multics были отделены от режимов ЦП; код во всех кольцах, кроме кольца 0, и некоторый код кольца 0, работали в подчиненном режиме. [6]
Однако большинство систем общего назначения используют только два кольца, даже если оборудование, на котором они работают, обеспечивает больше режимов ЦП , чем это. Например, Windows 7 и Windows Server 2008 (и их предшественники) используют только два кольца, причем кольцо 0 соответствует режиму ядра, а кольцо 3 — пользовательскому режиму , [7] поскольку более ранние версии Windows NT работали на процессорах, которые поддерживали только два уровня защиты. [8]
Многие современные архитектуры ЦП (включая популярную архитектуру Intel x86 ) включают некоторую форму защиты колец, хотя операционная система Windows NT , как и Unix, не использует эту функцию в полной мере. OS/2 в некоторой степени использует три кольца: [9] кольцо 0 для кода ядра и драйверов устройств, кольцо 2 для привилегированного кода (пользовательских программ с разрешениями на доступ к вводу-выводу) и кольцо 3 для непривилегированного кода (почти все пользовательские программы). В DOS ядро, драйверы и приложения обычно работают на кольце 3 (однако, это касается исключительно случая, когда используются драйверы защищенного режима или расширители DOS; как ОС реального режима, система работает фактически без защиты), тогда как менеджеры памяти 386, такие как EMM386 , работают на кольце 0. В дополнение к этому, DR-DOS ' EMM386 3.xx может опционально запускать некоторые модули (например, DPMS ) на кольце 1 вместо этого. OpenVMS использует четыре режима, называемые (в порядке убывания привилегий) Kernel, Executive, Supervisor и User.
Возобновление интереса к этой структуре проектирования произошло с распространением программного обеспечения Xen VMM , продолжающимися дискуссиями на тему монолитных и микроядер (особенно в группах новостей Usenet и на веб-форумах ), структурой проектирования Ring-1 компании Microsoft в рамках их инициативы NGSCB и гипервизорами на основе виртуализации x86 , такими как Intel VT-x (ранее Vanderpool).
В оригинальной системе Multics было восемь колец, но во многих современных системах их меньше. Аппаратное обеспечение всегда знает о текущем кольце потока выполняемых инструкций с помощью специального машинного регистра. В некоторых системах вместо этого областям виртуальной памяти назначаются номера колец в аппаратном обеспечении. Одним из примеров является Data General Eclipse MV/8000 , в котором верхние три бита счетчика программ (PC) служили регистром кольца. Таким образом, например, код, выполняемый с виртуальным PC, установленным на 0xE200000, автоматически находился бы в кольце 7, а вызов подпрограммы в другом разделе памяти автоматически вызывал бы передачу кольца.
Аппаратное обеспечение серьезно ограничивает способы передачи управления от одного кольца к другому, а также накладывает ограничения на типы доступа к памяти, которые могут выполняться между кольцами. Используя x86 в качестве примера, существует специальная [ требуется разъяснение ] структура шлюза , на которую ссылается инструкция вызова , которая передает управление безопасным способом [ требуется разъяснение ] к предопределенным точкам входа в кольцах более низкого уровня (более доверенных); это функционирует как вызов супервизора во многих операционных системах, использующих архитектуру кольца. Аппаратные ограничения призваны ограничить возможности случайных или злонамеренных нарушений безопасности. Кроме того, наиболее привилегированному кольцу могут быть предоставлены специальные возможности (например, адресация реальной памяти, которая обходит оборудование виртуальной памяти).
Архитектура ARM версии 7 реализует три уровня привилегий: приложение (PL0), операционная система (PL1) и гипервизор (PL2). Необычно, что уровень 0 (PL0) является наименее привилегированным уровнем, в то время как уровень 2 является наиболее привилегированным уровнем. [10] ARM версии 8 реализует четыре уровня исключений: приложение (EL0), операционная система (EL1), гипервизор (EL2) и защищенный монитор/прошивка (EL3) для AArch64 [11] : D1-2454 и AArch32. [11] : G1-6013
В некоторых системах защита кольца может быть объединена с режимами процессора (режим master/kernel/privileged/supervisor против slave/unprivileged/user). Операционные системы, работающие на оборудовании, поддерживающем оба, могут использовать обе формы защиты или только одну.
Эффективное использование кольцевой архитектуры требует тесного взаимодействия между оборудованием и операционной системой. [ почему? ] Операционные системы, разработанные для работы на нескольких аппаратных платформах, могут использовать кольца только ограниченно, если они не присутствуют на каждой поддерживаемой платформе. Часто модель безопасности упрощается до «ядра» и «пользователя», даже если оборудование обеспечивает более тонкую детализацию через кольца.
В компьютерных терминах режим супервизора — это аппаратно-опосредованный флаг, который может быть изменен кодом, запущенным в программном обеспечении системного уровня. Задачи или потоки системного уровня могут [a] иметь этот флаг установленным во время их работы, тогда как приложения пользовательского уровня — нет. Этот флаг определяет, будет ли возможно выполнять операции машинного кода, такие как изменение регистров для различных таблиц дескрипторов или выполнение операций, таких как отключение прерываний. Идея наличия двух разных режимов для работы исходит из принципа «чем больше мощности, тем больше ответственности» — программа в режиме супервизора считается никогда не выходящей из строя, поскольку сбой может привести к сбою всей компьютерной системы.
Режим супервизора — это «режим выполнения на некоторых процессорах, который позволяет выполнять все инструкции, включая привилегированные инструкции. Он также может предоставлять доступ к другому адресному пространству, к оборудованию управления памятью и другим периферийным устройствам. Это режим, в котором обычно работает операционная система». [12]
В монолитном ядре операционная система работает в режиме супервизора, а приложения — в пользовательском режиме. Другие типы операционных систем , например, с экзоядром или микроядром , не обязательно разделяют это поведение.
Несколько примеров из мира ПК:
Большинство процессоров имеют по крайней мере два различных режима. Процессоры x86 имеют четыре различных режима, разделенных на четыре различных кольца. Программы, работающие в кольце 0, могут делать с системой все, что угодно , а код, работающий в кольце 3, должен иметь возможность в любой момент выйти из строя без влияния на остальную часть компьютерной системы. Кольцо 1 и кольцо 2 используются редко, но могут быть настроены с различными уровнями доступа.
В большинстве существующих систем переключение из пользовательского режима в режим ядра связано с высокой стоимостью производительности. Было измерено, что на базовом запросе оно getpid
составляет 1000–1500 циклов на большинстве машин. Из них только около 100 приходится на фактическое переключение (70 из пользовательского в пространство ядра и 40 обратно), остальное — «накладные расходы ядра». [13] [14] В микроядре L3 минимизация этих накладных расходов снизила общую стоимость примерно до 150 циклов. [13]
Морис Уилкс писал: [15]
... в конце концов стало ясно, что иерархическая защита, которую обеспечивали кольца, не совсем соответствовала требованиям системного программиста и давала мало или совсем не давала улучшений по сравнению с простой системой, имеющей только два режима. Кольца защиты поддавались эффективной реализации в оборудовании, но больше о них сказать было нечего. [...] Привлекательность мелкозернистой защиты сохранялась даже после того, как стало ясно, что кольца защиты не дают ответа... Это снова оказалось тупиком...
Для повышения производительности и детерминизма некоторые системы помещают функции, которые, скорее всего, будут рассматриваться как прикладная логика, а не как драйверы устройств, в режим ядра; в качестве примеров приводятся приложения безопасности ( контроль доступа , брандмауэры и т. д.) и мониторы операционной системы. По крайней мере одна встроенная система управления базами данных, e X treme DB Kernel Mode , была разработана специально для развертывания в режиме ядра, чтобы предоставить локальную базу данных для функций приложений на основе ядра и исключить переключения контекста , которые в противном случае возникали бы, когда функции ядра взаимодействуют с системой базы данных, работающей в пользовательском режиме. [16]
Функции также иногда перемещаются по кольцам в обратном направлении. Например, ядро Linux внедряет в процессы раздел vDSO , содержащий функции, которые обычно требуют системного вызова, т. е. перехода кольца. Вместо выполнения системного вызова эти функции используют статические данные, предоставляемые ядром. Это позволяет избежать необходимости перехода кольца и поэтому является более легким, чем системный вызов. Функция gettimeofday может быть предоставлена таким образом.
Последние процессоры Intel и AMD предлагают инструкции виртуализации x86 для гипервизора для управления аппаратным доступом Ring 0. Хотя они взаимно несовместимы, и Intel VT-x (кодовое название «Vanderpool»), и AMD-V (кодовое название «Pacifica») позволяют гостевой операционной системе выполнять операции Ring 0 изначально, не влияя на других гостей или хостовую ОС. До появления аппаратной виртуализации гостевые операционные системы работали под кольцом 1.
Для содействия виртуализации и снижения накладных расходов, вызванных вышеуказанной причиной, VT-x и SVM позволяют гостю работать в Ring 0. VT-x представляет VMX Root/Non-root Operation: гипервизор работает в режиме VMX Root Operation, обладая наивысшей привилегией. Гостевая ОС работает в режиме VMX Non-Root Operation, что позволяет им работать в Ring 0 без фактических аппаратных привилегий. Некорневые операции VMX и переходы VMX контролируются структурой данных, называемой управлением виртуальной машиной. [17] Эти аппаратные расширения позволяют классической виртуализации «Trap and Emulate» выполняться на архитектуре x86, но теперь с аппаратной поддержкой.
Уровень привилегий в наборе инструкций x86 контролирует доступ программы, которая в данный момент выполняется на процессоре, к таким ресурсам, как области памяти, порты ввода-вывода и специальные инструкции. Существует 4 уровня привилегий, от 0, который является наиболее привилегированным, до 3, который является наименее привилегированным. Большинство современных операционных систем используют уровень 0 для ядра/исполняемой части и используют уровень 3 для прикладных программ. Любой ресурс, доступный для уровня n, также доступен для уровней от 0 до n, поэтому уровни привилегий представляют собой кольца. Когда менее привилегированный процесс пытается получить доступ к более привилегированному процессу, ОС сообщается об исключении общей ошибки защиты .
Не обязательно использовать все четыре уровня привилегий. Текущие операционные системы с большой долей рынка, включая Microsoft Windows , macOS , Linux , iOS и Android, в основном используют механизм страничного обмена только с одним битом для указания уровня привилегий как Supervisor или User (U/S Bit). Windows NT использует двухуровневую систему. [18] Программы реального режима в 8086 выполняются на уровне 0 (высший уровень привилегий), тогда как виртуальный режим в 8086 выполняет все программы на уровне 3. [19]
Потенциальные будущие применения для множественных уровней привилегий, поддерживаемых семейством x86 ISA, включают контейнеризацию и виртуальные машины . Ядро операционной системы хоста может использовать инструкции с полным доступом к привилегиям ( режим ядра ), тогда как приложения, работающие в гостевой ОС в виртуальной машине или контейнере, могут использовать самый низкий уровень привилегий в пользовательском режиме. Виртуальная машина и ядро гостевой ОС могут сами использовать промежуточный уровень привилегий инструкций для вызова и виртуализации операций режима ядра, таких как системные вызовы с точки зрения гостевой операционной системы. [20]
Флаг IOPL ( уровень привилегий ввода-вывода ) — это флаг, который есть на всех совместимых с IA-32 процессорах x86 . Он занимает биты 12 и 13 в регистре FLAGS . В защищенном режиме и длинном режиме он показывает уровень привилегий ввода-вывода текущей программы или задачи. Текущий уровень привилегий (CPL) (CPL0, CPL1, CPL2, CPL3) задачи или программы должен быть меньше или равен IOPL, чтобы задача или программа могла получить доступ к портам ввода-вывода .
IOPL можно изменить с помощью POPF(D)
и IRET(D)
только в том случае, если текущий уровень привилегий — Ring 0.
Помимо IOPL, разрешения порта ввода-вывода в TSS также участвуют в определении возможности задачи получать доступ к порту ввода-вывода.
В системах x86 аппаратная виртуализация x86 ( VT-x и SVM ) называется «кольцом −1», режим управления системой называется «кольцом −2», а Intel Management Engine и процессор безопасности платформы AMD иногда называются «кольцом −3». [21]
Многие аппаратные архитектуры ЦП обеспечивают гораздо большую гибкость, чем та, которая используется операционными системами , которые они обычно запускают. Правильное использование сложных режимов ЦП требует очень тесного взаимодействия между операционной системой и ЦП, и, таким образом, имеет тенденцию привязывать ОС к архитектуре ЦП. Когда ОС и ЦП специально разработаны друг для друга, это не является проблемой (хотя некоторые аппаратные функции все еще могут оставаться неиспользованными), но когда ОС разработана для совместимости с несколькими различными архитектурами ЦП, большая часть функций режима ЦП может игнорироваться ОС. Например, причина, по которой Windows использует только два уровня (кольцо 0 и кольцо 3), заключается в том, что некоторые аппаратные архитектуры, которые поддерживались в прошлом (например, PowerPC или MIPS ), реализовали только два уровня привилегий. [7]
Multics была операционной системой, разработанной специально для особой архитектуры ЦП (которая, в свою очередь, была разработана специально для Multics), и она в полной мере использовала доступные ей режимы ЦП. Однако это было исключением из правила. Сегодня эта высокая степень взаимодействия между ОС и оборудованием часто не является экономически эффективной, несмотря на потенциальные преимущества для безопасности и стабильности.
В конечном счете, цель различных режимов работы ЦП заключается в обеспечении аппаратной защиты от случайного или преднамеренного повреждения системной среды (и соответствующих нарушений безопасности системы) программным обеспечением. Только «доверенным» частям системного программного обеспечения разрешено выполняться в неограниченной среде режима ядра, и то, в парадигматических проектах, только при крайней необходимости. Все остальное программное обеспечение выполняется в одном или нескольких пользовательских режимах. Если процессор генерирует состояние сбоя или исключения в пользовательском режиме, в большинстве случаев стабильность системы не затрагивается; если процессор генерирует состояние сбоя или исключения в режиме ядра, большинство операционных систем остановят систему с неустранимой ошибкой. Когда существует иерархия режимов (безопасность на основе кольца), сбои и исключения на одном уровне привилегий могут дестабилизировать только уровни привилегий с более высокими номерами. Таким образом, сбой в кольце 0 (режим ядра с наивысшими привилегиями) приведет к краху всей системы, но сбой в кольце 2 повлияет только на кольца 3 и далее и само кольцо 2, самое большее.
Переходы между режимами осуществляются по усмотрению исполняемого потока , когда переход происходит с уровня высоких привилегий на уровень низких привилегий (например, из режима ядра в пользовательский режим), но переходы с более низких на более высокие уровни привилегий могут осуществляться только через безопасные, аппаратно контролируемые «ворота», которые проходят при выполнении специальных инструкций или при получении внешних прерываний.
Микроядерные операционные системы пытаются минимизировать объем кода, работающего в привилегированном режиме, в целях безопасности и элегантности , но в конечном итоге жертвуют производительностью.
заключается в том, что некоторые аппаратные архитектуры, которые поддерживались в прошлом (например, Compaq Alpha и Silicon Graphics MIPS ), реализовали только два уровня привилегий.