Поддержка ядром произвольных двоичных форматов (binfmt_misc)

Благодаря данной особенности ядра вы можете запускать большинство програм просто написав имя исполнимого файла в оболочке. Это могут быть даже программы предназначенные для других ОС или аппаратных платформ.

Для того, чтобы воспользоваться этой возможностью вы должны объяснить подсистеме binfmt_misc какой интерпретатор использовать для запуска конкретных бинарных файлов. Binfmt_misc определяет тип бинарных файлов по совпадению некоторых байт в начале файла с заданной маской - "магической" последовательностью (могут сравниваться отдельные биты). Также binfmt_misc может определять тип файла просто по расширению, например .jar или .exe.

Для начала вам нужно выполнить монтирование binfmt_misc:

#> mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc

Теперь для регистрации нового типа бинарных файлов вам достаточно сформировать примерно такую строку :name:type:offset:magic:mask:interpreter:flags и записать её в /proc/sys/fs/binfmt_misc/register. Разберёмся, что означают поля в нашей строке:

  • name

    Это идентификатор нашего формата. Новый /proc-файл будет создан с именем /proc/sys/fs/binfmt_misc/name. По вполне очевидным причинам этот идентификатор не может содержать слэшей (/).

  • type

    Тип распознавания файла. M (magic) для соответствия по заданному шаблону или E (extension) для определения по расширению файла.

  • offset

    Смещение magic/mask от начала файла в байтах. По умолчанию равно 0 и вы можете не указывать его (например :name:type::magic...). Не используется при идентификации типа файла по расширению.

  • magic

    Строка с последовательностью байт, по которой binfmt_misc определяет тип файла. Эта строка может содержать байты в шестнадцатиричной кодировке наподобие \x0a или \xA4. Нужно помнить, что все нулевые байты должны быть экранированы, так как разбор строки прекращается на первом нулевом байте. Если выбран тип определения по расширению файла, то строка должна быть равна нужному расширению без точки (.) и не может содержать шестнадцатиричных кодов и слэшей.

  • mask

    Опциональная маска для magic (по умолчания все байты равны 0xff). С помощью этой маски вы можете определить только конкретные биты файла для соответствия байтам magic. К последовательности байт из файла применяется операция побитового AND с маской. Не используется при идентификации типа файла по расширению.

  • interpreter

    Эта программа будет запущена с бинарным файлом в качестве первого аргумента (содержит полный путь к файлу).

  • flags

    Опциональное поле, которое позволяет контролировать некоторые аспекты запуска интерпритатора. Представляет собой набор флагов (строку из заглавных букв), каждый из которых определяет соответствующее поведение. Поддерживаются такие флаги:

    • P - preserve-argv[0]
    • O - open-binary
    • C - credentials
    • F - fix binary

Существующие ограничения:

  • строка регистрации бинарного формата не может превышать 1920 символов
  • magic поле должно находиться в первых 128 байтах файла (offset+size(magic) должно быть меньше 128)
  • строка названия интерпретатора не должна превышать 127 символов

Для начала использования binfmt_misc он должен быть предварительно смонтирован в нужное место. Вы можете это сделать с помощью команды

#> mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
или путём добавления в /etc/fstab такой строки
none  /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0
для автоматического монтирование при загрузке системы.

При добавлении нескольких форматов порядок добавления важен! Последний добавленный проверяется первым!

Несколько примеров использования:

поддержка исполнимых файлов Windows при помощи wine:

#> echo ':DOSWin:M::MZ::/usr/local/bin/wine:' > /proc/sys/fs/binfmt_misc/register

Вы можете активировать или деактивировать обработку определённых форматов файлов простой записью 1 (активировать) или 0 (деактивировать) в соответствующий /proc/sys/fs/binfmt_misc/type_name файл. Тут type_name - идентификатор формата фала. Для примера, приведённого выше, деактивация будет иметь вид:

#> echo '0' > /proc/sys/fs/binfmt_misc/DOSWin
а активация, соответственно:
#> echo '1' > /proc/sys/fs/binfmt_misc/DOSWin

Для глобального включения/отключения данной функциональности можно записать 0 или 1 в файл /proc/sys/fs/binfmt_misc/status.