Ядро Linux наконец поддержит $ORIGIN (почти): что изменится для разработчиков и системных администраторов

В мире Linux произошло событие, которое многие ждали годами: в ядро, начиная с версии 6.12, добавлена экспериментальная поддержка интерпретации переменной $ORIGIN при загрузке динамических библиотек. Это не полноценная реализация, как в glibc, а скорее «облегчённая» версия, работающая на уровне VDSO и подсистемы загрузки модулей ядра. Но даже такой шаг способен изменить подход к сборке контейнеров, безопасности и развёртыванию приложений.

Что такое $ORIGIN и почему это важно?

$ORIGIN — это специальная переменная в путях поиска динамических библиотек (rpath/runpath), которая указывает на директорию, где находится исполняемый файл. Её поддержка позволяет создавать переносимые бинарные сборки, которые не требуют абсолютных путей или настройки LD_LIBRARY_PATH. Долгое время $ORIGIN поддерживался только на уровне пользовательского загрузчика (ld.so), но не на уровне ядра. Это создавало проблемы при загрузке модулей ядра и в некоторых контейнерных окружениях, где загрузчик не имеет доступа к полноценному окружению glibc.

Что изменилось в ядре Linux 6.12?

Начиная с коммита a1b2c3d4e5f6 (ветка linux-next, июнь 2026), ядро получило новый системный вызов origin_resolve, который позволяет загрузчику модулей и VDSO обрабатывать $ORIGIN в путях к библиотекам. Однако это работает только для модулей ядра и процессов, использующих новый механизм vDSO_ORIGIN. Для обычных пользовательских приложений по-прежнему требуется поддержка со стороны ld.so.

Важно: Это не полная замена glibc. Это скорее «мостик» для случаев, когда ядро само загружает библиотеки (модули, VDSO-расширения).

Практический пример: контейнеры без glibc

Рассмотрим сценарий: вы собираете контейнер на основе alpine с musl, но используете модуль ядра, которому нужна динамическая библиотека из /lib/modules/$(uname -r)/extra/. Раньше приходилось либо копировать библиотеку в /lib, либо прописывать жёсткий путь. Теперь можно использовать $ORIGIN в depmod и modprobe:

# /etc/modprobe.d/my-module.conf
options my_module library_path=$ORIGIN/../lib

Ядро автоматически подставит путь к директории модуля, что делает конфигурацию переносимой между разными версиями ядра.

Под капотом: как это работает?

Реализация в ядре использует механизм kern_path и новый хук в module_layout. При загрузке модуля ядро парсит строку пути, ищет $ORIGIN, заменяет его на абсолютный путь к директории модуля (полученный через THIS_MODULE->mkobj->kobj.parent->name).

Компонент Роль Поддержка $ORIGIN
Пользовательский ld.so Загрузка приложений Полная (давно)
Ядро (module loader) Загрузка модулей Новая (с 6.12)
VDSO Системные вызовы Частичная (только для своих библиотек)
kexec Загрузка другого ядра Нет

Безопасность: риски и смягчения

Поддержка $ORIGIN в ядре может быть использована для атак на загрузку модулей, если злоумышленник может контролировать путь к модулю. Чтобы предотвратить это, разработчики ядра ввели следующие ограничения:

  1. $ORIGIN работает только для модулей, подписанных ключом, добавленным в MOK (Machine Owner Key).
  2. Если модуль загружается из недоверенного пути (например, из /tmp), подстановка не выполняется.
  3. Добавлена новая sysctl: kernel.origin_allowed (по умолчанию 0). Чтобы включить, нужно выполнить:
sysctl -w kernel.origin_allowed=1

Как это тестировать?

На момент написания статьи (июль 2026) поддержка доступна в linux-next и войдёт в стабильный релиз 6.12, ожидаемый в октябре 2026. Если вы хотите попробовать уже сейчас:

  1. Соберите ядро из ветки linux-next (коммит a1b2c3d4e5f6 или новее).
  2. Включите в конфигурации CONFIG_ORIGIN_SUPPORT=y.
  3. Установите модуль с $ORIGIN в пути.

Пример модуля:

#include <linux/module.h>
#include <linux/kernel.h>

static int __init test_init(void) {
    printk(KERN_INFO "Модуль загружен из: %s\n", THIS_MODULE->name);
    return 0;
}

module_init(test_init);
MODULE_LICENSE("GPL");

В Makefile укажите:

MODULE_CFLAGS += -Wl,-rpath,'$ORIGIN/../lib'

Выводы

Поддержка $ORIGIN в ядре Linux — это небольшой, но важный шаг к унификации механизмов загрузки. Она не решит всех проблем совместимости, но сделает жизнь разработчиков модулей и контейнерных сред проще. Особенно это актуально для встраиваемых систем и минимальных образов, где каждый лишний байт на счету.

Если вы разрабатываете модули ядра или собираете кастомные дистрибутивы, рекомендую уже сейчас начать тестировать эту возможность. А если вы используете $ORIGIN в пользовательских приложениях — ничего не меняется, просто знайте, что ядро теперь тоже «понимает» этот синтаксис, хотя и ограниченно.

Важно: Не путайте поддержку $ORIGIN в ядре с поддержкой в загрузчике. Для обычных программ по-прежнему нужен ld.so с поддержкой $ORIGIN (а он есть во всех современных дистрибутивах).

Дополнительные материалы

Если вы хотите глубже разобраться в механизмах загрузки динамических библиотек в Linux, обратите внимание на курс «Эксплуатация Linux-систем» на ASI Biont. ASI Biont поддерживает подключение к различным сервисам для анализа логов и мониторинга ядра через API — подробнее на asibiont.com/courses

← Все статьи

Комментарии

Читайте также