Как пропатчить ядро без перезагрузки: обзор современных инструментов
Тему обновления патчей ядра без перезагрузки мы уже рассматривали в статье, опубликованной в 2014 году. В ней речь шла о KernelCare — инструменте, разработанном нашими партнёрами из компании Cloud Linux. На момент написания статьи KernelCare был чуть ли не единственным пригодным для полноценного использования инструментом для наложения патчей.
Прошло два с небольшим года — и ситуация изменилась, причём кардинально: начиная с версии 4.0 возможность наложения патчей «на лету» была официально добавлена в ядро.
Инструменты kpatch и kGraft , которые в 2014 году находились в «сыром» состоянии, также были существенно усовершенствованы. Kpatch даже был добавлен в официальные репозитории, — например, в Ubuntu 16.04 его уже можно установить с помощью стандартного менеджера пакетов.
А компания Canonical совсем недавно представила сервис Canonical Livepatch Service , с помощью которого можно патчить без перезагрузки ядро Ubuntu.
Более подробно о современных инструментах для добавления патчей мы расскажем в этой статье.
Простейший пример: livepatch
Начнём с очень простого эксперимента. Для этого нам понадобится любой дистрибутив Linux c ядром версии 4.0 или выше (в нашем случае это Ubuntu 16.04; здесь и далее все примеры команд приводятся именно для этого дистрибутива). В новых версиях ядра функция добавления патчей «на лету»(она так и называется — livepatch) включена по умолчанию.
Чтобы проверить, как она работает, нам потребуется, во-первых, установить заголовки ядра:
Далее установим отладочные символы ядра:
К эксперименту всё готово, можно начинать. Выполним следующую команду:
Мы скачали исходный код модуля ядра, который вносит изменения в основной ядерный код и модифицирует вывод команды cat /proc/cmdline. Теперь этот самый модуль нужно собрать. Для этого создадим следующий make-файл:
Соберём модуль и вставим его в ядро:
Посмотрим, что получилось. Выполним:
Вместо стандартной информации о параметрах ядра мы увидим вот такой текст:
Как видим, патч был успешно применён.
Вся информация о загруженных патчах хранится в директории /sys/kernel/livepatch:
Деактивировать патч можно с помощью команды:
Kpatch
Kpatch — инструмент, разработанный компаний Red Hat. Впервые он был представлен широкой пользовательской аудитории в феврале 2016 года. За это время он был значительно усовершенствован: в Ubuntu 16.04 он уже включён в официальные репозитории. Рассмотрим особенности работы с kpatch на практических примерах.
Начнём с установки необходимых зависимостей:
Для полноценной работы с kpatch также желательно установить ccache :
Вот и всё, зависимости установлены. Можно устанавливать kpatch:
В нашем эксперименте мы будем патчить исходники ядра. Клонируем репозиторий с исходным кодом нашей текущей версии Ubuntu:
По завершении клонирования скопируем исходники в директорию ubuntu-xenial-kpatch (это нужно, чтобы вносить изменения в исходный код и потом создавать на основе этих изменений патчи):
Откроем файл ubuntu-xenial-kpatch/ubuntu-xenial/fs/proc/version.c и внесём в него следующие изменения:
Cоздадим патч с помощью команды:
Патч представляет собой обычный текстовый файл, в котором перечислены внесённые изменения:
Чтобы добавить патч в ядро, выполним:
Как видно из только что приведённого вывода, на выходе мы получаем модуль ядра. Чтобы применить патч, нужно просто добавить этот модуль стандартным способом:
Посмотрим, что получилось в результате:
Canonical Livepatch Service
Несколько месяцев назад компания Canonical запустила официальный сервис Canonical LivePatch Service, который позволяет патчить ядро «на лету» при помощи простейших команд. Этот сервис ориентирован в первую очередь на пользователей enterprise-уровня, и поэтому является платным.
Но рядовые пользователи тоже могут оперативно получать все свежие обновления ядра. Для этого нужно зарегистрироваться на Ubuntu One и получить токен . Токен даёт возможность установить на 3 машины программу canonical-livepatch, которая загружает и добавляет патчи.
Посмотрим, как работает Canonical Livepatch Service. Перейдём по ссылке выше, получим токен, а далее выполним:
По завершении установки выйдем из системы, затем войдём снова и выполним:
Если всё было сделано правильно, мы получим следующее сообщение:
Далее выполним команду:
Вывод показывает, что сanonical-livepatch работает, и в ядро установлены все последние обновления. Более подробную информацию можно получить, воспользовавшись опцией −−verbose:
Также информацию об установленных патчах можно получить, заглянув в уже упомянутую выше директорию /sys/kernel/livepatch:
Kpatch_livepatch_Ubuntu_4_4_0_47_68_generic_14 — это и есть последний загруженный патч. Последние цифры в имени патча (14) совпадают с номером версии, указанным в выводе команды canonical-livepatch status (см. выше).
Убедиться, что новый патч был добавлен, можно и с помощью команды lsmod:
Заключение
В этой статье мы проделали небольшой отбор инструментов для добавления патчей в ядро Linux. Естественно, что все аспекты темы в рамках одной публикации затронуть невозможно. Если у вас есть замечания и дополнения — добро пожаловать в комментарии.
А если вы хотите изучить тему более глубоко, обратите внимание на следующие ссылки:
Источник
Создание патча для ядра
Недавно создавал тему, в которой указывал на проблемы с радеоном (прошу, не надо холиваров!). Единственное решение, как я понял, это патч для ядра, ибо из исходников собирать не буду. Т.е. к стандартному арчелинуху добавить патч. Как его создать? Прикладываю ссылки на багтрекер и (наверное) содержимое патча. Сам я никогда с патчами дел не имел, мой первый раз. Спасибо.
Только конпелять. Или ждать когда оно будет в апстриме и придёт с обновлениями.
патч подразумевает сборку ядра из исходников, без вариантов
это патч для ядра, ибо из исходников собирать не буду
Это как?
Патч применяется к /drivers/gpu/drm/radeon/si_dpm.c
Это модуль ядра. Можно выкачать и собрать только его, а потом использовать insmod.
Оу, я ничего не понял. Можно поподробнее?
Окей. А как найти это самый модуль, как писал анон? Скачать сорцы пакменом/как-там-правильно-их-комиуниздить или есть тулзы для выкачивания модулей?
Выкачиваете исходники ядра, переходите в директорию drivers/gpu/drm/radeon, применяете патч:
Не понял на этапе патчинга. Его же ещё создать нужно, не? Или достаточно отредактировать файлы и собрать модуль?
Скачать сорцы пакменом/как-там-правильно-их-комиуниздить или есть тулзы для выкачивания модулей?
В арче вроде есть вот это. Либо можно с гитхаба взять сорцы.
Можно поправить файл руками. Либо как написано, но подразумевается, что в patch.diff должно быть
И? Пакет содержит сорцы?
Дошло, спасибо! Кстати, с автоинжектом. Можно просто добавить в modules-load.d файл с чем-то типа «/home/maxik/modulename(.ko)»? И нужно будет блэклистить радеон?
Kernel modules can be explicitly loaded during boot and are configured as a static list in files under /etc/modules-load.d/.
Наверное этого будет достаточно. Если я правильно понимаю, что такое блэклист, он здесь не нужен. У меня пробелы в знаниях систем-ди. Лучше спросить тех, кто его использует.
Насчёт блэка. А не нужен-ли он для блока оригинала? Вроде патченный модуль будет дублем, не? Система съест оба и будет былинный отказ.
Поверь, собрать ядро целиком проще, чем разбираться с подменой существующего модуля.
А не нужен-ли он для блока оригинала?
Он должен замениться тем, что Вы соберёте. Не вижу смысла иметь два модуля. Если выполнить make install, то собранный kernel object должен установиться вместо старого куда-нибудь в /sys/module/.
При загрузке ругнётся, что функции с теми же именами уже экспортированы и другую копию загружать не станет.
Судя по докам арча, сраться придётся не с ядром и компиляцией (это изи), а с системой на скрасноглазженом ядре 🙂
Спасибо, сэкономили мне кучу потерянного времени на трахание (неохлаждённое) с системой 🙂 С утра буду красноглазить.
Лучше поглядеть в доках, как оборачивать собранное ядро в пакет твоего дистрибутива. Во всех крупных есть свои инструменты для этого. (Кроме слаки ☺). А пакет он и есть пакет. Захотел — удалил.
Патч минимальный, проблем вызвать не должен.
Так не в этом дело, дело в атомной ё*ле с системой, модулями и прочим говном. Серьёзно, арч вики заполнен фразами «If you have a custom built kernel. ». Понимаю, что патч минимальный, но мне будет комфортнее каждый раз пересобирать модуль, или создать скрипт длчя этого 🙂
Ох ты ж. Всё, спать пора. Бред пишу. make install не сработает, нет таргета install в мейкфайле. Нужно make modules_install от корня, где исходники ядра (/usr/src/linux). В /sys/module модули попадают уже после инициализации. Лежат вроде в /lib/modules. Не суть важно. Послушай гентушника и сделай наоборот, короче.
«Custom built kernel» почти всегда означает «ядро с большими патчами и правками, несовместимое по ABI со стандартным.
В твоём случае ты выкачиваешь PKGBUILD стандартного, стокового ядра ( yaourt -G linux ), добавляешь свой патч в PKGBUILD и собираешь с заменой стандартного пакета linux. Дальше система ведёт себя так, как будто это стандартное ядро. Просто каждую версию придётся заново собирать.
Никогда не возился с собственнособранными ядрами в Archlinux. Но в Debian нет проблем с ядрами, собранными через make-kpkg . Вряд ли они будут в Archlinux.
Сюрпризы были при сборке deb-пакет через make deb-pkg , то есть скриптами самого ядра. Вроде, какая-то бяка с ссылками source и build, подробностей не вспомню.
Так, окей. Можно по порядку — что мне делать? Я так понял, что я топаю в /usr/src/linux, патчу модуль, make «что-то-лень-писать», настраиваю модулс-лоад и т.п.,конфигурация бутлоадера, ребут?
Выше арчеводы пишут, что проще будет всё ядро собрать с этим патчем, а не только один модуль. Ядро собирается через make menuconfig. Только там модули надо повключать нужные. Есть в арче аналог genkernel?
Звучит заманчиво. 1) Bfq и bfs считаются глобальными? Да/нет?
2) Можно, пожалуйста, подробную инструкциб по сборке йогуртом?
а кстати, в ядре же вроде есть live patching, такое в нём можно делать?
Да, фишка то-ли 4.0, то-ли 4.1.
BFQ и BFS — да. Они много чего изменяют.
Йогурт — не сборщик. Йогурт — обёртка над кучей других тулз. Здесь он нужен ровно для того, чтобы получить тарболл (архив) со скриптом сборки (PKGBUILD). Получив его (он автоматически распаковывается в текущий каталог), ты делаешь следующее:
- идёшь в подкаталог linux
- кладёшь в него свой патч (патчи)
- открываешь файл PKGBUILD любым текстовым редактором
- в массив source вписываешь имена патчей через пробел или перевод строки
- в функцию prepare() вписываешь команды патчинга (рядом с уже имеющимися) — patch -Np1 -i «$
/имя-файла-патча» - сохраняешь файл
- находясь в каталоге с PKGBUILD и патчами, делаешь команду updpkgsums
- там же делаешь (от имени пользователя, не от рута) makepkg -s
- идёшь пить чай или гулять (стоковое ядро собирается долго или очень долго, в зависимости от мощности железа)
- наконец, там же делаешь sudo pacman -U linux<,-headers>*.pkg.tar
Спасибо! 8320фх 120сек собирает, вроде 🙂 Кстати, а не проще makepkg -sri?
Стоковое ядро, со всеми включенными опциями — 2 минуты? У меня i7-4700MQ собирает его полчаса минимум (а процессор едва ли не флагманский).
С флагом -i , конечно, проще. Я хотел явно описать все шаги, чтобы не создавалось ощущения «магии».
в массив source вписываешь имена патчей через пробел или перевод строки
И как прописывать? Просто добавить строчку
? Я ничего в этом не понимаю 🙂
Эхх, ошибка при красноглазинге :С
[maxik@m-Arch linux]$ ls change-default-console-loglevel.patch linux-4.1.tar.sign linux.preset patch.diff config linux-4.1.tar.xz patch-4.1.6.sign PKGBUILD config.x86_64 linux.install patch-4.1.6.xz [maxik@m-Arch linux]$ nano PKGBUILD [maxik@m-Arch linux]$ makepkg -sri ==> Сборка пакета: linux 4.1.6-1 (Ср авг 26 10:20:47 UTC 2015) ==> Проверяю необходимые для запуска зависимости. ==> Проверяю необходимые для сборки зависимости. ==> Установка недостающих зависимостей. [sudo] пароль для maxik: разрешение зависимостей. проверка конфликтов.
Пакеты (1) xmlto-0.0.26-1
Будет загружено: 0,02 MiB Будет установлено: 0,07 MiB
:: Приступить к установке? [Y/n] y :: Получение пакетов . xmlto-0.0.26-1-x86_64 22,9 KiB 246K/s 00:00 [############################] 100% (1/1) проверка ключей [############################] 100% (1/1) проверяется целостность пакета [############################] 100% (1/1) загрузка файлов пакетов [############################] 100% (1/1) проверка конфликтов файлов [############################] 100% (1/1) проверяется доступное место [############################] 100% (1/1) установка xmlto [############################] 100% ==> Получение исходных файлов. -> Найден linux-4.1.tar.xz -> Найден linux-4.1.tar.sign -> Найден patch-4.1.6.xz -> Найден patch-4.1.6.sign -> Найден config -> Найден config.x86_64 -> Найден linux.preset -> Найден patch.diff -> Найден change-default-console-loglevel.patch ==> Проверка исходных файлов с помощью sha256sums. linux-4.1.tar.xz . Готово linux-4.1.tar.sign . Пропущен patch-4.1.6.xz . Готово patch-4.1.6.sign . Пропущен config . Готово config.x86_64 . Готово linux.preset . Готово patch.diff . Готово change-default-console-loglevel.patch . Готово ==> Проверка подписей исходных файлов с помощью gpg. linux-4.1.tar . СБОЙ (неизвестный открытый ключ 79BE3E4300411886) patch-4.1.6 . СБОЙ (неизвестный открытый ключ 38DBBDC86092693E) ==> ОШИБКА: Одна или более PGP подписей не может быть проверена! ==> Removing installed dependencies. проверка зависимостей.
Пакеты (1) xmlto-0.0.26-1
Будет освобождено: 0,07 MiB
:: Хотите удалить эти пакеты? [Y/n] y (1/1) удаление xmlto [############################] 100% [maxik@m-Arch linux]$
Источник