Стандартный подход к созданию ответственных приложений для бизнеса и критически важной инфраструктуры — это подход «снизу вверх», когда начинают с надежного фундамента, выбирая аппаратную архитектуру и системное ПО, а поверх него разрабатывают приложение и обеспечивают его безопасное выполнение. Убедиться в надежности микропрограммного и системного ПО (ОС, гипервизор, диспетчер ресурсов и т. д.) помогают формальные методы доказательства корректности микроядерной системы [1].

Под управлением Linux, операционной системы с монолитным ядром, сегодня работают многие современные системы и устройства: облачные инфраструктуры, смартфоны, автомобильные компьютеры и другие устройства, критичные к безопасности встроенного программного обеспечения [2]. Однако доказать корректность работы ОС Linux современными формальными методами практически нереально — если в самом микроядре насчитывается лишь 10 тыс. строк кода, то для ядра Linux пришлось бы верифицировать более 20 млн строк. Более того, опыт показал, что Linux всегда содержит исправимые ошибки, так что формальное доказательство корректности в любом случае даст отрицательный результат.

Статический анализ репозиториев открытого кода обычно выявляет в среднем 0,61 дефекта на тысячу строк, и, несмотря на постоянно проводимые исправления, число неустраненных ошибок в ядре остается на уровне примерно 5 тыс. [3]; правда, не все они могут использоваться для проведения атак. Другое исследование показало, что за последние пять лет в Linux было исправлено около 500 ошибок, связанных с нарушением безопасности, и они присутствовали в ядре в течение пяти лет. В проприетарном коде плотность дефектов несколько выше, чем в открытых проектах, а значит, коммерческое ПО тоже не застраховано от наличия уязвимостей.

Защита и безопасность приложений

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

Если при создании драйверов разработчики полагаются на надежность операционной системы, то при написании критически важных приложений они доверяют только подконтрольным им  компонентам.  При выполнении ответственного приложения в облаке системные сервисы и ОС могут находиться под административным контролем третьей стороны. Современные расширения набора инструкций процессора, в частности Intel Software Guard Extensions (SGX), позволяют приложениям сохранять состояния в защищенных областях памяти — «анклавах», доступа к которым нет даже у самого привилегированного кода, включая ОС и гипервизор. Однако SGX более чем на порядок замедляет выполнение своих команд, если рабочий срез данных анклава не помещается в расширенный кэш страниц SGX, размер которого составляет сейчас лишь около 90 Мбайт. Поэтому данные состояния для анклава нужно ограничивать в объеме — не только для минимизации базы доверенных вычислений (совокупности элементов, влияющих на защищенность системы), но и для того, чтобы сохранить...

Это не вся статья. Полная версия доступна только подписчикам журнала. Пожалуйста, авторизуйтесь либо оформите подписку.
Купить номер с этой статьей в PDF