内核对其他二进制格式的支持 (binfmt_misc)

此内核功能允许您通过在 shell 中简单地键入其名称来调用几乎所有程序(对于限制,请参见下文)。这包括例如已编译的 Java(TM)、Python 或 Emacs 程序。

要实现此目的,您必须告诉 binfmt_misc 哪个解释器必须使用哪个二进制文件调用。Binfmt_misc 通过将文件开头的某些字节与您提供的幻数字节序列(屏蔽掉指定的位)进行匹配来识别二进制文件类型。Binfmt_misc 还可以识别文件名扩展名,例如 .com.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 下;由于显而易见的原因,不能包含斜杠 /

  • type

    是识别的类型。对于幻数,请提供 M,对于扩展名,请提供 E

  • offset

    是文件中幻数/掩码的偏移量,以字节为单位计数。如果您省略它,则默认为 0(即,您编写 :name:type::magic...)。使用文件名扩展名匹配时忽略。

  • magic

    是 binfmt_misc 匹配的字节序列。幻数字符串可以包含十六进制编码的字符,例如 \x0a\xA4。请注意,您必须转义任何 NUL 字节;解析在第一个字节处停止。在 shell 环境中,您可能必须编写 \\x0a 以防止 shell 吃掉您的 \。如果您选择文件名扩展名匹配,则这是要识别的扩展名(不带 .,不允许使用 \x0a 特殊字符)。扩展名匹配区分大小写,并且不允许使用斜杠 /

  • mask

    是一个(可选的,默认为全部 0xff)掩码。您可以通过提供类似于幻数并且与幻数一样长的字符串来屏蔽掉匹配中的某些位。掩码与文件的字节序列进行与运算。请注意,您必须转义任何 NUL 字节;解析在第一个字节处停止。使用文件名扩展名匹配时忽略。

  • interpreter

    是应该使用二进制文件作为第一个参数调用的程序(指定完整路径)

  • flags

    是一个可选字段,用于控制解释器调用的几个方面。它是大写字母的字符串,每个字母控制某个方面。支持以下标志

    P - 保留 argv[0]

    binfmt_misc 的传统行为是用二进制文件的完整路径覆盖原始的 argv[0]。当包含此标志时,binfmt_misc 将为此目的向参数向量添加一个参数,从而保留原始的 argv[0]。例如,如果您的 interp 设置为 /bin/foo 并且您运行 blah(位于 /usr/local/bin 中),则内核将执行 /bin/foo,并将 argv[] 设置为 ["/bin/foo", "/usr/local/bin/blah", "blah"]。interp 必须意识到这一点,以便可以使用设置为 ["blah"]argv[] 执行 /usr/local/bin/blah

    O - 打开二进制文件

    binfmt_misc 的传统行为是将二进制文件的完整路径作为参数传递给解释器。当包含此标志时,binfmt_misc 将打开文件以进行读取,并传递其描述符作为参数,而不是完整路径,从而允许解释器执行不可读的二进制文件。应谨慎使用此功能 - 必须信任解释器不会发出不可读二进制文件的内容。

    C - 凭据

    当前,binfmt_misc 的行为是根据解释器计算新进程的凭据和安全令牌。当包含此标志时,将根据二进制文件计算这些属性。它还暗示了 O 标志。应谨慎使用此功能,因为当使用 binfmt_misc 运行 root 拥有的 setuid 二进制文件时,解释器将以 root 权限运行。

    F - 修复二进制文件

    binfmt_misc 的通常行为是在调用 misc 格式文件时延迟生成二进制文件。但是,这在面对挂载命名空间和 changeroots 时效果不佳,因此 F 模式会在安装模拟时立即打开二进制文件,并使用打开的映像来生成模拟器,这意味着一旦安装,无论环境如何更改,它始终可用。

有一些限制

  • 整个注册字符串不得超过 1920 个字符

  • 幻数必须位于文件的前 128 个字节中,即 offset+size(magic) 必须小于 128

  • 解释器字符串不得超过 127 个字符

要使用 binfmt_misc,您必须首先挂载它。您可以使用 mount -t binfmt_misc none /proc/sys/fs/binfmt_misc 命令来挂载它,或者您可以将行 none  /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0 添加到您的 /etc/fstab,以便它在启动时自动挂载。

您可能需要在启动期间的 /etc/rc 脚本之一中添加二进制格式。请阅读您的 init 程序的手册,以了解如何正确执行此操作。

考虑添加条目的顺序!稍后添加的条目首先匹配!

一些示例(假设您在 /proc/sys/fs/binfmt_misc 中)

  • 启用对 em86 的支持(类似于 binfmt_em86,仅适用于 Alpha AXP)

    echo ':i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
    echo ':i486:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
    
  • 启用对打包的 DOS 应用程序的支持(预配置的 dosemu hdimages)

    echo ':DEXE:M::\x0eDEX::/usr/bin/dosexec:' > register
    
  • 启用使用 wine 的 Windows 可执行文件的支持

    echo ':DOSWin:M::MZ::/usr/local/bin/wine:' > register
    

有关 Java 支持,请参见 Linux v1.03 的 Java(tm) 二进制内核支持

您可以通过将 0(禁用)或 1(启用)回显到 /proc/sys/fs/binfmt_misc/status/proc/.../the_name 来启用/禁用 binfmt_misc 或一种二进制类型。使用 cat 命令查看该文件将告诉您 binfmt_misc/the_entry 的当前状态。

您可以通过将 -1 回显到 /proc/.../the_name/proc/sys/fs/binfmt_misc/status 来删除一个条目或所有条目。

提示

如果您想向您的解释器传递特殊的参数,您可以为其编写一个包装脚本。请参阅 Documentation/admin-guide/java.rst 获取示例。

您的解释器不应该在 PATH 中查找文件名;内核会传递给它要使用的完整文件名(或文件描述符)。使用 $PATH 可能会导致意外行为,并且可能存在安全隐患。

Richard Günther <rguenth@tat.physik.uni-tuebingen.de>