Загрузка системы: BIOS & UEFI, GRUB, initrd, systemd/sysvinit/upstart

Аналитики компании Binarly обнаружили 23 критические уязвимости в UEFI от InsydeH2O, которая используется многими крупными вендорами, включая HP, Lenovo, Fujitsu, Microsoft, Intel, Dell, Bull (Atos) и Siemens.
  • В BIOS есть настройки работы с питанием (bios power management), могут быть полезны:
    • что делать в случае неожиданного отключения
      • не включаться (по умолчанию)
      • включать сразу
    • включаться всегда при наличии питания
  • Правки дампа BIOS делаются
    • (чаще работает) с использованием HEX редактора и UEFITool – дамп BIOS открывается в UEFITool, ищется модуль, содержащий необходимые для замены значения, экпортируется, изменяется в HEX редакторе, импортируется, сохраняется новый образ и при помощи программатора заливается на микросхему
    • (чаще не работает) с использованием HEX редактора – дамп BIOS открывается в HEX редакторе, далее ищутся строки которые необходимо заменить, дамп сохраняется и при помощи программатора заливается на микросхему

 

BOOT directory

В Boot директории содержатся ключевые файлы, необходимые для загрузки системы – grub.cfg, kernel, boot image, initrd/initramfs, config и прочие.

/boot – file system contains the Linux kernel, boot support files, and boot configuration files для загрузки системы. The /boot file system is created at system installation. The default size of this file system is 500MB, and it may be expanded as part of the preparation to update the kernel.
The output indicates that the current kernel is vmlinuz-3.10.0-327.el7.x86_64, its boot image is stored in the initramfs-3.10.0-327.el7.x86_64.img file, and configuration in the config-3.10.0-327.el7.x86_64 file.
[root@localhost ~]# ll /boot/
total 108556
-rw-r--r--. 1 root root 126426 Nov 20 2015 config-3.10.0-327.el7.x86_64
drwxr-xr-x. 2 root root 4096 Oct 11 11:07 extlinux
drwxr-xr-x. 2 root root 26 Jul 27 17:23 grub
drwx------. 6 root root 104 Jul 27 21:05 grub2
-rw-r--r--. 1 root root 57594234 Jul 27 20:32 initramfs-0-rescue-c45de976bcc44afba871f946c3230751.img
-rw-r--r--. 1 root root 29701379 Jul 27 21:03 initramfs-3.10.0-327.el7.x86_64.img
-rw-r--r--. 1 root root 10192063 Jul 27 20:01 initrd-plymouth.img
-rw-r--r--. 1 root root 252612 Nov 20 2015 symvers-3.10.0-327.el7.x86_64.gz
-rw-------. 1 root root 2963044 Nov 20 2015 System.map-3.10.0-327.el7.x86_64
-rwxr-xr-x. 1 root root 5156528 Jul 27 20:41 vmlinuz-0-rescue-c45de976bcc44afba871f946c3230751
-rwxr-xr-x. 1 root root 5156528 Nov 20 2015 vmlinuz-3.10.0-327.el7.x86_64
A sub-directory /boot/grub2 contains GRUB information. The key file in /boot/grub2 is grub.cfg, which maintains a list of available kernels and defines the default kernel to boot, along with other information.
[root@localhost ~]# ll /boot/grub2
total 32
-rw-r--r--. 1 root root 64 Jul 27 20:51 device.map
drwxr-xr-x. 2 root root 24 Jul 27 20:51 fonts
-rw-r--r--. 1 root root 4231 Jul 27 21:05 grub.cfg
-rw-r--r--. 1 root root 1024 Oct 17 18:56 grubenv
drwxr-xr-x. 2 root root 8192 Jul 27 20:51 i386-pc
drwxr-xr-x. 2 root root 4096 Jul 27 20:51 locale
drwxr-xr-x. 3 root root 19 Jul 27 17:59 themes
Процесс загрузки Linux

    1. запуск микрокода BIOS / UEFI который проверяет hardware (POST – Power-on self-test), осуществляет его низкоуровневую настройку, определяет на каком носителе будет осуществляться поиск загрузчика и выполняет программу-загрузчик ОС, как только загрузчик был обнаружен и загружен в память, BIOS передает управление ему.
    2. /boot/efi (папка может быть пустой): поиск на выбранном носителе главная загрузочной записи MBR / GPT (чаще всего сформатированном в небольшой раздел FAT32) загрузчика bootloader в boot record носителя (первые секторы раздела носителя) – именно для создания boot record на носителях (flash/usb) нужно использовать dd / rufus / unetbooting / win32diskimager и прочие утилиты, недостаточно просто ‘забросить’ файлы на носитель. MBR размещена в 1-м секторе загрузочного диска, например /dev/hda или /dev/sda. MBR занимает меньше, чем 512 байтов. Она содержит информацию о GRUB’е (или LILO) и состоит из трех компонентов:
      1. главная загрузочная информация, «живущая» в первых 446 байтах
      2. информация о таблице разделов — в следующих 64 байтах
      3.  последние 2 байта нужны для проверки корректности mbr
    3. boot/grub (тут или в /boot/grub/ или в /etc/ находится файл конфигурации grub.conf/grub.cfg): запуск bootloader (сейчас обычно в виде GRUB version 2, но раньше были разные bootloader, что привело к созданию GRand Unified Bootloader – универсального загрузчика для разных ОС/разных ядер одной ОС, который может или полностью подменить существующий загрузчик или «встать» перед ним как в случае с Windows); ключевое что содержит GRUB это местонахождение файлов с ОС на диске (путь к ядру и образу initrd), но так же в конфигурации GRUB можно задать доп. параметры типа kernel parameters в /proc/cmdline, параметры recovery feature, можно отключать аппаратные и програмные модули еще до загрузки ОС и даже управлять разрешением экрана (для извращений).
      1. Пример записи из GRUB для одной из menuentry, в конфиге grub можно указать конкретные ядра/список ядер:
        • menuentry ‘Debian GNU/Linux, with Linux 4.19.0-9-amd64 (recovery mode)’
          • linux   /boot/vmlinuz-4.19.0-9-amd64  – kernel
          • initrd  /boot/initrd.img-4.19.0-9-amd64  – RAM disk
      2. Для автоматического редактирования grub файла в случае обновления ядра делать ничего вручную не нужно – автоматически установщик добавляет menu entry с новым ядром и метит его дефолтным для загрузки, пример описан в CentOS
      3. Для редактирования grub нужно не редактировать сам grub файл (он находится в boot и обычно эта директория read only), а редактировать файл grub в директории /etc/default через sudoedit; на случай проблем рекомендуется иметь live USB, с которого можно загрузиться и пофиксить конфигурацию GRUB
        • sudoedit /etc/default/grub 
      4. Пример опций/изменений, хорошо описаны на gnu.org
        • GRUB_TIMEOUT=5 – сколько будет timeout ожидания выбора ОС/ядра (-1 бесконечно, 0 не ждать вообще)
        • GRUB_DISABLE_RECOVERY=true – режимы восстановления не показываются в меню GRUB
        • GRUB_DEFAULT=saved – сохранение выбранной опции в последней загрузке (выбранной ОС) по умолчанию
        • GRUB_DEFAULT=”1>Debian GNU/Linux, with Linux 4.19.0-20-amd64″ – фиксация конкретной версии ядра Linux
        • GRUB_TERMINAL_OUTPUT=consoleможет быть изменение с вывода на консоль в другой источник – напр. на serial port для сетевых девайсов в среднем может быть лучше т.к. монитор для подключения к консоли может отсутствовать
        • GRUB_CMDLINE_LINUX=”default_hugepagesz=1GB hugepagesz=1G hugepages=8 transparent_hugepage=never” – пример настройки huge pages для DPDK/TRex
        • GRUB_CMDLINE_LINUX=”isolcpus=1-19″ – пример изоляции CPU ядер
      5. Кроме основного файла grub.cfg, GRUB так же считывает все конфигурационные файлы из директории /etc/grub.d и добавляет их в общую конфигурацию grub в один grub.cfg; изменения пользователя в виде кастомизированный меню-записей рекомендуется добавлять в файлы 40_custom, другую кастомазацию 41_custom, найденые ОС, добавленные в меню фигурируют в 30_os-prober
/etc/grub.d# ls -ltr
total 76
-rwxr-xr-x 1 root root 6258 Jun 13 2019 05_debian_theme
-rw-r--r-- 1 root root 483 Jun 25 2019 README
-rwxr-xr-x 1 root root 216 Jun 25 2019 41_custom
-rwxr-xr-x 1 root root 214 Jun 25 2019 40_custom
-rwxr-xr-x 1 root root 1418 Jun 25 2019 30_uefi-firmware
-rwxr-xr-x 1 root root 12059 Jun 25 2019 30_os-prober
-rwxr-xr-x 1 root root 11497 Jun 25 2019 20_linux_xen
-rwxr-xr-x 1 root root 12444 Jun 25 2019 10_linux
-rwxr-xr-x 1 root root 9783 Jun 25 2019 00_header
      • Обновление конфигурации GRUB после изменений, при обновлении GRUB собирает все файлы конфигурационные файлы в один grub.cfg, проверяет корректность синтаксиса перед обновлением конфигурации в /boot/ директории
        • sudo update-grub или sudo update-grub2 – Debian
        • sudo grub2-mkconfig -o /boot/grub2/grub.cfg – RHEL
    1. boot/initrd.img / initramfs.img (обычно линк к конкретному файлу определенной версии ядра):
      1. ядро ОС монтирует ram disk initrd/initramfs. Initrd (Initial RAM Disk) – временный диск в оперативной памяти; в виде образа диска копируется в RAM и рассматривается как полноценный примонтированный hard drive диск, внутри initrd находится код ОС, который необходим для старта системы. initrd используется самим ядром в качестве временной корневой файловой системы, пока kernel не загрузится в реальную примонтированную файловую систему. Этот временный диск также содержит необходимые для загрузки драйверы, позволяющие получить доступ к разделам дисков и другому оборудованию.
      2. ядро ОС запускает код операционной системы через выполнение программы /sbin/init. Поскольку init — это первый процесс, запущенный ядром Linux, поэтому она имеет идентификатор процесса (PID) №1
    2. /sbin/init (обычно линк к /lib/systemd/systemd): код ядра запускает init процесс/скрипт, который в свою очередь отвечает за запуск всех остальных компонентов/сервисов/приложений системы, вариантов реализации init несколько, ключевые:
        1. systemd – самый новый и популярный, работает в виде отдельного процесса
        2. sysvinit (old from unix) – самый старый, работает в виде скриптов
        3. upstart (backward compatible with sysvinit)
Initrd (сокращение от англ. Initial RAM Disk, диск в оперативной памяти для начальной инициализации) — временная файловая система, используемая ядром Linux при начальной загрузке. Initrd обычно используется для начальной инициализации перед монтированием «настоящих» файловых систем. В Linux Kernel HOWTO (руководстве о сборке ядра) пишут, что initrd призван решить проблему курицы и яйца для модульного ядра: для монтирования файловой системы необходим модуль для работы с диском и файловой системой, а для чтения модуля необходима файловая система, с которой этот модуль читается[1].

runlevel – исходя из настроек по умолчанию с указанием номера runlevel, система будет выполнять файлы в соответствии с нижеприведенными директориями, соответствующими runlevel. К примеру, это могут быть сообщения типа «starting Postfix … OK» (запускается Postfix). Эти службы — и называются программами уровня выполнения, выполняемые из директории, которая соответствует нужному уровню выполнения.

Выполнение уровня 0 – /etc/rc.d/rc0.d/
Выполнение уровня 1 – /etc/rc.d/rc1.d/
Выполнение уровня 2 – /etc/rc.d/rc2.d/
Выполнение уровня 3 – /etc/rc.d/rc3.d/
Выполнение уровня 4 – /etc/rc.d/rc4.d/
Выполнение уровня 5 – /etc/rc.d/rc5.d/
Выполнение уровня 6 – /etc/rc.d/rc6.d/

Чаще всего тут используются ссылки типо:
# ls -ltr /etc/rc2.d/
total 0
lrwxrwxrwx 1 root root 14 May 24 2021 S01cron -> ../init.d/cron

В каталогах вы можете увидеть список программ, имя которых начинается из букв S и K.

    • Программы, начинающиеся на S используются для запуска. S, потому что startup.
    • Программы, которые начинаются с литеры K используются — правильно — для завершения работы. K, потому что kill.
    • Еще есть номера рядом с буквами S и K в именах программ. Эти номера используются для определения порядка запуска этих программ.
К примеру, 
- S12syslog предназначен для запуска демона syslog, его порядковый номер 12. 
- S80sendmail — для запуска демона sendmail, имеющего порядковый номер 80. 
Таким образом, программа syslog будет запущена перед sendmail.

По факту сейчас в Debian так:
# ls -ltr /etc/rc5.d/
total 0
lrwxrwxrwx 1 root root 14 May 24 2021 S01cron -> ../init.d/cron
lrwxrwxrwx 1 root root 17 May 24 2021 S01rsyslog -> ../init.d/rsyslog
lrwxrwxrwx 1 root root 26 May 24 2021 S01console-setup.sh -> ../init.d/console-setup.sh
lrwxrwxrwx 1 root root 14 May 24 2021 S01dbus -> ../init.d/dbus
lrwxrwxrwx 1 root root 13 May 24 2021 S01ssh -> ../init.d/ssh
lrwxrwxrwx 1 root root 15 Mar 14 2022 S01squid -> ../init.d/squid
lrwxrwxrwx 1 root root 14 Sep 29 2023 S01atop -> ../init.d/atop
lrwxrwxrwx 1 root root 18 Sep 29 2023 S01atopacct -> ../init.d/atopacct

runlevel+sysvinit: На старых системах под управлением sysvinit используется файл /etc/inittab для того, чтобы определить уровень выполнения (runlevel). Init определяет уровень выполнения по умолчанию (initdefault) и использует его для загрузки всех необходимых программ.

Есть следующие уровни выполнения: 
0 – прервать выполнение 
1 – однопользовательский режим, так называемый «Single user mode», или иными словами, консоль восстановления 
2 – многопользовательский режим без поддержки NFS 
3 – полноценный многопользовательский режим 
4 – не используется 
5 – X11 
6 – перезагрузка

runlevel+systemd: На более актуальных системах с управлением systemd файл /etc/inittab не используется, runlevel задается в конфигурации systemd, уровни приближенные к старым, но в целом они могут отличаться в разных дистрибутивах.

root@serv:~# systemctl get-default
graphical.target
root@serv:~# runlevel
N 5
root@serv:~# ls -la /lib/systemd/system/runlevel*
lrwxrwxrwx 1 root root 15 Mar 18 2021 /lib/systemd/system/runlevel0.target -> poweroff.target
lrwxrwxrwx 1 root root 13 Mar 18 2021 /lib/systemd/system/runlevel1.target -> rescue.target
lrwxrwxrwx 1 root root 17 Mar 18 2021 /lib/systemd/system/runlevel2.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Mar 18 2021 /lib/systemd/system/runlevel3.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Mar 18 2021 /lib/systemd/system/runlevel4.target -> multi-user.target
lrwxrwxrwx 1 root root 16 Mar 18 2021 /lib/systemd/system/runlevel5.target -> graphical.target
lrwxrwxrwx 1 root root 13 Mar 18 2021 /lib/systemd/system/runlevel6.target -> reboot.target

 

Leave a Reply