- PVSM.RU - https://www.pvsm.ru -
Тему обновления патчей ядра без перезагрузки мы уже рассматривали в статье [1], опубликованной в 2014 году. В ней речь шла о KernelCare — инструменте, разработанном нашими партнёрами из компании Cloud Linux. На момент написания статьи KernelCare был чуть ли не единственным пригодным для полноценного использования инструментом для наложения патчей.
Прошло два с небольшим года — и ситуация изменилась, причём кардинально: начиная с версии 4.0 возможность наложения патчей «на лету» была официально добавлена в ядро.
Инструменты kpatch [2] и kGraft [3], которые в 2014 году находились в «сыром» состоянии, также были существенно усовершенствованы. Kpatch даже был добавлен в официальные репозитории, — например, в Ubuntu 16.04 его уже можно установить с помощью стандартного менеджера пакетов.
А компания Canonical совсем недавно представила сервис Canonical Livepatch Service [4], с помощью которого можно патчить без перезагрузки ядро Ubuntu.
Более подробно о некоторых современных инструментах для добавления патчей мы расскажем в этой статье.
Начнём с очень простого эксперимента. Для этого нам понадобится любой дистрибутив Linux c ядром версии 4.0 или выше (в нашем случае это Ubuntu 16.04; здесь и далее все примеры команд приводятся именно для этого дистрибутива). В новых версиях ядра функция добавления патчей «на лету»(она так и называется — livepatch) включена по умолчанию.
Чтобы проверить, как она работает, нам потребуется, во-первых, установить заголовки ядра:
$ sudo apt-get install linux-headers-$(uname -r)
Далее установим отладочные символы ядра:
#добавляем репозитории
$ codename=$(lsb_release -sc)
$ sudo tee /etc/apt/sources.list.d/ddebs.list << EOF
deb http://ddebs.ubuntu.com/ ${codename} main restricted universe multiverse
deb http://ddebs.ubuntu.com/ ${codename}-security main restricted universe multiverse
deb http://ddebs.ubuntu.com/ ${codename}-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com/ ${codename}-proposed main restricted universe multiverse
EOF
#добавляем ключ
wget -Nq http://ddebs.ubuntu.com/dbgsym-release-key.asc -O- | sudo apt-key add -
#обновляем список пакетов
$ sudo apt-get update
#устанавливаем отладочные символы
$ sudo apt-get install linux-image-$(uname -r)-dbgsym
Далее выполним:
$ sudo apt-get build-dep linux
При выполнении этой команды в Ubuntu 16.04 может быть выдано следующее сообщение об ошибке:
E: You must put some 'source' URIs in your sources.list
Причина ошибки в том, что репозитории deb-src по умолчанию не подключены, а соответствующие строки в файле /etc/apt/sources.list закомментированы. Чтобы мы смогли работать с репозиториями исходных кодов, выполним:
$ sudo sed -i -- 's/#deb-src/deb-src/g' /etc/apt/sources.list && sudo sed -i -- 's/# deb-src/deb-src/g' /etc/apt/sources.list
$ sudo apt-get update
После этого предыдущая команда будет выполняться без ошибок. К эксперименту всё готово, можно начинать:
wget http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/samples/livepatch/livepatch-sample.c
Мы скачали код модуля ядра, который вносит изменения в основной ядерный код и модифицирует вывод команды cat /proc/cmdline. Теперь этот самый модуль нужно собрать. Для этого создадим следующий make-файл:
obj-m +=livepatch-sample.o
KDIR= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.* .c* .t*
Соберём модуль и вставим его в ядро:
$ make
$ insmod livepatch-sample.ko
Посмотрим, что получилось. Выполним:
$ cat /proc/cmdinfo
Вместо стандартной информации о параметрах ядра мы увидим вот такой текст:
this has been live patched
Как видим, патч был успешно применён.
Вся информация о загруженных патчах хранится в директории /sys/kernel/livepatch:
$ ls /sys/kernel/livepatch/
livepatch_sample
Деактивировать патч можно с помощью команды:
$ echo 0 > /sys/kernel_livepatch/livepatch_sample/enabled
Kpatch [2] — инструмент, разработанный компаний Red Hat. Впервые он был представлен широкой пользовательской аудитории [5] в феврале 2016 года. За это время он был значительно усовершенствован: в Ubuntu 16.04 он уже включён в официальные репозитории. Рассмотрим особенности работы с kpatch на практических примерах.
Начнём с установки необходимых зависимостей:
$ sudo apt-get install libelf-dev dpkg-dev
Для полноценной работы с kpatch также желательно установить ccache [6]:
$ sudo apt-get install ccache
$ ccache --max-size=5G
Вот и всё, зависимости установлены. Можно устанавливать kpatch:
$ sudo apt-get install kpatch kpatch-build
В нашем эксперименте мы будем патчить исходники ядра. Клонируем репозиторий с исходным кодом нашей текущей версии Ubuntu:
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-xenial.git
По завершении клонирования скопируем исходники в директорию ubuntu-xenial-kpatch (это нужно, чтобы вносить изменения в исходный код и потом создавать на основе этих изменений патчи):
$ mkdir ubuntu-xenial-kpatch
$ cp -r ubuntu-xenial ubuntu-xenial-kpatch
Откроем файл ubuntu-xenial-kpatch/ubuntu-xenial/fs/proc/version.c и внесём в него следующие изменения:
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/utsname.h>
static int version_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, linux_proc_banner,
"This has been patched!",
utsname()->sysname,
utsname()->release,
utsname()->version);
return 0;
}
Cоздадим патч с помощью команды:
$ diff -u ubuntu-xenial/fs/proc/version.c ubuntu-xenial.kpatch/ubuntu-xenial/proc.version.c > version.patch
Патч представляет собой обычный текстовый файл, в котором перечислены внесённые изменения:
--- ubuntu-xenial/fs/proc/version.c 2016-12-05 10:04:30.126141156 +0300
+++ ubuntu-xenial.kpatch/ubuntu-xenial/fs/proc/version.c 2016-12-05 10:10:35.678461801 +0300
@@ -8,6 +8,7 @@
static int version_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, linux_proc_banner,
+ "This has been patched!",
utsname()->sysname,
utsname()->release,
utsname()->version);
Чтобы добавить патч в ядро, выполним:
$ kpatch-build -t vmlinux --skip-gcc-check version.patch
WARNING: Skipping gcc version matching check (not recommended)
Debian/Ubuntu distribution detected
Downloading the kernel source for 4.4.0-51-generic
Unpacking kernel source
Testing patch file
checking file fs/proc/version.c
Reading special section data
Building original kernel
Building patched kernel
Detecting changed objects
Rebuilding changed objects
Extracting new and modified ELF sections
version.o: changed function: version_proc_show
Building patch module: kpatch-version.ko
SUCCESS
Как видно из только что приведённого вывода, на выходе мы получаем модуль ядра. Чтобы применить патч, нужно просто добавить этот модуль стандартным способом:
sudo insmod kpatch-version.ko
Посмотрим, что получилось в результате:
cat /proc/version
This has been patched! version Linux (buildd@lcy01-08) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) ) 4.4.0-51-generic
Всё работает!
Несколько месяцев назад компания Canonical запустила официальный сервис Canonical LivePatch Service, который позволяет патчить ядро «на лету» при помощи простейших команд. Этот сервис ориентирован в первую очередь на пользователей enterprise-уровня, и поэтому является платным.
Но рядовые пользователи тоже могут оперативно получать все свежие обновления ядра. Для этого нужно зарегистрироваться на Ubuntu One и получить токен [7]. Токен даёт возможность установить на 3 машины программу canonical-livepatch, которая загружает и добавляет патчи.
Посмотрим, как работает Canonical Livepatch Service. Перейдём по ссылке выше, получим токен, а далее выполним:
$ sudo snap install canonical-livepatch
По завершении установки выйдем из системы, затем войдём снова и выполним:
$ sudo canonical-livepatch enable [токен]
Если всё было сделано правильно, мы получим следующее сообщение:
Successfully enabled device. Using machine-token: [токен]
Далее выполним команду:
$ canonical-livepatch status
kernel: 4.4.0-47.68-generic
fully-patched: true
version: "14.1"
Вывод показывает, что сanonical-livepatch работает, и в ядро установлены все последние обновления. Более подробную информацию можно получить, воспользовавшись опцией −−verbose:
$ canonical-livepatch status --verbose
client-version: "6"
machine-id: [id]
machine-token:[token]
architecture: x86_64
cpu-model: Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz
last-check: 2016-12-05T11:56:02.88803394+03:00
boot-time: 2016-11-29T10:48:38+03:00
uptime: 145h18m21s
status:
- kernel: 4.4.0-47.68-generic
running: true
livepatch:
checkState: checked
patchState: applied
version: "14.1"
fixes: |-
* CVE-2016-7425
* CVE-2016-8658
Также информацию об установленных патчах можно получить, заглянув в уже упомянутую выше директорию /sys/kernel/livepatch:
$ ls /sys/kernel/livepatch
kpatch_livepatch_Ubuntu_4_4_0_47_68_generic_14
Kpatch_livepatch_Ubuntu_4_4_0_47_68_generic_14 — это и есть последний загруженный патч. Последние цифры в имени патча (14) совпадают с номером версии, указанным в выводе команды canonical-livepatch status (см. выше).
Убедиться, что новый патч был добавлен, можно и с помощью команды lsmod:
$ lsmod |grep livepatch
kpatch_livepatch_Ubuntu_4_4_0_47_68_generic_14 36864 1
В этой статье мы проделали небольшой отбор инструментов для добавления патчей в ядро Linux. Естественно, что все аспекты темы в рамках одной публикации затронуть невозможно. Если у вас есть замечания и дополнения — добро пожаловать в комментарии.
А если вы хотите изучить тему более глубоко, обратите внимание на следующие ссылки:
Если вы по каким-то причинам не можете оставлять комментарии здесь — добро пожаловать в наш корпоративный блог [11].
Автор: Селектел
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/218303
Ссылки в тексте:
[1] статье: https://habrahabr.ru/company/selectel/blog/225299/
[2] kpatch: https://github.com/dynup/kpatch
[3] kGraft: https://en.wikipedia.org/wiki/KGraft
[4] Canonical Livepatch Service: https://www.ubuntu.com/server/livepatch
[5] представлен широкой пользовательской аудитории: http://rhelblog.redhat.com/2014/02/26/kpatch/
[6] ccache: https://ccache.samba.org/
[7] получить токен: https://auth.livepatch.canonical.com/
[8] https://events.linuxfoundation.org/sites/events/files/slides/kpatch-linuxcon_3.pdf: https://events.linuxfoundation.org/sites/events/files/slides/kpatch-linuxcon_3.pdf
[9] http://events.linuxfoundation.org/sites/events/files/slides/kGraft.pdf: http://events.linuxfoundation.org/sites/events/files/slides/kGraft.pdf
[10] http://www.slideshare.net/UdoSeidel/kpatchkgraft: http://www.slideshare.net/UdoSeidel/kpatchkgraft
[11] наш корпоративный блог: https://blog.selectel.ru/kak-propatchit-yadro-bez-perezagruzki-obzor-sovremennyx-instrumentov/
[12] Источник: https://habrahabr.ru/post/317034/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.