Компьютерра 20.06.2011 - 26.06.2011

Статьи

Система строгого режима: Microsoft Singularity (часть 1) Евгений Лебеденко, Mobi.ru

Опубликовано 21 июня 2011 года

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

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

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

Драйверы устройств, работающие в пространстве памяти ядра и способные на самые непредсказуемые действия. Динамически подгружаемые библиотеки, код которых одни программы могут перезаписывать в ущерб работе других программ. Бесчисленные уязвимости, основанные на концепции обмена данными через совместно используемые объекты. Все эти механизмы прекрасно работали в ситуации, когда пользователь-профессионал держал работу системы под контролем. Сегодня же юзер, устанавливая новый плагин для браузера, даже не представляет, что за код в нём реализован. А между тем этот плагин будет трудиться в адресном пространстве браузера и без зазрения совести пользоваться всеми возможностями своей родительской программы.

Оставим в покое пользователя-любителя, что с него возьмёшь. Зачастую сама операционная система не ведает, что творят работающие процессы. Многозадачная архитектура современных систем, разработанная в начале семидесятых годов прошлого столетия, подразумевала продуманность каждой запускаемой программы и минимальное количество в ней критических ошибок, дотошно вылавливаемых на этапе программирования и отладки кода. И, конечно же, то, что работающие одновременно программы написаны в соответствии с высшими компьютерными заповедями — не убий своими действиями другой процесс, не укради чужие данные, не нарушай адресное пространство процесса-соседа... — те времена давно прошли. Нынешние программы крадут и убивают, пользуясь тем, что в основе современных систем продолжают лежать принципы «мир, дружба, жвачка».

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

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

Решить эту, казалось бы, нереальную задачу можно как минимум тремя способами.

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

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

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

Второй способ (новая архитектура ОС) реализуется в проекте Microsoft Singularity.

Microsoft Singularity

В недрах компании Microsoft, точнее — в её исследовательском центре Microsoft Research с 2006 года ведётся работа над архитектурой новой операционной системы. Проект Singularity не является «убийцей» нынешней коммерчески успешной Windows, но может доказать, что система с программно изолированными процессами, основанная на идее управляемого выполнения кода, может быть безопаснее и надёжнее традиционных систем. Не потеряв при этом их производительности и расширяемости функций.

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

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

В системах, подобных Singularity, предполагается тщательная верификация кода программы, которая будет в данный момент выполняться. Результат такой верификации — строгое математическое доказательство того, что этот код, именуемый проверенно безопасным (verifiably safe code), в ходе своего выполнения будет работать только с положенными ему объектами и не станет вносить никаких изменений в код и данные других процессов.

То есть, запуская любую программу, система предварительно удостоверяется в полной легитимности работы и, следовательно, полностью контролирует процесс её выполнения. Это и есть идея управляемого выполнения кода.

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

Но разве предварительная верификация кода не снижает производительность системы? Ведь такая проверка не менее затратна по времени и ресурсам, чем переключение процессов.

Ответ на этот вопрос кроется в прогрессе программных платформ управляемого выполнения кода. Основанные на типобезопасных языках, таких, например, как Java или C#, и высокопроизводительных runtime компиляторах, способных «на лету» генерировать оптимальный и дотошно проверенный код, на системах сборки мусора, корректно очищающих память после завершения работы программы, подобные платформы в последнее время сделали гигантский скачок в плане производительности. Теперь она соизмерима с выполнением обычного неуправляемого кода.

Процесс управляемого выполнения кода — основа архитектуры системы Singularity. Базируется он на спецификации Microsoft CLS (Common Language Specification), поддержка которой открыта для многих из имеющихся и вновь разрабатываемых языков программирования и компиляторов для них. Согласно CLS, эти компиляторы не генерируют неуправляемый код, а создают некий промежуточный код на языке MSIL (Microsoft Intermediate Language). Дополнительно с генерацией кода MISL они создают манифест — метаданные программы, в которых чётко описаны её типы, сведения о необходимых программе внешних объектах и правила взаимодействия с ними. Код MISL и манифест упаковываются в исполняемый PE (portable executable) файл.

Дальше происходит компиляция MISL-кода в машинный код, специфичный для системы команд процессора, на котором запущена Singularity. Занимаются этим процессом или JIT-компилятор (just-in-time), генерирующий машинные команды для процессора «на лету», или же программа-генератор NGen (Native Image Generator), создающая традиционный исполняемый образ. Важным является то, что в ходе работы и JIT-компилятора, и программы NGen создаваемый машинный код проверяется на типобезопасность. В случае доказательства того, что полученный код типобезопасен, он исполняется, в противном случае генерируется исключение. Программа не прошла проверку и требует внесения изменений в свой исходный текст.

Проверка на типобезопасность кода каждой программы возможна только тогда, когда чётко доказана корректность работы всех компонентов системы управляемого выполнения кода. В настоящее время в Singularity для процессоров Intel x86 код MSIL компилируется в машинные инструкции компилятором Bartok, разработанным в той же Microsoft Research. При этом команда Singularity исходит из предположения, что Bartok не содержит ошибок и гарантированно создаёт типобезопасный машинный код.


В будущем должен быть создан специальный типизированный ассемблер TAL (Typed Assembly Language), который потребует от каждой программы доказательств её типобезопасности.

Читайте далее: Система строгого режима: Microsoft Singularity (часть 2)


К оглавлению

Система строгого режима: Microsoft Singularity (часть 2) Евгений Лебеденко, Mobi.ru

Опубликовано 23 июня 2011 года

Продолжение. Первую часть читайте здесь.

Микроядро Singularity и SIP

Singularity — микроядерная система. Весь код небольшого и тщательно проверенного на типобезопасность микроядра в большинстве сво`м написан на языке Sing# — подмножестве языка C#, специально разработанного для этой системы в Microsoft Research. Код ядра не верифицируется перед исполнением, поэтому он называется доверенным (trusted). Вообще-то в ядре есть небольшие фрагменты небезопасного кода, написанные на C++ и ассемблере, но они тщательно изолированы в уровне аппаратных абстракций HAL.


Система Singularity — это микроядро, компиляторы MSIL и множество программно изолированных процессов (SIP)

Ядро содержит типичный для микроядра набор менеджеров, управляющих памятью, переключением процессов, вводом-выводом, безопасностью. К доверенному коду относится и run-time среда — компиляторы в MSIL и машинный код.

Код всех запускаемых в Singularity прикладных программ, сервисов и драйверов является строго верифицируемым.

Любая запускаемая программа или сервис с точки зрения Singularity является SIP — Software Isolated Process (программно изолированный процесс). Благодаря выполненной проверке типобезопасности SIP не нужно держать в «клетке» ограниченного адресного пространства. Он сам гарантирует свою лояльность — то, что будет работать только со строго определёнными объектами и данными, не нарушая целостности системы и других программ. А как же быть с межпроцессным взаимодействием? Без него в многозадачной среде никуда. Для взаимодействия SIP-ов Singularity предлагает очень надёжный механизм каналов, по которым один SIP может передавать другому сообщения и данные. Каналы в Singularity высокоскоростные и неплохо заменяют небезопасный механизм разделения данных в традиционных системах. SIP может общаться и с микроядром через специальный бинарный интерфейс ABI (Application Binary interface), с помощью которого один SIP может контролируемо повлиять на состояние другого SIP.


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

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

Таким образом, упрощённо архитектура Singularity — это: микроядро, написанное на доверенном коде, трансляторы кода MSIL и компиляторы JIT (NGen), также состоящие из доверенного кода, множество SIP на основе верифицированного кода, работающие в едином адресном пространстве, каналы, связывающие SIPы, и интерфейс ABI, связывающий SIP с ядром.

В зависимости от потребностей в процессорном времени конкретного SIP, диспетчер задач Singularity предоставляет один из пяти имеющихся в его распоряжении алгоритмов планирования.

Данные SIPов хранит SIP специального типа — файловая система Boxwood, в которой файлы представлены бинарными деревьями (B-tree).

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

Разработчики Singularity предоставляют прикладным программистам и драйверописателям Singularity RDK, обеспечивающий среду создания и обкатки своих программ, совместимых с Singularity. Программы можно писать на массе совместимых c CLS языков, для которых Singularity поддерживает компиляторы MSIL. К ним относятся C#, F#, Perl и даже COBOL.


Очевидно, что число компиляторов MSIL для разных языков будет увеличиваться с развитием Singularity. А это означает привлечение к системе множества разработчиков. На данный момент пользовательский интерфейс Singularity весьма аскетичен и ограничивается командной строкой.



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

Побратимы Singularity

Архитектурные решения, реализованные в Singularity, родились не на пустом месте. На её архитектуру оказали влияние проекты таких микроядерных архитектур, как L4, Exokernel и SPIN. Однако большинство из них (кроме разве что SPIN, использующей язык Modula-3) создано на основе небезопасного кода и применяют традиционную для современных систем технологию разделения адресных пространств процессов.

Идея проверки кода на типобезопасность, реализованная в Singularity, перекликается с подобными подходами в таких проектах, как JX, JavaOS, KaffeOS (язык Java), Inferno (язык Limbo) и RMoX (язык occam-pi).

Итак, Microsoft Singularity — один из множества проектов, разрабатывающих архитектуру надёжной и безопасной операционной системы или среды исполнения, надстраиваемой над существующими системами, на основе изоляции процессов путём проверки их кода на типобезопасность. Благодаря активному развитию безопасных языков программирования и высокопроизводительных исполняющих сред этот, поначалу чисто теоретический, подход становится всё ближе к реальным коммерческим реализациям. Проекты, подобные Singularity, стараются доказать, что они способны составить конкуренцию архитектуре современных операционных систем и предоставить пользователям надёжную и предсказуемую среду исполнения их программ.


К оглавлению

Загрузка...