В вычислительной технике загружаемый модуль ядра ( LKM ) представляет собой объектный файл , который содержит код для расширения работающего ядра , или так называемого базового ядра , операционной системы . LKM обычно используются для добавления поддержки нового оборудования (в качестве драйверов устройств ) и/или файловых систем или для добавления системных вызовов . Когда функциональность, предоставляемая LKM, больше не требуется, ее можно выгрузить, чтобы освободить память и другие ресурсы.
Большинство современных Unix-подобных систем и Microsoft Windows поддерживают загружаемые модули ядра под разными именами, например, загружаемый модуль ядра ( kld ) во FreeBSD , расширение ядра ( kext ) в macOS (хотя поддержка сторонних модулей прекращается [1] ). , [2] модуль расширения ядра в AIX , динамически загружаемый модуль ядра в HP-UX , [3] драйвер режима ядра в Windows NT [4] и загружаемый модуль ядра ( DKM ) в VxWorks . Они также известны как загружаемые модули ядра (или KLM ) и просто модули ядра ( KMOD ).
Без загружаемых модулей ядра операционная система должна была бы включать в себя все возможные ожидаемые функции, скомпилированные непосредственно в базовое ядро. Большая часть этих функций будет находиться в памяти и не использоваться, тратя память впустую [ нужна цитация ] и потребует от пользователей пересобирать и перезагружать базовое ядро каждый раз, когда им требуются новые функции.
Одним из незначительных замечаний по поводу предпочтения модульного ядра статическому ядру является так называемый штраф за фрагментацию . Базовое ядро всегда распаковывается в реальную непрерывную память с помощью процедур установки; таким образом, базовый код ядра никогда не фрагментируется. Когда система находится в состоянии, в котором можно вставлять модули, например, после того, как были смонтированы файловые системы , содержащие модули, вполне вероятно, что любая новая вставка кода ядра приведет к фрагментации ядра, что приведет к незначительному снижению производительности. за счет использования большего количества записей TLB , что приводит к большему количеству промахов TLB. [ нужна цитата ]
Загружаемые модули ядра в Linux загружаются (и выгружаются) с помощью этой modprobe
команды. Они расположены в /lib/modules
или /usr/lib/modules
и имеют расширение .ko
(«объект ядра») начиная с версии 2.6 (предыдущие версии использовали это .o
расширение). [5] Команда lsmod
выводит список загруженных модулей ядра. В экстренных случаях, когда система не загружается, например, из-за сломанных модулей, определенные модули можно включить или отключить, изменив список параметров загрузки ядра (например, при использовании GRUB , нажав «e» в меню запуска GRUB, а затем редактирование строки параметров ядра).
По мнению сопровождающих Linux, LKM являются производными продуктами ядра . Сопровождающие Linux допускают распространение проприетарных модулей, [ нужна ссылка ] , но позволяют помечать символы как доступные только для модулей GNU General Public License (GPL).
Загрузка проприетарного или несовместимого с GPL модуля приведет к установке флага «загрязнения» [6] [7] в работающем ядре — это означает, что любые возникающие проблемы или ошибки с меньшей вероятностью будут расследованы сопровождающими. [8] [9] LKM фактически становятся частью работающего ядра, поэтому могут повредить структуры данных ядра и вызвать ошибки, которые невозможно исследовать, если модуль действительно является проприетарным.
В 2004 году Linuxant, консалтинговая компания, выпускающая проприетарные драйверы устройств в виде загружаемых модулей ядра, попыталась злоупотребить нулевым терминатором в своих файлах MODULE_LICENSE
, как видно из следующего фрагмента кода:
MODULE_LICENSE ( "GPL \0 для файлов в каталоге \" GPL \" ; для остальных применяется только файл ЛИЦЕНЗИИ" );
Код сравнения строк, используемый ядром в то время, пытался определить, находится ли модуль под лицензией GPL, и остановился, когда он достиг нулевого символа ( \0
), поэтому он был обманут, думая, что модуль объявляет свою лицензию просто «GPL». [10]
Модули ядра для FreeBSD хранятся внутри /boot/kernel/
для модулей, распространяемых вместе с операционной системой , или обычно /boot/modules/
для модулей, установленных из портов FreeBSD или пакетов FreeBSD , или для проприетарных или других двоичных модулей. Модули ядра FreeBSD обычно имеют расширение .ko
. После загрузки машины их можно загрузить с помощью kldload
команды, выгрузить с помощью kldunload
и внести в список с помощью kldstat
. Модули также можно загружать из загрузчика до запуска ядра либо автоматически (через /boot/loader.conf
), либо вручную.
Некоторые загружаемые модули ядра в macOS могут загружаться автоматически. Загружаемые модули ядра также можно загрузить с помощью этой kextload
команды. Их можно просмотреть командой kextstat
. Загружаемые модули ядра располагаются в бандлах с расширением .kext
. В каталоге хранятся модули, поставляемые с операционной системой /System/Library/Extensions
; модули, поставляемые третьими лицами, находятся в других каталогах.
Модуль ядра NetWare называется загружаемым модулем NetWare (NLM). NLM вставляются в ядро NetWare с помощью команды LOAD и удаляются с помощью команды UNLOAD; команда modules
выводит список загруженных в данный момент модулей ядра. NLM могут находиться в любом допустимом пути поиска, назначенном на сервере NetWare, и .NLM
в качестве имени файла они имеют расширение.
Можно создать проект типа загружаемого модуля ядра (DKM) для создания файла «.out», который затем можно загрузить в пространство ядра с помощью команды «ld». Этот загружаемый модуль ядра можно выгрузить с помощью команды «unld».
Solaris имеет настраиваемый путь загрузки модулей ядра, который по умолчанию равен /platform/platform-name/kernel /kernel /usr/kernel
. Большинство модулей ядра находятся в подкаталогах /kernel
; те, которые не считаются необходимыми для загрузки системы до момента запуска init, часто (но не всегда) встречаются в файлах /usr/kernel
. При запуске сборки ядра DEBUG система активно пытается выгрузить модули.
Linux не предоставляет стабильного API или ABI для модулей ядра. Это означает, что между разными версиями ядра существуют различия во внутренней структуре и функциях, что может вызвать проблемы совместимости. В попытке решить эти проблемы данные о версиях символов помещаются в .modinfo
раздел загружаемых модулей ELF . Эту информацию о версии можно сравнить с информацией о работающем ядре перед загрузкой модуля; если версии несовместимы, модуль не будет загружен.
Другие операционные системы, такие как Solaris , FreeBSD , macOS и Windows , поддерживают API ядра и ABI относительно стабильными, что позволяет избежать этой проблемы. Например, модули ядра FreeBSD , скомпилированные с версией ядра 6.0, будут работать без перекомпиляции с любой другой версией FreeBSD 6.x, например 6.4. Однако они несовместимы с другими основными версиями и должны быть перекомпилированы для использования с FreeBSD 7.x, поскольку совместимость API и ABI поддерживается только внутри ветки.
Хотя загружаемые модули ядра являются удобным методом модификации работающего ядра, злоумышленники могут злоупотреблять им в скомпрометированной системе, чтобы предотвратить обнаружение своих процессов или файлов , что позволяет им сохранять контроль над системой. Многие руткиты используют LKM таким образом. Обратите внимание, что в большинстве операционных систем модули никак не помогают повысить привилегии , поскольку для загрузки LKM требуются повышенные привилегии; они просто облегчают злоумышленнику скрытие взлома. [11]
Linux позволяет отключить загрузку модулей через опцию sysctl/proc/sys/kernel/modules_disabled
. [12] [13] Система initramfs может загружать определенные модули, необходимые для машины при загрузке, а затем отключать загрузку модулей. Это делает безопасность очень похожей на монолитное ядро. Если злоумышленник может изменить initramfs, он может изменить двоичный файл ядра.
В OS X Yosemite и более поздних версиях расширение ядра должно быть подписано кодом сертификата разработчика, который имеет определенное «право». Такой сертификат разработчика предоставляется Apple только по запросу и не выдается автоматически участникам Apple Developer . Эта функция, называемая «подписью kext», включена по умолчанию и дает указание ядру прекратить загрузку, если присутствуют неподписанные расширения ядра. [14] В OS X El Capitan и более поздних версиях он является частью защиты целостности системы .
В более старых версиях macOS или если подпись kext отключена, загружаемый модуль ядра в пакете расширения ядра может быть загружен пользователями без полномочий root, если для свойства OSBundleAllowUserLoad в списке свойств пакета установлено значение True. [15] Однако, если какой-либо из файлов в комплекте, включая файл исполняемого кода, не принадлежит пользователю root и группе Wheel или доступен для записи группе или «другому», попытка загрузить загружаемый модуль ядра завершится неудачно. . [16]
Модули ядра могут дополнительно иметь раздел ELF криптографической подписи, который проверяется при загрузке в зависимости от настроек политики проверенной загрузки. Ядро может обеспечить криптографическую подпись модулей набором доверенных сертификатов; список доверенных сертификатов хранится вне ОС в ILOM на некоторых платформах на базе SPARC. Загрузка модуля ядра, инициированная пользовательским пространством, возможна только по доверенному пути, когда система работает с включенной функцией неизменяемой глобальной зоны.