При создании программного обеспечения все, как правило, активно ратуют за соблюдение принципов проектирования, но, на самом деле, систематически эти принципы применяются очень редко. Авторы статьи описывают принципы, на основе которых они создавали операционную систему «с нуля», а также рассказывают о том, как эти принципы повлияли на архитектуру, структуру приложений, защищенность и тестируемость системы.

Extremely Reliable Operating System (EROS) [1] — операционная система на основе мандатов, призванная выполнять требования защиты и надежности активных систем. Пользователи активных систем могут в любое время вводить и исполнять произвольный код, в том числе ошибочный или даже вредоносный. Активные системы представляют собой разделяемые платформы, которые должны одновременное поддерживать потенциально конкурирующих пользователей на одной машине в одно и то же время.

Поскольку активные системы исполняют код, предоставленный пользователем, мы не можем особо полагаться на то, что защита на границах системы позволит предотвратить последствия работы вредоносного кода. В случае исполнения такого кода EROS дает гарантии и безопасности, и работоспособности системы (загружаемое программное обеспечение можно найти на www.eros-os.org). Приложения, которые исполняют вредоносный код (такой как вирусы) не могут нанести ущерб другим пользователями или системе в целом и не могут использовать права доступа, предоставленные пользователю, чтобы нанести ущерб другим компонентам пользовательской среды.

Проект EROS начинался как эталонная реализация KeyKOS [2], операционной системы, созданной Нормом Харди и его коллегами для IBM System/370 (первые документы по системе KeyKOS можно найти на сайте www.cis.upenn.edu/~KeyKOS). Основной вклад EROS заключается в формальной проверке некоторых основных свойств защиты архитектуры и инжиниринге реализации конкретных характеристик работы. Этих характеристик защиты и производительности удалось добиться двумя способами.

Во-первых, при создании основной архитектуры системы разработчики придерживались жестких принципов. В том случае, если планируемая возможность системы противоречила принципу защиты, мы сразу же от нее отказывались. В результате была создана небольшая, внутренне непротиворечивая архитектура, чье поведение четко очерчено и которая приводит к тщательной и надежной реализации. Во-вторых, ведущие архитекторы системы раньше занимались разработкой процессоров. Это позволило нам избежать определенного рода абстракции, которой, как правило, отличаются современные операционные системы, и разрабатывать систему так, чтобы она напрямую соответствовала функциям, которые предлагают современные аппаратные реализации; при преобразовании абстракций производительность уменьшается очень незначительно.

Джереми Салцер и Майкл Шредер выработали многие принципы проектирования EROS при реализации проекта Multics [3] и интегрировали другие на основе своего опыта работы над иными проектами (см. врезки «Материалы по сходной тематике», «Основные принципы программирования EROS»). Согласованности производительности и архитектуры системы удалось добиться исключительно за счет поиска наилучших способов точного выполнения этих принципов вплоть до нюансов, при этом, не снижая производительности.

Мы строго придерживались принципов архитектуры при проектировании EROS/KeyKOS по следующим трем причинам.

  • Мы хотели быть уверены в том, что система работает, и знать почему она работает. Если для каждого фрагмента системного кода невозможно сказать, каков руководящий принцип или обязательное ограничение, гарантирующее корректность, добиться этой цели очень сложно. Связь такого рода также необходима для оценок работы системы с высокой степенью достоверности.
  • Мы предполагали, что четкая архитектура сама будет способствовать высокопроизводительной реализации. Проведенные тесты на производительность подтвердили правильность таких предположений [1].
  • Мы хотели формально и строго проверить некоторые из механизмов защиты, которые используются в системе. Строгая проверка механизма ограничений в EROS, который является критически важным компонентом защиты в системе, была недавно завершена [4].

Архитектура ядра EROS

Самое непосредственное влияние принципов проектирования в EROS сказалось на структуре и реализации ядра. В некоторых случаях наше жесткое следование принципам проектирования приводило к неожиданным архитектурным решениям.

Безопасная перезагрузка

В защищенных системах необходимо гарантировать, что после перезагрузки система находиться в непротиворечивом и защищенном состоянии. В большинстве операционных систем существует первоначальный набор процессов, которые специально создаются ядром. Эти процессы выполняют проверку непротиворечивости, ограничивают свои полномочия теми, которые предполагаются в стабильном режиме, а затем инициируют остальные программы в системе. В этой ситуации возникает две проблемы.

  1. Проверка непротиворечивости является эвристической, в силу чего определить ее корректность довольно сложно. К примеру, команда fsck в Unix должна определить, какие файлы удалить, а какие оставить, не зная о том, как эти файлы взаимосвязаны. Следовательно, состояние файлов паролей и групп могут оказаться несогласованными друг с другом.
  2. Первоначальные процессы получают свои полномочия с помощью средств, которые выходят за рамки обычных механизмов предоставления или передачи полномочий. Разработчики должны создать особые средства для демонстрации того, что система корректным образом управляет этими полномочиями и сокращает их. Сложность этих средств сравнима со сложностью средств обеспечения корректности остальной части системы.

В EROS обе проблемы решены за счет использования системы реализации контрольных точек при выполнении транзакций. Эта система периодически делает рациональные асинхронные снимки состояния всей машины, выполняя проверку непротиворечивости этого состояния, а затем записывает его в рамках одной дисковой транзакции. Поскольку система поддерживает механизм транзакций в целом, ситуация несогласованности всей системы невозможна. При перезагрузке система просто восстанавливает последнюю полностью выполненную транзакцию.

Ядро, не сохраняющее состояние

EROS — это ядро, не сохраняющее состояние — состояние исполнения системы размещается в зарезервированной пользователем памяти. Приемлемая производительность ядра достигается за счет кэширования этого состояния. Архитектура кэширования поддерживает механизм контрольных точек и обеспечивает контроль зависимостей в ядре. Чтобы гарантировать, что зарезервированная пользователем память всегда при проверке предоставляет корректные значения, ядро должно иметь возможность восстанавливать свое состояние по требованию. Эти зависимости предлагают определенную форму самопроверки. Ядро может иногда сравнивать свое кэшированное состояние с пользовательским состоянием, чтобы выявить несогласованность, тем самым не позволяя записывать на диск некорректное состояние.

EROS не открывает фрагменты карты памяти, поскольку это может нарушить принцип несохранения состояния ядра. Вместо этого EROS требует, чтобы приложение точно резервировало все фрагменты, которые составляют структуру отображения памяти. На рисунке 1 показан небольшой фрагмент адресного пространства EROS. Приложение точно резервирует (обычно с помощью обработчика ошибок на уровне пользователя) каждый узел и страницу в этом адресном пространстве. Ядро создает таблицы отображения памяти и аппаратного обеспечения за счет переноса этой структуры и кэширования результатов в таблицах отображения аппаратного обеспечения.

Рис. 1. Адресное пространство EROS

Полное посредничество

В EROS ресурсы включают в себя страницы памяти, узлы (массивы мандатов фиксированного размера) время центрального процессора, сетевые соединения и все, что из них создается. Каждая отдельная страница, узел или другой ресурс именуются по одному или нескольким мандатам. Каждый мандат именует объект, который реализуется ядром или другим процессом в отдельном адресном пространстве. Мандаты — единственные средства инициации операций над объектами, и единственные операции, которые могут выполняться с помощью мандата — это операции, разрешенные этим мандатом. Это значит, что каждый ресурс обслуживается через посредника и полностью инкапсулирован. В большинстве случаев клиент не может определить различия между системными объектами и объектами, которые реализует серверное программное обеспечение. Таким образом, мы можем рассматривать систему EROS как единое большое пространство защищенных объектов. В таблице 1 приведены некоторые ключевые отличия между системами мандатов и существующими традиционными системами.

Полная подотчетность

Хотя многие системы декларируют в качестве своей цели полную подотчетность, на самом деле, очень мало в каких системах это реализовано на уровне ядра. Ошибки в контроле на уровне ядра часто принимают две формы.

  • Ядро может оказаться не в состоянии отвечать за метаданные ядра. Отображение метаданных особенно сложно для контроля, поскольку на большей части аппаратного обеспечения нет прямого соответствия между числом отображенных страниц и объемом требуемых метаданных.
  • Ядро может отвечать за синтезированные, а не за реальные ресурсы. Процесс состоит из двух узлов. Поскольку они не являются фундаментальной единицей хранения, EROS не поддерживает отдельную категорию квотирования для процессов.

В EROS все ресурсы, которым требуется пространство, рассматриваются с точки зрения двух атомарных единиц хранения — узлов и страниц, и это единицы, на которых строятся расчеты. Приложения точно выполняются все резервирование объектов, а модули обработки ошибок уровня пользователя обслуживают ошибки страниц. Это происходит потому, что для обработки ошибки страницы может потребоваться новая страница, и ядро не может знать, из какого пула ресурсов должна поступить новая страница.

Точное назначение

В EROS для каждой операции, которую выполняет программа, можно выяснить, какой именно мандат предоставил такие права. Если строка кода выполняет операцию, которая изменяет объект, мандат на этот объект точно указывается в аргументах вызова процедуры. Поскольку это так, нет никакой неопределенности относительно того, как и почему была выполнена операция, и вредоносным клиентам становится намного сложнее злоупотребить привилегиями, предоставленными той или иной службе. Даже право выполнения команд не дается изначально — приложение, которое не содержит мандат планирования (schedule capability) не выполняет команды (минимальные привилегии).

Политика доверия

Этот принцип можно переформулировать как «плохая защита мешает хорошему», и лучше всего это иллюстрируется следующим примером. Как правило, пользователям необходима политика защиты, которая, к примеру, гарантирует, что Фред не получит доступ к данному объекту. К сожалению, если программа A имеет мандат, позволяющий ей взаимодействовать с программой B, и A также имеет мандат на определенный ресурс R, то A может получить доступ к R от имени B (т. е., действовать как доверенное лицо). Если две программы могут взаимодействовать, они могут работать вместе. Компилятор Interface Definition Language может автоматически генерировать код, который это делает. Единственный способ действительно не допустить, чтобы Фред получил доступ — это полностью изолировать его программы от других программ, чего, в общем случае, пользователи совсем не желают.

В силу всего вышесказанного, EROS не пытается предотвратить передачу мандатов по санкционированным каналам. Безопасность достигается не за счет предотвращения подобного копирования. EROS не позволяет программам действовать вместе, если не существует санкционированного пути взаимодействия между ними, но ее цель — гарантировать, что такие пути не могут возникнуть. Нам необходимо указать осуществимую политику защиты, которую нельзя реализовать подобным образом.

Принцип минимальной неожиданности

По большей части мы можем реализовать принципы программирования EROS без каких-либо конфликтов. Единственное исключение — это принцип «минимальной неожиданности», который нарушен в спецификации вызова мандата. Если процесс указывает неопределенный адрес в качестве адреса назначения входящей строки данных, ядро будет отбрасывать это сообщение, вместо того, чтобы передать его модулю обработки ошибок для этой области. Проблема в том, что сообщения не буферизуются (как того требует принцип ядра, не сохраняющего состояние), обработчик ошибок не является доверенным, и процесс, посылающий сообщение, может быть разделяемой службой. Атака на отказ от обслуживания, предпринятая против службы, может быть организована за счет предоставления обработчика ошибок, который никогда не возвращает результат. Таким образом, ядро отбрасывает сообщение вместо того, чтобы подвергать систему риску стать объектом атаки на отказ от обслуживания.

Это неожиданно до такой степени, что в одной из конференций было названо недостатком архитектуры. При проверке же оказывается, что это фундаментальный конфликт принципов в данной области, и существует всего три возможных решения: буферизация, прерывания работы или отбрасывание. Буферизация нарушает несколько принципов проектирования (ядро, не сохраняющее состояние, минимальный общий механизм, полная отчетность и отсутствие резервирования ядра), а прерывание работы в условиях большой нагрузки не позволяет реализовать принцип повторяемости. Поэтому, учитывая, что благонамеренное приложение всегда имеет возможность предоставить корректный адресат назначения, оказывается, что отбрасывание является наименее неприятной стратегией для предотвращения отказов от обслуживания.

Компонентные приложения

Сейчас совершенно ясно, что возможности, которые напрямую предлагает ядро EROS, относятся к довольно низкому уровню. Код приложения реализует большинство системных функций, даже заслуживающих доверия функций. Например, ядро EROS напрямую предоставляет страницы дисковой памяти, но не файловой системы. Файловая абстракция полностью строится на уровне приложений (разделение механизма и правил работы), и файловое приложение просто хранит содержимое файла в адресном пространстве, увеличивая адресное пространство по мере необходимости так, чтобы оно могло содержать весь файл. Обязанность файлового приложения состоит в том, чтобы реализовать такие операции, как чтение и запись, которые выполняются над файлом. Механизм контрольных точек обеспечивает стабилизацию. Поскольку каждый файл реализуют разные объекты, эта реализация соответствует принципу наименьшего общего механизма.

Этот метод проектирования — создание высокоуровневых функций за счет объединения базовых примитивов операционной системы в повторно используемые компоненты — основная стратегия для создания приложений EROS. Каждый экземпляр компонента реализуется с помощью отдельного процесса, а ядро обеспечивает высокопроизводительный механизм межпроцессорной связи, позволяющий эффективно объединять эти компоненты. Фактически, крайне редко приложения EROS работают с предлагаемыми ядром объектами напрямую. Большинство приложений повторно используют компоненты, предоставляемые системой, или реализуют новые компоненты, которые обеспечивают необходимую функцию структурированным способом. Это естественным образом заставляет программистов при проектировании приложений применять принцип минимальных полномочий, поскольку эти компоненты предназначены только для использования тех мандатов, которые им необходимы.

Структура приложений

Приложения EROS структурируются как защищенные, связанные мандатами компоненты (рис. 2). Каждый экземпляр компонента работает с индивидуально указанными мандатами, определяющими его полномочия. Мандаты защищены ядром, как и объекты, на которые они указывают. Единственные операции, которые могут выполняться с мандатом — это операции, определяемые объектом. Благодаря этому сочетанию защиты и посредничества, приложение, которое выполняет вредоносный код не может повредить систему в целом или нанести ущерб другим пользователям, а также не может использовать привилегии пользователя для того, чтобы повредить другие части пользовательской среды. Точно также, мандаты управляют доступом к ресурсам, не позволяя вредоносному коду злоупотреблять ресурсами или вывести остальную часть системы из работоспособного состояния.

На рис. 2 тестовый процессор состоит из компонента-контейнера и отдельных компонентов редактирования. Компонент-контейнер имеет доступ к файловой системе пользователя только через доверенную диалоговую систему «открыть/сохранить как», но компоненты редактирования не имеют доступа к файловой системе пользователя. Хотя текстовый процессор имеет недоверительный доступ к оконной системе, инструментарий «открыть/сохранить как» имеет доступ через специальный, доверенный интерфейс. Оконная система дополняет доверенные компоненты различными отличительными признаками окон, тем самым, информируя пользователей о том, что они взаимодействуют с компонентом, который имеет потенциально рискованную привилегию.

Всесторонняя тестируемость и защита

Проектирование приложений как композиций небольших компонентов упрощает тестирование. Благодаря полному посредничеству, каждый компонент может быть вызван только через своей предназначенный интерфейс. Хорошо написанный комплект тестов может обычно воспроизводить и тестировать все состояния, которые реально достигаются клиентским кодом. Компилятор IDL, в общем случае, генерирует внешний интерфейс для компонентов, тем самым серьезно снижая риск атак, рассчитанных на переполнение буфера. Поскольку каждый компонент имеет хорошо определенный, защищенный интерфейс, зачастую можно развернуть новые версии компонента в этой области и протестировать их работу на реальных приложениях, запуская их бок о бок с существующей рабочей версией и сравнивая результаты.

Посреднические компоненты и минимальные полномочия также затрудняют распространение вирусов. Повреждение одного из компонентов, на самом деле, вряд ли удовлетворят амбиции хакера, организовавшего атаку, поскольку действия компонента ограничены мандатами, которые он вызывает. Предположим, что хакер нанес вред какой-то части системы, но ему не так-то просто будет использовать путь связи, посредством которого он может распространить свое вредоносное действие. Все его взаимодействия с остальной системой ограничиваются протоколами, определенными на границах мандата. В отличие от межсетевых экранов, которые должны действовать на сетевом уровне, располагая относительно небольшой информацией о состоянии приложения, мандатные интерфейсы оперируют на уровне приложений с узко определенными, специфическими для компонент интерфейсами. Это дает системе некую оболочку типа «глубокой обороны», чего трудно (или даже невозможно) добиться в приложениях, которые структурированы как единое, неразделенное адресное пространство.

Сравните это с современными системами. Как только поражен фрагмент приложения, все приложение оказывается неработоспособно. В результате, вирус получает все полномочия, которые имеет приложение, даже если исходное приложение реально эти полномочия не использовало. Модуль чтения электронной почты на базе Unix имеет полномочие переписывать любой файл, который имеет право переписать пользователь. Модуль чтения не делает этого, поскольку программа работает корректно, но, когда модуль чтения электронной почты оказывается под властью вируса, он может запустить любой код. В системе с мандатами такое невозможно.

Конструкторы

С компонентной моделью EROS тесно связан компонент общей системной утилиты, получивший название конструктор. Когда разработчик пишет код для нового компонента, ему необходим определенный механизм для создания экземпляра новых копий данного компонента. Это и входит в обязанности конструктора. Для каждого типа объектов в системе существует свой конструктор. Чтобы создать экземпляр объекта, клиент вызывает мандат для его конструктора.

Вторая, и более важная задача конструктора состоит в предотвращении утечки информации. Один из основных вопросов, которые программисту хотелось бы задать относительно компонента, звучит следующим образом: «Если я создал один из этих компонентов и дал ему некоторый фрагмент важной информации, может ли эта информация быть разглашена без моего разрешения?» Конструктор может определять, препятствует ли компонент, который он создает, утечке информации. Это можно сделать, поскольку все возможные действия компонента определены мандатами, которые первоначально содержит компонент. Если эти первоначальные мандаты позволяют (транзитивно) выполнять только операции чтения, то тогда единственный способ, каким компонент может взаимодействовать — используя мандаты, поставляемые программой, создающей компонент. Такой компонент, как говорят, будет ограниченным [5]. До тех пор, пока создатель разборчив в предоставлении мандатов новому компоненту, утечки информации не будет. Поскольку конструктор создает компонент с самого начала, ему известны все мандаты, которые содержит компонент, и, таким образом, он может сертифицировать безопасность компонента. Несмотря на все свои возможности защиты, конструктор создает новые процессы очень быстро. Мы пришли к выводу, что на практике программисты используют конструкторы в качестве общего программного средства создания экземпляров для всех программ.

Самое удивительное, что ограничения о том, что «все мандаты должны быть транзитивны только на чтение» почти всегда достаточно. Сейчас единственные приложения, которые нельзя напрямую создать с учетом этого ограничения — это такие вещи, как сетевые подсистемы. Сетевой подсистеме нужен доступ к внешним устройствам, в силу чего она, безусловно, является потенциальным источником утечки информации. В конце концов, это задача все сети — распространять информацию. Программы, которые допускают утечку информации, вовсе не являются изначально плохими, но их нужно тщательно контролировать.

Таким образом, конструктор является ключом к безопасному выполнению не пользующегося доверием кода. Если такой код исполняется внутри закрытой области, он не может свободно взаимодействовать с остальной частью системы. Хотя атаки на ресурсы (на центральный процессор или память, к примеру) возможны, мы может ограничить и время центрального процессора, и пространство, зарезервированное закрытой подсистемой. Это значит, например, что браузер может быть организован так, чтобы он создавал новые компоненты рендеринга HTML для каждой страницы. В этом компоненте совершенно безопасно исполнять не пользующийся доверием код сценария, поскольку компонент как единое целое закрыт. В силу чего код сценария не имеет доступа ни к чему важному.

Затраты и преимущества

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

Адаптация приложений

Даже если для существующих приложений могут быть созданы совместимые среды (сейчас решается задача обеспечения совместимости на уровне двоичных кодов для среды Linux), EROS требует значительных затрат на разработку. Чтобы воспользоваться преимуществами свойств защиты, имеющихся в базовом ядре, мы должны разделить критически важные приложения на компоненты. Самые важные из этих приложений — это внешние интерфейсы, такие как серверы SMTP, LDAP, HTTP и FTP. Эти службы работают с большими полномочиями и используют критичный к защите код. По завершении система EROS будет выпускаться со всеми этими службами.

Следующей наиболее важной категорией являются приложения, которые исполняют активное информационное наполнение, такое как языки создания сценариев: браузеры, агенты электронной почты и текстовые процессоры. В существующем программном обеспечении в этих приложениях уже существуют точки деления и их легко изменить. Текстовые процессоры, к примеру, обычно открывают файлы для записи только после того, как выводиться некоторое диалоговое окно для работы с файлами. Предстоит проделать большую работу, чтобы изменить механизмы диалоговых окон таким образом, чтобы создать защищенную подсистему и возвращать открытый дескриптор, а не строку, и, тем самым, избавиться от макровирусов. Защита такого уровня не может быть достигнута с помощью списков контроля доступа — в системе, где применяются такие списки, приложение работает с теми же полномочиями, что и пользователь.

Доверительный пользовательский интерфейс

Раньше во всех обсуждениях игнорировался весьма важный момент: каким образом я как пользователь могу знать, что взаимодействую с реальным диалоговым окном для работы с файлами? Это вопрос создания доверительного пользовательского интерфейса, и, хотя в этой области проделана большая работа, сама проблема отнюдь не проста. Архитектура на базе мандатов помогает ее решить, поскольку, к примеру, оконная система может реализовать различные доверительные и недоверительные интерфейсы (рис. 2) и оформлять доверительные окна так, чтобы это было заметно для пользователя. Поскольку мандаты фальсифицировать невозможно, недоверительное приложение не в состоянии сделать так, чтобы выглядеть достойным доверия. Короче говоря, мы свели задачу защиты приложений к корректному проектированию диалогового окна для работы с файлами и гарантиям защиты и доверия к операционной системе, которые мы в состоянии решить.

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

Производительность

Существующие оценки производительности EROS базируются на результатах микротестов [1]. Создание процессов в EROS, к примеру, требует использования пяти компонентов: приложение, посылающее запрос, конструктор, создатель процесса, модуль резервирования памяти и только что созданные компоненты. Несмотря на многокомпонентность данной архитектуры, механизм создания процессов в EROS в три раза быстрее, чем механизм ветвления (fork) и подмены исполняемой программы (exec) в Linux. Обработка ошибок страниц и управление отображением в EROS выполняется более чем в 1000 раз быстрее, чем в Linux.

Поскольку в EROS пока не существует эмулятора Unix, напрямую сравнивать приложения трудно. KeyKOS включает в себя реализацию Posix, совместимую на уровне двоичных кодов, которую можно напрямую сравнить по производительности с реализацией Unix на базе Mach [6]. Мы рассчитываем на то, что совместимая реализация в EROS будет значительно лучше.

Трудно количественно определить, насколько своей тестируемостью и производительностью семейство EROS обязано именно базовым принципам, а не тщательной реализации и проектированию. Вероятно, самое очевидное влияние на результаты проектирования оказал именно принцип отчетности, поскольку он заставлял нас как архитекторов тщательно продумывать все вопросы, связанные с манипуляцией ресурсами и защитой.

Что касается влияния, не последнее место здесь, безусловно, занимают принципы защиты. Насколько успешной будет EROS пока не понятно, но проект, связанный с семейством EROS, уже позволил добиться явно необычной вещи: архитектуры с проверенной защитой с работающей, высокопроизводительной реализацией. В результате, сейчас EROS рассматривают как возможный кандидат на интеграцию в различные коммерческие потребительские устройства. EROS планируется использовать для сервисов, критичных к надежности, таких как реализации упрощенного протокола доступа к каталогу и Web-серверы.

Весьма впечатляющим является следующий факт: прошло более восьми лет с того момента, как мы обнаружили в ядре EROS ошибку, которую не могла локализовать служба проверка качества (assertion check). Это позволяет предположить, что проектирование, выполняемое исходя из жестких принципов, помогло нам создать более надежную систему, поскольку дает возможность более эффективно находить ошибки.

Лаборатория Systems Research Laboratory в университете Джона Хопкинса создает вторую версию EROS, модернизированную таким образом, чтобы она поддерживала встроенные приложения и приложения реального времени. Мы рассчитываем на то, что эта система получит уровень гарантии надежности EAL7, т. е. самый высокий из существующих сейчас уровней, в рамках процедуры Common Criteria [7].

Мы также были свидетелями того, что программисты, использующие EROS, создают свои программы качественно иным образом, чем, скажем разработчики Unix. Системная архитектура заставляет их разделять приложения на управляемые фрагменты, и границы защиты помогают сделать эти фрагменты более тестируемыми. Существуют и другие особенности системы, которые этому способствуют — самая значительная из них — это стиль компонентного кода, определяемого событиями. EROS — первая система в семействе EROS/KeyKOS, которая открыта для значительного числа программистов. Пока слишком рано для появления четкого списка шаблонов проектирования.

Поразительно, однако, что студенты могут быстро монтировать систему и создавать приложения, несмотря на отсутствие различных упрощающих абстракций. Самое, по-видимому, сложное с практической точки зрения для программистов — это отказаться от своих старых, инспирированных Unix представлений о том, как работают процессы. Очень часто они задают вопросы типа: «Как можно сдублировать ту или иную функциональность Unix», несмотря на то, что той же самой цели можно достичь намного проще с помощью предлагаемых в ОС механизмов.

Литература
  1. J.S. Shapiro, J.M. Smith, D.J. Farber, "EROS: A Fast Capability System", Proc. 17th ACM Symp. Operating Systems Principles, ACM Press, New York, 1999
  2. N. Hardy, "The KeyKOS Architecture", Operating Systems Rev., vol. 19, no. 4, 1985
  3. J.H. Saltzer, M.D. Schroeder, "The Protection of Information in Computer Systems", Proc. IEEE, vol. 9, no. 63, 1975
  4. J.S. Shapiro, S. Weber, "Verifying the EROS Confinement Mechanism", Proc. 2000 IEEE Symp. Security and Privacy, IEEE Press, Piscataway, N.J., 2000
  5. B.W. Lampson, "A Note on the Confinement Problem", Comm. ACM, vol. 16, no. 10, 1973
  6. A.C. Bomberger et al., "The KeyKOS Nanokernel Architecture", Proc. Usenix Workshop Micro-Kernels and other Kernel Architectures, Usenix, San Diego, 1992
  7. Common Criteria for Information Technology Security, ISO/IS 15408, Int'l Standards Organization, Final Committee Draft, version 2.0, 1998

Джонатан Шапиро (shap@cs.jhu.edu) — доцент факультета информатики университета Джона Хопкинса. К области его научных интересов относятся компьютерная безопасность, операционные системы и инструментальные средства разработки. Норм Харди (norm@agorics.com) — старший архитектор компании Agorics. Он специализируется на операционных системах, безопасности и языках программирования.


Основные принципы проектирования EROS

Принципы, взятые из проекта Multics Project
  • Экономия механизма: добиваться максимально простой архитектуры.
  • Надежные значения по умолчанию: принимать решения о доступе по разрешительному принципу, а не исключительному.
  • Полное посредничество: проверять полномочия при каждом доступе.
  • Открытая архитектура: архитектура не должна быть секретом. (В EROS и архитектура, и реализация открыты).
  • Минимальные привилегии: компоненты не должны иметь больше полномочий, чем им требуется (а, иногда, и меньше).
  • Минимальный общий механизм: минимизировать объем разделяемых экземпляров в системе.
Общепринятые принципы
  • Разделение правил работы и механизма: ядро должно реализовывать механизм, посредством которого реализуется управление ресурсами, но не должно определять правила, в соответствии с которыми этот контроль осуществляется.
  • Минимальная неожиданность: поведение системы должны соответствовать тому, что естественно предположить.
  • Полная отчетность: все реальные ресурсы, принадлежащие приложению, должны предоставляться из некоторого подотчетного пула.
  • Безопасная перезагрузка: при перезагрузке система должна либо уже поддерживать, либо иметь возможность быстро установить непротиворечивое и защищенное состояние исполнения.
  • Повторяемость: корректные операции должны порождать идентичные результаты вне зависимости от рабочей нагрузки.
Принципы, специфические для EROS
  • Политика доверия: если правила защиты не могут быть реализованы за счет корректного использования механизмов защиты, имеющихся в системе, не следует требовать их применения.
  • Отсутствие резервирования ядра: ядру запрещено создавать или освобождать ресурсы. Однако можно использовать основную память как динамический кэш для этих ресурсов.
  • Атомарность операций: все операции, которые выполняет ядро, являются атомарными, т. е. либо они выполняются так, чтобы завершиться в ограниченное время, либо они не имеют видимого эффекта.
  • Ослабление полномочий: если приложение имеет определенные полномочия, оно должно (в принципе) иметь возможность по своему усмотрению сокращать эти полномочия.
  • Ядро, не сохраняющее состояние: Защита системы и ее состояние исполнения должны логически размещаться в резервируемой пользователем памяти. Ядро вправе кэшировать это состояние.
  • Однозначное назначение полномочий. Каждая операция точно указывает источник полномочий, которые она использует.

Материалы сходной тематики

Хенри Леви [1] и Эд Геринджер [2] предлагают обзоры некоторых мандатных систем. EROS заимствует идеи напрямую у трех ранее существовавших мандатных систем. Как и Hydra [3] система EROS — система, существенным образом опирающаяся на механизм мандатов. Программы могут реализовывать новые объекты, которые вызывают защищенные мандаты. Как и CAL/TSS [4] система EROS объединяет процессы в защищенные домены. Проектировщики EROS хорошо усвоили уроки, извлеченные разработчиками при выполнении проекта CAL/TSS. Компьютер Cambridge CAP [5], хотя он реализован аппаратно, аналогичным образом использует детализированные мандаты для защиты памяти. Это также первый пример ядра, не сохраняющего состояние.

EROS использует мандаты, защищаемые ядром. Альтернативная система Amoeba [6] использует мандаты на обработку как данные, выполняя с целью защиты нерегулярное неплотное резервирование. Этот подход не поддерживает разграничение, поскольку невозможно определить, какие биты приложения представляют данные, а какие — мандаты.

В случае применения простых схем шифрования или подписей возникает та же проблема. Одно из возможных решений — мандаты с паролями, которые применяются в Monash [7] и Mungi [8]. В этом случае перед принятием мандатов выполняется определенная системой операция XOR. Опасения, возникающие в связи с этим подходом, состоят в том, что любую операцию, достаточно простую для того, чтобы быть эффективной (такую как XOR) можно легко подвергнуть обратному инжинирингу. Настоящая криптографическая проверка должна выполняться с помощью кэширования, чтобы избежать запредельных вычислительных затрат.

Литература
  1. H.M. Levy, Capability-Based Computer Systems, Digital Press, 1984
  2. E.F. Gehringer, Capability Architectures and Small Objects, UMI Research Press, Ann Arbor, Mich., 1982
  3. W.A. Wulf, R. Levin, S.P. Harbison, HYDRA/C.mmp: An Experimental Computer System, McGraw Hill, New York, 1981
  4. B.W. Lampson, H.E. Sturgis, "Reflections on an Operating System Design", Comm. ACM, vol. 19, no. 4, 1976
  5. M.V. Wilkes, R.M. Needham, The Cambridge CAP Computer and its Operating System, Elsevier, North Holland, 1979
  6. A.S. Tannenbaum, S.J. Mullender, R. van Renesse, "Using Sparse Capabilities in a Distributed Operating System", Proc. 9th Int'l Symp. Distributed Computing Systems, IEEE Press, Piscataway, N.J., 1986
  7. M. Anderson, R. Pose, C.S. Wallace, "A Password Capability System", The Computer J., vol. 29, no. 1, 1986
  8. G. Heiser et al., "Mungi: A Distributed Single Address-Space Operating System", Proc. 17th Australiaision Computer Science Conf., ACM Press, New York, 1994