Содержание статьи
Одна из удобных особенностей *nix-систем — компьютер не нужно перезагружать после установки, удаления и обновления программ. Именно поэтому серверы в сети могут спокойно работать годами, хотя ПO постоянно обновляется администраторами. Единственное исключение из правила представляет обновление ядра ОС: здесь уже без перезагрузки точно не обойтись. Хотя в Linux это уже тоже не обязательно.
Проекты
В самой перезагрузке в общем ничего плохого нет. Если это домашний ПК или отдельный VDS, то минута-другая в ночное время вряд ли будет проблемой для пользователей. К тому же некоторые дистрибутивы из коробки поддерживают механизм kexec (появился в Linux с версии 2.6.27), позволяющий загрузить новое ядро из текущего окружения без физической перезагрузки сервера, что обеспечивает минимальный простой.
Другое дело, что во время повальной виртуализации на физическом сервере могут работать десятки виртуальных машин — в этом случае перезагрузка очень даже проблематична. А еще есть системы реального времени, различные симуляторы, работающие месяцами, и многое другое. Обновление ядра Linux на лету для таких систем, критичных ко времени простоя, сегодня очень востребовано, и поэтому неудивительно, что в разное время стартовало несколько проектов, относящихся к классу dynamic software updating: Ksplice от Oracle, KernelCare от CloudLinux, kGraft от SUSE, kpatch от Red Hat и livepatch. Все они похожи по общему принципу работы, но отличаются в деталях реализации.
Ksplice
Самый старый проект. Начат приблизительно в 2006 году как магистерская диссертация в MIT одного из пяти разработчиков Джеффа Арнольда (Jeff Arnold). Идея создать технологию, позволяющую безопасно обновлять ОС без перезагрузки, возникла после неудачного обновления серверов MIT, когда процедура готовилась неделю, но в итоге из-за ошибки оказалась проблемной. Проведенный разработчиками анализ патчей безопасности за период с 2005 по 2008 год показал, что в 87% случаев патч только добавлял проверку некоторых параметров, а поэтому такие исправления можно применять без остановки работы. Это и послужило толчком к старту проекта.
Изначально поддерживалась только x86/x64 Linux, но, по заявлениям разработчиков, код написан таким образом, что его очень легко можно перенести на Mac и Win (хотя этого до сих пор никто не сделал). В 2009 году проект привлек внимание инвесторов, получив премию в 100 тысяч долларов. В это же время разработчики организовали компанию Ksplice, Inc.
Ksplice первоначально был ограничен патчами, не использовавшими семантические изменения в структурах данных, что присуще многим (но не всем) патчам безопасности. Сегодня возможно применить Ksplice и при изменении семантики, но в автоматическом режиме генерировать такие патчи невозможно, поскольку это потребует дать Ksplice дополнительные инструкции. А вот четких указаний, как составить такие инструкции, у разработчиков нет, да и для этого требуются специфические знания, поэтому вряд ли сисадмин или пользователь будет этим заниматься. Кроме того, сборку патча нужно производить ровно в таком же окружении, как у используемого ядра. Разные версии GCC генерируют разный код, предсказать, как будет выглядеть бинарный патч в таком случае, невозможно. Именно поэтому разработчики основой технологии считали специальный сервис обновления Ksplice Uptrack, упрощавший все операции, так как все необходимые патчи готовились и проверялись на работоспособность специальной командой.
Первым дистрибутивом, официально поддерживающим технологию, стал Ubuntu, пользователи которого при помощи Ksplice Uptrack могли устанавливать критические обновления ядра в дистрибутиве Ubuntu 9.04 без перезагрузки и остановки работы системы. Позже к ним присоединилась и Fedora Linux, коммерческую поддержку Ksplice получили RHEL, CentOS, CloudLinux, Ubuntu Server и Debian GNU/Linux.
В 2011 году Ksplice, Inc. была выкуплена Oracle, и теперь это основной компонент всех Oracle Linux. Компания сразу закрыла доступ к разработке. Сегодня можно скачать и свободно использовать для своих сборок лишь старую версию 0.9.9.1. Поддержка для RHEL была прекращена, но остался доступным 30-дневный пробный период. С 2015 года бесплатная поддержка доступна для Ubuntu Desktop (а настоящее время 12.04, 14.04, 16.04, 16.10) и Fedora 23 и 24. Чтобы начать работать, достаточно установить пакет с сайта разработчика. Метод получения обновлений не изменялся — они по-прежнему загружаются из стандартных репозиториев Ubuntu, а затем транслируются в представление, подходящее для использования в Ksplice.
Ksplice универсален, так как не требует специальной модификации ядра и теоретически может работать с любым. Необходимо лишь установить пакет, содержащий модуль ядра и пользовательские утилиты, а также оформить файл изменений, который будет спроецирован на работающее ядро. Обновление ядра производится в два этапа. На первом шаге специальная утилита ksplice-create собирает ядро, используя исходные тексты и патч к ядру, и сравнивает получившийся образ со старым ядром. В результате генерируется модуль ядра, содержащий код измененных функций.
На втором этапе модуль ядра ksplice.ko получает бинарный патч и после анализа необходимых изменений меняет адреса текущих функций ядра на адреса новых функций, указанных в патче, передавая им управление, плюс изменяются данные и структуры в памяти. Для этого на какой-то миг замораживается выполнение всех программ и проверяется, что текущие процессы не используют функции, требующие изменения. Затем выполнение процессов возобновляется. Время заморозки системы зависит от количества изменений, хотя оно все равно измеряется миллисекундами и точно гораздо меньше, чем перезагрузка системы, и главное, что фактически работа сервера и программ не прерывается.
Откат, при необходимости, делается в таком же порядке (утилитой ksplice-undo). Если модуль содержит патч для не загруженного в данный момент объекта, он не делает ничего, информация обновится, как только он будет запущен. Некоторые основные системные функции, постоянно используемые ядром, обновить при помощи Ksplice не получится.
Ksplice изначально позволял применять исправления только к ядру Linux, но новые возможности Ksplice, реализованные в Oracle Linux 7 и чуть позже для 6, позволяют вносить изменения в разделяемые библиотеки без необходимости перезапуска связанных с ними работающих процессов. Применение исправлений также производится на лету и позволяет избавиться от необходимости планового перезапуска длительно работающих приложений. На сегодня user space возможность обновления реализована для glibc и OpenSSL.
kGraft, kpatch, KernelCare
Самый большой недостаток Ksplice — это закрытость проекта. Привязанность к конкретному дистрибутиву делает его неинтересным. Именно поэтому практически сразу, как стала ясна политика Oracle, основные игроки рынка начали свои разработки, которые в общем похожи на Ksplice и отличаются только реализацией (процессом подготовки патчей и их применением). Поэтому буквально пару слов о каждом.
kGraft изначально позиционируется как open source проект. Прототип был представлен общественности компанией SUSE в январе 2014-го и выпущен в марте 2014 года. Компоненты, работающие на уровне ядра, открыты под лицензией GPLv2, а утилиты, позволяющие создавать патчи к ядру, — под GPLv3. Чуть позже для SLES 12 стала доступна новая функция Live Patching. В апреле 2014 года проект был предложен для добавления в основную ветку ядра Linux и после небольших доработок включен в ядро Linux 4.0, выпущенное в апреле 2015 года. Но реализация механизмов согласования на уровне функций, необходимых для безопасных переходов между исходными и исправленными версиями функций, была отложена, поскольку остались нерешенными несколько моментов. Для проверки объектных файлов во время компиляции ядра и обеспечения сохранности стека вызовов разработана дополнительная утилита stacktool.
В своей работе kGraft базируется на уже доступных в ядре технологиях: трассировщике ftrace (Function Tracer), используемом для подмены функций, работе с памятью через mcount, технике патчинга INT3/IPI-NMI, RCU (read-copy update) модели обновления кода, не требующей остановки ядра. Патч формируется непосредственно на основе анализа исходных текстов, без манипуляций с объектным кодом. Сгенерированный модуль загружается в ядро штатными средствами, как и любой другой модуль ядра, после чего вносит изменения в ядро без прерывания работы системы.
Основное отличие от Ksplice в том, что kGraft не останавливает процессы. Вместо этого он заменяет старые функции новыми постепенно, дожидаясь прерывания при выходе из kernel space, поэтому в какой-то момент в системе работают обе версии функций. Чтобы не допустить возможных рассогласований при работе обеих версий со структурами данных, используются дополнительные проверки.
Red Hat анонсировала свой kpatch буквально через месяц после появления информации о kGraft. Он похож на Ksplice: при применении патча останавливаются все процессы и функции подменяются новыми. Такой подход разработчики Red Hat считают более безопасным и простым в реализации. Для подмены функции используется ftrace. Выпущен под GPLv2. Kpatch одновременно с kGraft также предложен в ядро Linux, в общем с теми же результатами.
Технология входит в состав RHEL 7 и лежит в основе ReadyKernel, дистрибутива Virtuozzo Linux 7 (ранее в Virtuozzo использовали KernelCare, о котором ниже). Последний патч, например, устраняет проблему безопасности с высоким приоритетом CVE-2016-5195 MAP_PRIVATE COW, позволяющую локальному пользователю повысить свои привилегии. Это, кстати, как раз тот случай, когда патч действительно необходим и систему бы пришлось перезагружать.
Следующей за kGraft и kpatch анонсировала свой сервис KernelCare, позволяющий обновлять ядро без перезагрузки, компания CloudLinux. Бета-версия появилась в марте 2014 года, а коммерческое использование началось уже с мая. Модуль ядра выпускается под GPLv2, остальные компоненты доступны только по лицензии в двоичном формате. Патч содержит дополнительную информацию обо всех изменениях и о том, как их применять, позволяет модифицировать уязвимые функции и структуры данных.
Агент KernelCare, установленный на сервере, проверяет наличие новых патчей в репозитории, загружает их, после чего модуль ядра их применяет. Принцип схож с Ksplice, то есть при переключении на новые функции процессы приостанавливаются. Патчи KernelCare предоставляются по подписке для CentOS/RHEL 5–7, CloudLinux 5–7, Ubuntu 14.04/16.04, Debian 6, 7 и системы виртуализации OpenVZ, KVM, Virtuozzo и других.
...и kGraft + kpatch
Две практически одинаковые реализации одной проблемы в ядре — это многовато. Поэтому, столкнувшись с рядом проблем, разработчики kpatch и kGraft решили объединить свои усилия в новом универсальном проекте, названном livepatch, особенность которого — возможность использования патчей обоих типов. Разработки kpatch и kGraft фактически забросили, в Git ядра Linux последние изменения зафиксированы полгода назад. Сам livepatch при этом предоставляет лишь базовый интерфейс для регистрации и активации патчей в ядре и реализован в форме управляющего модуля livepatch.ko.
По аналогии с другими проектами в livepatch есть замены функций в ядре целиком и перенаправления на новую функцию при помощи штатной подсистемы ftrace. Патч оформляется в виде модуля ядра, который выполняет необходимую подстановку кода функций. Из областей, которые еще требуют доработки, отмечается обеспечение целостности системы при применении патча. Для работы livepatch потребуется ядро версии 4.4 и выше (поэтому старые дистрибутивы не поддерживаются).
В октябре этого года технология livepatches стала официально доступной пользователям Ubuntu 16.04, обеспечивая установку патчей Ubuntu Security Notices (USN) и CVE. Пока только для x86_64, но в будущем планируется внедрить поддержку POWER8, s390x и ARM64. x86-системы непопулярны на серверах и не получат такой возможности, как и релизы без долгосрочной поддержки тоже не смогут работать с livepatch, поскольку они тестовые и не ориентированы на бесперебойно работающие системы. Обычные пользователи без платной подписки UA могут получать обновления только на три компьютера. Однако стоит учесть, что патчи будут тестироваться в первую очередь как раз на тех, кто получил обновления бесплатно, а пользователи с платной техподдержкой получат обновления только после тщательного тестирования.
Исходный код модулей livepatch доступен на git.launchpad.net, код клиента canonical-livepatch — коммерческое ПО и часть продукта по управлению системами Landscape. Использование livepatch в Ubuntu выглядит очень простым. Регистрируемся на ubuntu.com/livepatch и получаем токен.
Устанавливаем snap-пакет:
$ sudo snap install canonical-livepatch
Включаем livepatch:
$ sudo canonical-livepatch enable 043eca…….560b04da3
Это все. Теперь демон будет каждые четыре часа проверять наличие обновлений и устанавливать. Статус можно посмотреть, введя
$ sudo canonical-livepatch status --verbose
Чтобы временно отключить canonical-livepatch, достаточно просто запретить установку новых модулей:
$ echo 1 | sudo tee /proc/sys/kernel/modules_disabled
Вывод
Домашнему пользователю новая технология вряд ли будет интересна, ведь перезагрузка компьютера для установки полноценного обновления — это не проблема. А отсутствие инструментов не позволяет покопаться во внутренностях даже любопытным. А вот владельцу интернет-магазина, размещенного на VDS, совсем игнорировать ее не стоит. Тем более что использовать livepatch, как и все остальные решения обзора, очень просто.