Защита памяти — это способ управления правами доступа к памяти на компьютере, который является частью большинства современных архитектур наборов команд и операционных систем . Основная цель защиты памяти — предотвратить доступ процесса к памяти, которая ему не выделена. Это предотвращает влияние ошибки или вредоносного ПО внутри процесса на другие процессы или на саму операционную систему. Защита может охватывать все доступы к указанной области памяти, доступы к записи или попытки выполнить содержимое области. Попытка доступа к несанкционированной [a] памяти приводит к аппаратному сбою , например, сбою сегментации , исключению нарушения хранения , обычно вызывающему ненормальное завершение процесса-нарушителя. Защита памяти для обеспечения безопасности компьютера включает в себя дополнительные методы, такие как рандомизация макета адресного пространства и защита исполняемого пространства .
Сегментация относится к разделению памяти компьютера на сегменты. Ссылка на местоположение памяти включает значение, которое идентифицирует сегмент и смещение внутри этого сегмента. Дескриптор сегмента может ограничивать права доступа, например, только чтение, только из определенных колец .
Архитектура x86 имеет несколько функций сегментации, которые полезны для использования защищенной памяти в этой архитектуре. [1] В архитектуре x86 глобальная таблица дескрипторов и локальные таблицы дескрипторов могут использоваться для ссылки на сегменты в памяти компьютера. Указатели на сегменты памяти на процессорах x86 также могут храниться в сегментных регистрах процессора. Первоначально процессоры x86 имели 4 сегментных регистра, CS (сегмент кода), SS (сегмент стека), DS (сегмент данных) и ES (дополнительный сегмент); позже были добавлены еще два сегментных регистра – FS и GS. [1]
При страничном размещении адресное пространство памяти или сегмент делится на блоки одинакового размера [b], называемые страницами . Используя аппаратное обеспечение виртуальной памяти , каждая страница может находиться в любом месте на подходящей границе физической памяти компьютера или быть помечена как защищенная. Виртуальная память позволяет иметь линейное адресное пространство виртуальной памяти и использовать его для доступа к блокам, фрагментированным по адресу физического пространства памяти .
Большинство компьютерных архитектур , поддерживающих страничную организацию памяти, также используют страницы в качестве основы для защиты памяти.
Таблица страниц отображает виртуальную память в физическую память. Может быть одна таблица страниц, таблица страниц для каждого процесса, таблица страниц для каждого сегмента или иерархия таблиц страниц, в зависимости от архитектуры и ОС. Таблицы страниц обычно невидимы для процесса. Таблицы страниц упрощают выделение дополнительной памяти, поскольку каждая новая страница может быть выделена из любого места физической памяти. В некоторых системах запись таблицы страниц также может обозначать страницу как доступную только для чтения.
Некоторые операционные системы устанавливают разные адресные пространства для каждого процесса, что обеспечивает жесткие границы защиты памяти. [2] Непривилегированное [c] приложение не может получить доступ к странице, которая не была ему явно выделена, поскольку каждый адрес памяти либо указывает на страницу, выделенную этому приложению, либо генерирует прерывание, называемое ошибкой страницы . Невыделенные страницы и страницы, выделенные любому другому приложению, не имеют никаких адресов с точки зрения приложения.
Ошибка страницы не обязательно указывает на ошибку. Ошибки страницы используются не только для защиты памяти. Операционная система может управлять таблицей страниц таким образом, что ссылка на страницу, которая ранее была выгружена во вторичное хранилище [d], вызывает ошибку страницы. Операционная система перехватывает ошибку страницы, загружает требуемую страницу памяти, и приложение продолжает работу, как будто никакой ошибки не произошло. Эта схема, тип виртуальной памяти , позволяет перемещать данные в памяти, которые в данный момент не используются, во вторичное хранилище и обратно способом, который прозрачен для приложений, для увеличения общей емкости памяти.
В некоторых системах запрос на виртуальное хранилище может выделить блок виртуальных адресов, для которых не назначены страничные фреймы, и система будет назначать и инициализировать страничные фреймы только при возникновении ошибок страниц. В некоторых системах может использоваться защитная страница , либо для обнаружения ошибок, либо для автоматического увеличения структур данных.
В некоторых системах механизм ошибки страницы также используется для защиты исполняемого пространства , например W^X .
Механизм ключа защиты памяти (MPK) [3] делит физическую память на блоки определенного размера (например, 4 КиБ), каждый из которых имеет связанное с ним числовое значение, называемое ключом защиты. Каждый процесс также имеет связанное с ним значение ключа защиты. При доступе к памяти оборудование проверяет, соответствует ли ключ защиты текущего процесса значению, связанному с блоком памяти, к которому осуществляется доступ; если нет, возникает исключение. Этот механизм был введен в архитектуре System/360 . Он доступен на современных мэйнфреймах System z и активно используется операционными системами System z и их подсистемами.
Описанные выше ключи защиты System/360 связаны с физическими адресами. Это отличается от механизма ключей защиты, используемого такими архитектурами, как Hewlett-Packard / Intel IA-64 и Hewlett-Packard PA-RISC , которые связаны с виртуальными адресами и допускают несколько ключей на процесс.
В архитектурах Itanium и PA-RISC трансляции ( записи TLB ) имеют ключи (Itanium) или идентификаторы доступа (PA-RISC), связанные с ними. Выполняющийся процесс имеет несколько регистров ключей защиты (16 для Itanium, [4] 4 для PA-RISC [5] ). Трансляция, выбранная виртуальным адресом, имеет свой ключ, сравненный с каждым из регистров ключей защиты. Если любой из них совпадает (плюс другие возможные проверки), доступ разрешен. Если ни один из них не совпадает, генерируется ошибка или исключение. Программный обработчик ошибок может, при желании, проверить отсутствующий ключ по большему списку ключей, поддерживаемому программным обеспечением; таким образом, регистры ключей защиты внутри процессора могут рассматриваться как программно-управляемый кэш большего списка ключей, связанных с процессом.
PA-RISC имеет 15–18 бит ключа; Itanium требует не менее 18. Ключи обычно связаны с доменами защиты , такими как библиотеки, модули и т. д.
В x86 архитектура ключей защиты [6] позволяет помечать виртуальные адреса для страниц пользователя любым из 16 ключей защиты. Все страницы, помеченные одним и тем же ключом защиты, составляют домен защиты. Новый регистр содержит разрешения, связанные с каждым доменом защиты. Операции загрузки и сохранения проверяются как по разрешениям таблицы страниц, так и по разрешениям ключа защиты, связанным с доменом защиты виртуального адреса, и разрешаются только в том случае, если оба разрешения разрешают доступ. Разрешения ключа защиты могут быть установлены из пространства пользователя, что позволяет приложениям напрямую ограничивать доступ к данным приложения без вмешательства ОС. Поскольку ключи защиты связаны с виртуальным адресом, домены защиты находятся на каждом адресном пространстве, поэтому процессы, работающие в разных адресных пространствах, могут использовать все 16 доменов.
В Multics и системах, полученных из него, каждый сегмент имеет защитное кольцо для чтения, записи и выполнения; попытка процесса с более высоким номером кольца, чем номер кольца для сегмента, вызывает ошибку. Существует механизм для безопасного вызова процедур, которые работают в нижнем кольце, и возврата в верхнее кольцо. Существуют механизмы для процедуры, работающей с низким номером кольца, для доступа к параметру с большим из ее собственного кольца и кольца вызывающего.
Моделирование — это использование программы мониторинга для интерпретации инструкций машинного кода некоторых компьютерных архитектур. Такой симулятор набора инструкций может обеспечить защиту памяти, используя схему, подобную сегментации, и проверяя целевой адрес и длину каждой инструкции в реальном времени перед их фактическим выполнением. Симулятор должен вычислить целевой адрес и длину и сравнить их со списком допустимых диапазонов адресов, которые он содержит относительно среды потока , например, любые динамические блоки памяти , полученные с момента создания потока, а также любые допустимые общие слоты статической памяти. Значение «допустимого» может меняться на протяжении жизни потока в зависимости от контекста. Иногда может быть разрешено изменять статический блок памяти, а иногда нет, в зависимости от текущего режима выполнения, который может зависеть или не зависеть от ключа хранилища или состояния супервизора. [ необходима цитата ]
Обычно не рекомендуется использовать этот метод защиты памяти, если на ЦП имеются адекватные возможности, поскольку это отнимает ценную вычислительную мощность у компьютера. Тем не менее, он обычно используется для отладки и тестирования, чтобы обеспечить дополнительный уровень детализации для общих нарушений хранения и может точно указать, какая инструкция пытается перезаписать конкретный раздел хранения, который может иметь тот же ключ хранения, что и незащищенное хранилище.
Адресация на основе возможностей — это метод защиты памяти, который не используется в современных коммерческих компьютерах. В этом методе указатели заменяются защищенными объектами (называемые возможностями ), которые могут быть созданы только с помощью привилегированных инструкций, которые могут быть выполнены только ядром или каким-либо другим процессом, уполномоченным на это. [ требуется ссылка ] Это эффективно позволяет ядру контролировать, какие процессы могут получать доступ к каким объектам в памяти, без необходимости использования отдельных адресных пространств или переключателей контекста . Только несколько коммерческих продуктов использовали безопасность на основе возможностей: Plessey System 250 , IBM System/38 , архитектура Intel iAPX 432 и KeyKOS . Подходы на основе возможностей широко используются в исследовательских системах, таких как браузер EROS и Combex DARPA. Они используются концептуально в качестве основы для некоторых виртуальных машин , в первую очередь Smalltalk и Java . В настоящее время финансируемый DARPA проект CHERI в Кембриджском университете работает над созданием современной машины возможностей, которая также поддерживает устаревшее программное обеспечение.
Динамическое заражение — это метод защиты программ от несанкционированного доступа к памяти. Когда память выделяется во время выполнения, этот метод заражает как память, так и соответствующий указатель, используя одну и ту же метку заражённости. Метки заражённости затем соответствующим образом распространяются во время выполнения программы и проверяются каждый раз, когда к адресу памяти m осуществляется доступ через указатель p ; если метки заражённости, связанные с m и p, различаются, выполнение останавливается и сообщается о несанкционированном доступе. [7] [8]
Процессоры SPARC M7 (и выше) реализуют динамическое заражение на аппаратном уровне. Oracle продвигает эту функцию как Silicon Secured Memory (SSM) (ранее называвшуюся Application Data Integrity (ADI)). [9]
Конструкция lowRISC CPU включает динамическое заражение под названием Tagged Memory. [10]
Уровень защиты конкретной реализации можно измерить по тому, насколько точно она соответствует принципу минимальных привилегий . [11]
Различные операционные системы используют различные формы защиты или разделения памяти. Хотя защита памяти была распространена на большинстве мэйнфреймов и многих миникомпьютерных системах с 1960-х годов, настоящее разделение памяти не использовалось в операционных системах домашних компьютеров до тех пор, пока OS/2 (и в RISC OS ) не была выпущена в 1987 году. В предыдущих системах такое отсутствие защиты даже использовалось как форма межпроцессного взаимодействия , путем отправки указателя между процессами. Процессы могут получать доступ к системной памяти в семействе операционных систем Windows 9x . [12]
Вот некоторые операционные системы, которые реализуют защиту памяти:
В Unix-подобных системах mprotect
системный вызов используется для управления защитой памяти. [14]