Ядро
Содержание
- 1 Введение
- 2 Пакеты с ядром
- 3 Политика обновлений ядра
- 4 Сторонние проприетарные модули ядра
- 5 Подписывание сторонних модулей ядра
- 5.1 Описание механизма подписи модулей ядра
- 5.2 Формулировка проблемы подписывания сторонних модулей ядра
- 5.3 Механизм подписывания сторонних модулей ядра
- 5.4 Действия получающего ключ разработчика стороннего ПО
- 5.5 Действия сотрудников Росы по подписыванию ключа
- 5.6 Подписывание модуля ядра
- 5.7 Упаковка модуля ядра с публичным ключом
Введение
Эта статья описывает политику упаковки и сопровождения официальных ядер Linux в дистрибутивах ROSA Fresh/Chrome платформы rosa2021.1
.
Пакеты с ядром
Исходники пакетов с ядрамя находятся здесь:
Каждое ядро собирается в отдельный пакет, в название которого включается:
- flavour — разновидность ядра; в официальный репозиторий собираются ядра generic, а сообществом делаются сборки, например, xanmod
- мажорная версия ядра, например, 5.10
Примеры названий пакетов с ядрами:
- kernel-5.10-generic
- kernel-5.15-generic
Примеры называний пакетов с заголовочными файлами и исходниками ядра:
- kernel-5.10-generic-devel
- kernel-5.15-generic-devel
Пример пути к модулям ядра: /lib/modules/5.15.67-generic-1rosa2021.1-x86_64
Пример uname ядра: 5.15.67-generic-1rosa2021.1-x86_64
Пакетный менеджер dnf обеспечивает одновременную установку нескольких (по умолчанию — трех) минорных версий ядра несмотря на одинаковые названия пакетов:
$ dnf config-manager --dump | grep installonly installonly_limit = 3 installonlypkgs = kernel, kernel-PAE, installonlypkg(kernel), installonlypkg(kernel-module), installonlypkg(vm), multiversion(kernel) $ rpm -q --whatprovides 'installonlypkg(kernel)' <...> kernel-5.15-generic-5.15.53-1.x86_64 kernel-5.15-generic-5.15.65-1.x86_64 kernel-5.15-generic-5.15.67-1.x86_64
Политика обновлений ядра
Используются официальные релизы выбранной ветки ядра (например, 5.10, 5.15) с kernel.org. По мере выхода новых минорных версий производится обновление пакета с ядром, которые проходят стандартное для всех обновлений тестирование. Задачи как можно быстрее обновлять пакет при выходе новой версии ядра не стоит. Основной упор делается на обеспечение стабильной работы. При выходе исправлений уязвимостей обновления производятся быстрее.
Сторонние проприетарные модули ядра
Существует несколько способов поставки сторонних модулей ядра:
- сборка модулей ядра во время сборки ядра и поставка пользователю бинарных (уже собранных) модулей
- использование dkms для сборки модуля ядра из исходников на стороне клиента для каждого релиза ядра
- использование бинарных модулей ядра
Первые 2 способа не вызывают вопросов и требуют наличия исходников, но некоторые разработчики модулей ядра не хотят поставлять их в виде исходников. У сопровождающих пакета с ядром получился такой выбор:
- либо разработчики этих сторонних модулей ядра будут поставлять модули для конкретных сборок дистрибутивного ядра, поставляя в своем ПО файлы с путем вида /lib/modules/5.15.67-generic-1rosa2021.1-x86_64/kernel/*.ko и тем самым вынуждают пользователей нашего дистрибутива не обновлять ядро, лишая и нас, и пользователя возможности поставлять исправления работы и уязвимостей,
- либо разработчики этих сторонних модулей кладут свои модули в специальную папку, которая не содержит в пути к себе конкретную версию ядра, а наши ядра пытаются подгрузить модули из нее, но есть опасность, что ABI ядра, с которым был собран модуль, и ABI ядра, в которое подгружается модуль, не совпадут в части используемых модулем ABI
Второе представляется меньшим злом. Мы не гарантируем стабильность ABI. По мере появления сторонних модулей от технологических партнеров, возможно, будет проводиться какой-то контроль ABI исходя из используемых ими интерфейсов. Ядро собрано с CONFIG_MODVERSIONS=y, при загрузке модулей ядра не проверяется соответствие исходного и текущего ядер, а сверяются хеш-суммы прототипов используемых функций ABI в загружаемом модуле и в текущем ядре, которые должны совпадать для загрузки модуля.
В пакетах с ядром есть симлинк /lib/modules/5.15.67-generic-1rosa2021.1-x86_64/zzz-5.15-rosa-flow-abi[1] на /lib/modules/5.15-rosa-flow-abi. Таким образом, сторонние модули ядра, лежащие в /lib/modules/5.15-rosa-flow-abi, будут подгружаться всеми ядрами 5.15.х в дистрибутивах ROSA Fresh/Chrome. Разработчикам бинарных модулей, которые не готовы поставлять их в виде исходных текстов, рекомендуется класть их в /lib/modules/5.15-rosa-flow-abi.
Каталог /lib/modules/5.15-rosa-flow-abi принадлежит пакету kernel-5.15-rosa-flow-abi, который содержит только ее.
Рекомендуем разработчикам сторонних модулей поставлять связываемую с ядром часть в виде исходников, как Nvidia.
Подписывание сторонних модулей ядра
Описание механизма подписи модулей ядра
В ОС РОСА (далее — Роса) имеется механизм проверки валидности подписей модулей ядра.
При сборке ядра создается ключевая пара (далее — «рандомный ключ»), закрытым ключом подписываются все входящие в состав ядра модули, а открытый ключ встраивается в ядро. Закрытая часть этой ключевой пары нигде не сохраняется.
Также в ядро встраиваются несколько дополнительных открытых ключей, закрытые части которых хранятся у Росы (далее — «дополнительные ключи»).
При загрузке модуля ядра выполняется проверка валидности его подписи. Если модуль подписан одним из ключей, открытая часть которых встроена в ядро, а подпись валидна, то проверка подписи модуля считается пройденной успешно.
В ОС ROSA Fresh/Хром по умолчанию разрешена загрузка неподписанных модулей ядра, а для ее запрета необходимо добавить в cmdline ядра: `module.sig_enforce=1`.
В ОС ROSA Никель по умолчанию запрещена загрузка неподписанных модулей ядра, а для ее разрешения необходимо добавить в cmdline ядра: `module.sig_enforce=0`.
Формулировка проблемы подписывания сторонних модулей ядра
Из предыдущего раздела следует, что проверка подписи модуля ядра может быть проведена успешно только в следующих случаях:
- модуль был собран и подписан во время сборки ядра рандомным ключом,
- модуль был подписан одним из дополнительных ключей.
Сторонний модуль с непубличным исходным кодом не может быть собран и подписан во время сборки ядра, т.к. это требует свободного распространения его кода. Закрытая часть одного из дополнительных ключей могла бы быть передана разработчику стороннего модуля, однако это представляется неправильным, поскольку доверие к таким модулям не может быть более или равным доверию к поставляемым разработчиком ОС модулям, а системный администратор не будет иметь возможности ограничить доверие к сторонним разработкам, в т.ч. в случае компроментации выданного таким образом закрытого ключа.
Механизм подписывания сторонних модулей ядра
Предлагается следующий механизм:
- Разработчик стороннего модуля (далее — РСМ) самостоятельно создает ключевую пару и подписанный созданным ключом запрос на сертификат (CSR);
- РСМ высылает CSR в Росу;
- Роса подписывает публичный ключ РСМ одним из встроенных в ядро ключей;
- РСМ создает в RPM-пакете со своим ПО специальные файлы и/или скрипты и кладет публичный ключ в специальный каталог, что обеспечивает добавление ключа в список доверенных при запуске ОС;
- администратор ОС имеет возможность убрать этот ключ из доверенных.
Действия получающего ключ разработчика стороннего ПО
Нужно создать ключевую пару и подписанный этим ключом запрос на сертификат.
Можно использовать как ГОСТ-алгоритмы, так и RSA или эллиптические кривые.
RSA:
openssl req -new -nodes -newkey rsa:2048 -keyout privatekey.key -out certificatesigningrequest.csr
По ГОСТ:
libressl req -new -nodes -newkey gost2001 -pkeyopt dgst:streebog512 -pkeyopt paramset:A -streebog512 -days 109500 -keyout privatekey.key -out certificatesigningrequest.csr
(для ГОСТ требуется libressl с патчами Росы (или иное средство), который есть в репозитории Росы или может быть собран отдельно; лучше использовать пока что RSA)
Generating a 2048 bit GOST2001 private key writing new private key to 'privatekey.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. -----
Указываем страну:
Country Name (2 letter code) []:RU
Указываем субъект РФ (республику/область/иное):
State or Province Name (full name) []:Orlovskaya region
Указываем город или иной населенный пункт (для городов федерального значения значение этих двух полей может совпадать, например, в обоих Moscow):
Locality Name (eg, city) []:Oryol
Заполняем информацию об организации, OUN можно пропустить:
Organization Name (eg, company) []:Roga i kopyta Ltd. Organizational Unit Name (eg, section) []: Common Name (eg, fully qualified host name) []:roga-i-kopyta.ru Email Address []:info@roga-i-kopyta.ru
Можно использовать пароль, можно не использовать, оставив поле пустым и просто нажав Enter:
Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:
Было создано 2 файла:
- privatekey.key — ваш закрытый ключ, его следует хранить внутри организации и предотвращать доступ посторонних лиц к нему.
- certificatesigningrequest.csr — запрос сертификата, его нужно отправить в Росу.
Отправьте CSR (файл certificatesigningrequest.csr) в Росу.
Действия сотрудников Росы по подписыванию ключа
Выпускаем подписанный сертификат:
certtool --generate-certificate --load-request certificatesigningrequest.csr --load-ca-privkey встроенный_в_ядро_ключ.pem --load-ca-certificate встроенный_в_ядро_ключ.pem --outfile /tmp/t1.pem
где /tmp/t1.pem — необходимый результат операции.
Необходимо конвертировать ключ в формат der (это может сделать как сотрудник Росы, так и РСМ сам):
openssl x509 -outform der -in /tmp/t1.pem -out /tmp/t1.der
Подписывание модуля ядра
Подписывание производится с помощью scripts/sign-file из состава исходных кодов ядра Linux. Для удобства использования эта утилита опакечена в Росе (в ОС Никель имеется на диске разработчика), ее можно установить с помощью пакетного менеджера:
sudo dnf install sign-file
Эта утилита в варианте из репозитория поддерживает ГОСТ-ключи и работает через libressl вместо openssl.
Далее подписать модуль ядра:
sign-file sha256 privatekey.key t1.pem file.ko
В случае ГОСТ заменить sha* на streebog256 / streebog512.
Использование именно этой утилиты рекомендуется, но не обязательно.
Упаковка модуля ядра с публичным ключом
Выше описано, в какой каталог рекомендуется положить модуль ядра (*.ko*).
В /lib/modules/keys/*.der
необходимо положить подписанный ключом Росы публичный ключ. Имя файла рекомендуется сделать таким: имя_пакета.der, однако технически имя файла может быть любым.
Все ключи из этого каталога добавляются в ядро из initrd (dracut). В силу наличия в dracut в ОС Никель ошибки, которая не может быть исправлена до прохождения соответствующим обновлением сертификации, при сборке пакета для ОС Никель (для rosa2021.1 (Хром) и новее — нет необходимости, будет исправлен сам dracut!) необходимо добавить в него файл-скрипт systemd.generator(7). Его необходимо назвать по имени пакета с постфиксом "-key" (это рекомендация, не обязательное требование, имя файла может быть любым) и положить в каталог /lib/systemd/system-generators
, который задается RPM-макросом %_systemdgeneratordir
. Пример полного пути к файлу: /lib/systemd/system-generators/paket-key
. Права 755. Текст скрипта следующий:
#!/bin/sh keyctl padd asymmetric "" %:.secondary_trusted_keys < /lib/modules/keys/paket.der
- ↑ zzz, чтобы эта папка была последней, в которой будут искаться модули ядра