Разбираемся в процессе Secure Boot в Linux
Эта заметка начнётся с общего обзора процесса загрузки Ubuntu, а затем углубится в то, какую роль в нём играет SecureBoot, если он включён. Я затрону такие вещи, как shim, переменные EFI и MOK. Информация, которую вы тут увидите, собрана из источников, перечисленных в конце статьи. Также будут команды и примеры вывода, чтобы картина получилась более целостной.
Понимание процесса загрузки вместе с SecureBoot важно, потому что без нормального представления о том, как всё устроено внутри Linux-системы, очень легко случайно превратить её в кирпич, пытаясь включить такие настройки, как SecureBoot. Это низкоуровневые операции, которые при неосторожности могут наделать много бед.
Типичный процесс загрузки
Когда Ubuntu загружается, она проходит через четыре основные фазы.
- Фаза BIOS — прошивка на материнской плате, обычно хранящаяся в виде ПЗУ, инициализирует аппаратные компоненты и получает код для загрузчика.
- Фаза загрузчика — загрузчик поднимает операционную систему в память вместе с начальным образом файловой системы initrd.
- Фаза ядра — ядро запускает скрипт
initвнутри файловой системы initrd. Он загружает драйверы и монтирует корневой раздел. - Запуск системы — операционная система поднимает демоны и сервисы, настраивает сеть, монтирует файловые системы, запускает системный логгер и делает прочую инициализацию.
Обычно на Linux-системах есть 512-битный раздел под названием Master Boot Record (MBR). В нём хранится загрузчик (GRUB, LILO, yaboot и другие) и загрузочные записи. Это одно из мест, откуда Linux может стартовать. Другие варианты — загрузчик на носителе вроде USB-флешки или CD-R, либо загрузчик, который приходит по сети, например через Preboot Execution Environment (PXE).
Secure Boot
Secure Boot — это стандарт безопасности. Когда компьютер включается, процесс Secure Boot стартует с прошивки на материнской плате, которая проверяет криптографические подписи каждого файла, участвующего в загрузке. Сюда входят драйверы прошивки UEFI (они же optional ROMs), EFI-приложения и сама операционная система. Если всё проверяется успешно, машина продолжает загрузку, и прошивка передаёт управление операционной системе.
Shim
При включении Secure Boot важно понимать, что такое shim. В контексте Secure Boot это пред-загрузчик, который умеет работать с прошивкой, enforcing Secure Boot. Он позволяет загружать и выполнять загрузчики и модули ядра, даже если их нет в базе доверенных ключей Secure Boot. В Ubuntu shim ставится заранее и подписан сертификатным центром Microsoft.
Secure Boot использует асимметричную криптографию, то есть пару ключей — публичный и приватный. Пользователь может создать свою пару: приватным ключом подписываются все программы, которым разрешено выполняться, включая загрузчик GRUB. Прошивка BIOS или UEFI потом использует публичный ключ, чтобы проверять контрольные суммы и подписи перед запуском этих программ.
Вы можете проверить подпись своего shim-загрузчика с помощью sbverify, который входит в пакет sbsigntool:
# locate your shim binary $ SHIM=$(sudo find /boot/efi/EFI/ -iname "shim*" 2>/dev/null) $ sbverify $SHIM Signature verification OK
Переменные UEFI
Ещё одна важная вещь — переменные UEFI, которые хранятся в энергонезависимой памяти прошивки (NV-RAM). В них записаны разные данные: порядок загрузки, тайм-ауты, сетевые настройки, информация о накопителях и параметры Secure Boot. Для каждой переменной есть свой бинарный файл в каталоге /sys/firmware/efi/efivars/. Формат имён такой: имя переменной плюс GUID вендора. Например, файл
SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c
может хранить значение, включён Secure Boot (0x01) или выключен (0x00).
Посмотреть эти переменные можно, просто перечислив содержимое /sys/firmware/efi/efivars/ или через инструмент efivarfs, чтобы вывести список и прочитать значения:
$ sudo apt-get install efivar $ sudo efivar -p -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot

В этом примере значение переменной SecureBoot — 0x01, то есть Secure Boot включён. Есть ещё несколько ключевых переменных, связанных именно с Secure Boot:
8be4df61-93ca-11d2-aa0d-00e098032b8c-PKDefault 8be4df61-93ca-11d2-aa0d-00e098032b8c-KEKDefault 8be4df61-93ca-11d2-aa0d-00e098032b8c-dbDefault 8be4df61-93ca-11d2-aa0d-00e098032b8c-dbxDefault
Эти переменные относятся к базам ключей, которые определяют, можно ли считать модуль безопасным для загрузки.
Базы данных Secure Boot
Secure Boot опирается на четыре ключевые базы. Их можно подробно изучить в официальной спецификации, но кратко смысл такой:
- Allowed Signature Database (db) — список криптографических подписей, которые разрешено загружать во время старта системы.
- Disallowed Signature Database (dbx) — список подписей, которые, наоборот, запрещены к загрузке.
- Key Enrollment Key Database (KEK) — набор ключей, которые используются для проверки подлинности других баз.
- Platform Key Database (PK) — содержит публичный ключ, с помощью которого проверяются подписи загрузчиков или прошивки, если они подписаны соответствующим приватным ключом. Рекомендуемый формат платформенного ключа для UEFI — RSA-2048.
Эти базы фактически задают правила: какие подписи считаются допустимыми, а какие нет. Для Secure Boot это критично, потому что именно так обеспечивается проверка целостности модулей перед их выполнением.
Machine Owner Keys (MOK)
Ещё один элемент загрузочного процесса — Machine Owner Keys (MOK). Это дополнительная база ключей, которой может управлять сам пользователь. Она не связана с тем сертификатным ключом, который поставляется вместе с shim. MOK дают пользователю больше контроля над тем, какие модули можно загружать. Например, когда пользователь регистрирует MOK в системе, связанный с ним ключ добавляется в базу разрешённых подписей (db). Это значит, что любой бинарник, подписанный этим ключом, будет считаться доверенным прошивкой во время загрузки.
Обычно MOK-файлы находятся в каталоге /var/lib/shim-signed/mok/ и называются MOK.der, MOK.pem или MOK.priv. Если у вас ещё нет MOK-ключей, а создать их нужно, можно воспользоваться такими командами:
# mkdir -p /var/lib/shim-signed/mok/ # cd /var/lib/shim-signed/mok/ # openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -days 36500 -subj "/CN=My Name/" # openssl x509 -inform der -in MOK.der -out MOK.pem
По умолчанию shim предоставляет утилиту управления MOK под названием MokManager. Она позволяет «добавлять ключи, удалять доверенные ключи, регистрировать хэши бинарников и переключать проверку Secure Boot на уровне shim», как описано в документации Ubuntu. Учтите, что для работы с MokManager обычно требуется пароль — чтобы аутентифицировать пользователя, который вносит изменения.
MokManager помогает корректно настроить ключи, если требуется управление ими. После завершения настройки система перезагрузится, чтобы применить изменения. Если всё прошло как надо, загрузка продолжится в обычном режиме, без появления экрана MokManager.
Конфигурация загрузчика и полезная информация
Можно покопаться глубже в том, как ваша Linux-машина загружается. Один из способов — посмотреть файл /proc/cmdline. В нём лежат параметры командной строки ядра, которые были переданы ему во время загрузки.
$ cat /proc/cmdline # example output BOOT_IMAGE=/boot/vmlinuz-5.11.0-16-generic root=UUID=12345678-1234-1234-1234-1234567890AB ro quiet splash
Эта команда показывает путь к файлу образа ядра, который загрузчик передал ядру через BOOT_IMAGE. Опция quiet splash в конце — стандартная штука для GRUB: она отключает подробные сообщения во время старта и выводит графический сплэш-скрин.
Ядро — это бинарник, содержащий основной код ОС. В нём всё необходимое, чтобы загрузиться, управлять памятью, работать с устройствами ввода-вывода и запускать пользовательские программы. Загрузчик использует его, чтобы стартовать систему. Имя файла ядра обычно подсвечивает его версию и архитектуру. Например, ядро vmlinuz-5.4.0-1042-aws — это версия 5.4.0-1042 для AWS-окружения.
Загрузчик использует свои драйверы файловых систем из initramfs, и вы можете посмотреть их содержимое, если знаете, какой файл /boot/initrd* соответствует текущему ядру. Проще всего — воспользоваться утилитами из initramfs-tools-core:
## list files inside the initramfs $ lsinitramfs /boot/initrd.img-$(uname -r) . kernel kernel/x86 . bin conf conf/arch.conf conf/conf.d conf/conf.d/resume -- snip -- ## extract files from the initramfs $ unmkinitramfs /boot/initrd.img-$(uname -r) initramfs/
Это позволяет пройтись по файловой системе initramfs и лучше понять, что происходит во время ранних этапов загрузки. Если вы распакуете initramfs, то увидите внутри каталога ./initramfs три папки: early, early2 и main:
$ ls initramfs early early2 main
В контексте initramfs early и early2 — это первая и вторая стадии начальной RAM-файловой системы. На первой стадии загружается минимальный набор драйверов и утилит, необходимых для инициализации оборудования и монтирования настоящего корневого раздела. На второй стадии (early2) подгружаются дополнительные драйверы и инструменты, которые нужны для полной инициализации системы.
Папка main внутри initramfs содержит собственно образ корневой файловой системы, а также дополнительные инструменты и драйверы, которые могут понадобиться во время загрузки. После монтирования корневой ФС система продолжает запуск обычных сервисов и демонов, необходимых для работы операционной системы.
Проверка подписей вручную
Можно проверить, какие модули ядра подписаны, с помощью команды modinfo. Подпись ядра в выводе выглядит как длинная строка шестнадцатеричных значений, разделённых двоеточиями.
$ modinfo example.ko filename: /lib/modules/5.10.0-5-amd64/kernel/drivers/misc/example.ko version: 1.0.0 license: GPL description: Example kernel module author: John Doe <jdoe@example.com> srcversion: 12AB34CD5678EF90ABCD1234 sig_key: A0:3B:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF sig_hashalgo: sha256 signature: 12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF
Заключение
Спасибо, что дочитали этот обзор Secure Boot. Очень советую заглянуть в источники ниже — эта заметка лишь поверхностно прошлась по теме. Надеюсь, она помогла вам лучше почувствовать, насколько сложной и одновременно изящной является система, когда Linux-машина включается и оживает.
Источники
- Ubuntu’s wiki on Secure Boot (detailed)
- Ubuntu’s wiki on Booting Process
- Linux Documentation — Kernel Module Signing
- Mike Danslegio Explains Secure Boot
- User Space and Kernel Space in Linux
- Kernel.org — Ramfs, rootfs, and initramfs
- SecureBoot Debian Wiki
- Check UEFI or BIOS
- Using the initial RAM disk (initrd)
- Linux Boot Process Explained
- Preboot Execution Environment
- EFI Variables — Stack Exchange
- UEFI Specification Version 2.9 (March 2021)
- Initramfs Debian Wiki