4.6. Annobin 项目

Annobin 项目是 Watermark 规格项目的实现。水位线规格项目旨在向可执行文件和可链接格式(ELF)对象添加标记,以确定其属性。Annobin 项目由 annobin 插件和 annockeck 程序组成。

anobin 插件扫描 GNU Compiler Collection(GCC)命令行、编译状态和编译过程,并生成 ELF 备注。ELF 备注记录了二进制文件的构建方式,并为 annocheck 程序提供信息来执行安全强化检查。

安全强化检查程序是 annocheck 程序的一部分,默认是启用的。它检查二进制文件,以确定是否使用必要的安全强化选项构建程序。annocheck 能够为 ELF 对象文件递归扫描目录、存档和 RPM 软件包。

注意

这些文件必须采用 ELF 格式。anocheck 不处理任何其他二进制文件类型。

下面的部分描述了如何:

  • 使用 annobin 插件
  • 使用 annocheck 程序
  • 删除冗余 annobin 备注

4.6.1. 使用 annobin 插件

下面的部分描述了如何:

  • 启用 annobin 插件
  • 将选项传递给 annobin 插件

4.6.1.1. 启用 annobin 插件

下面的部分论述了如何通过 gccclang 启用 annobin 插件。

步骤

  • 要启用带有 annobin 插件的 gcc,请使用:

    $ gcc -fplugin=annobin
    • 如果 gcc 找不到 annobin 插件,请使用:

      $ gcc -iplugindir=/path/to/directory/containing/annobin/

      /path/to/directory/containing/annobin/ 替换为包含 annobin 的目录的绝对路径。

    • 要查找包含 annobin 插件的目录,请使用:

      $ gcc --print-file-name=plugin
  • 要启用带有 clanggcc,请使用:

    $ clang -fplugin=/path/to/directory/containing/annobin/

    /path/to/directory/containing/annobin/ 替换为包含 annobin 的目录的绝对路径。

4.6.1.2. 将选项传递给 annobin 插件

下面的部分论述了如何通过 gccclang 将选项传递给 annobin 插件。

步骤

  • 要将选项传递给带有 gccannobin 插件,请使用:

    $ gcc -fplugin=annobin -fplugin-arg-annobin-option file-name

    使用 annobin 命令行参数替换 option,并使用文件名替换 file-name

    示例

    • 要显示 annobin 正在进行的操作的其他详情,请使用:

      $ gcc -fplugin=annobin -fplugin-arg-annobin-verbose file-name

      用文件名替换 file-name

  • 要将选项传递给带有 clangannobin 插件,请使用:

    $ clang -fplugin=/path/to/directory/containing/annobin/ -Xclang -plugin-arg-annobin -Xclang option file-name

    使用 annobin 命令行参数替换 option,并将 /path/to/directory/containing/annobin/ 替换为包含 annobin 的目录的绝对路径。

    示例

    • 要显示 annobin 正在进行的操作的其他详情,请使用:

      $ clang -fplugin=/usr/lib64/clang/10/lib/annobin.so -Xclang -plugin-arg-annobin -Xclang verbose file-name

      用文件名替换 file-name

4.6.2. 使用 annocheck 程序

下面的部分论述了如何使用 annocheck

  • 文件
  • 目录
  • RPM 软件包
  • annocheck 额外工具
注意

annocheck 递归扫描 ELF 对象文件的目录、存档和 RPM 软件包。文件必须采用 ELF 格式。annocheck 不处理任何其他二进制文件类型。

4.6.2.1. 使用 annocheck 检查文件

下面的部分论述了如何使用 annocheck 检查 ELF 文件。

步骤

  • 要检查文件,请使用:

    $ annocheck file-name

    使用文件名替换 file-name

注意

文件必须采用 ELF 格式。anocheck 不处理任何其他二进制文件类型。annocheck 会处理包含 ELF 对象文件的静态库。

附加信息

  • 有关 annocheck 和可用命令行选项的详情请参考 annocheck man page。

4.6.2.2. 使用 annocheck 检查目录

下面的部分论述了如何使用 annocheck 检查目录中的 ELF 文件。

步骤

  • 要扫描目录,请使用:

    $ annocheck directory-name

    使用目录名称替换 directory-nameannocheck 会自动检查目录的内容、其子目录以及该目录中的任何存档和 RPM 软件包。

注意

annocheck 仅查找 ELF 文件。其他文件类型将被忽略。

附加信息

  • 有关 annocheck 和可用命令行选项的详情请参考 annocheck man page。

4.6.2.3. 使用 annocheck 检查 RPM 软件包

下面的部分论述了如何使用 annocheck 检查 RPM 软件包中的 ELF 文件。

步骤

  • 要扫描 RPM 软件包,请使用:

    $ annocheck rpm-package-name

    使用 RPM 软件包的名称替换 rpm-package-namenocheck 会以递归方式扫描 RPM 软件包中的所有 ELF 文件。

注意

annocheck 仅查找 ELF 文件。其他文件类型将被忽略。

  • 要使用提供 debug info RPM 扫描 RPM 软件包,请使用:

    $ annocheck rpm-package-name --debug-rpm debuginfo-rpm

    使用 RPM 软件包的名称替换 rpm-package-name,使用与二进制 RPM 关联的调试信息 RPM 的名称替换 debuginfo-rpm

附加信息

  • 有关 annocheck 和可用命令行选项的详情请参考 annocheck man page。

4.6.2.4. 使用 annocheck 额外的工具

annocheck 包括多个检查二进制文件的工具。您可以使用命令行选项启用这些工具。

下面的部分描述了如何启用:

  • built-by 工具
  • notes 工具
  • section-size 工具

您可以同时启用多个工具。

注意

强化检查程序被默认启用。

4.6.2.4.1. 启用 built-by 工具

您可以使用 annocheck built-by 工具来查找用于构建二进制文件的编译器的名称。

步骤

  • 要启用 built-by 工具,请使用:

    $ annocheck --enable-built-by

附加信息

  • 有关 built-by 工具的更多信息,请参阅 --help 命令行选项。
4.6.2.4.2. 启用 notes 工具

您可以使用 annocheck notes 工具显示存储在 annobin 插件创建的二进制文件中的注释。

步骤

  • 要启用 notes 工具,请使用:

    $ annocheck --enable-notes

    注释按地址范围排序。

附加信息

  • 有关 notes 工具的详情,请查看 --help 命令行选项。
4.6.2.4.3. 启用 section-size 工具

您可以使用 annocheck section-size 工具显示指定部分的大小。

步骤

  • 要启用 section-size 工具,请使用:

    $ annocheck --section-size=name

    使用指定部分的名称替换 name。输出仅限于特定的部分。结束时会生成累积结果。

附加信息

  • 有关 section-size 工具的更多信息,请参阅 --help 命令行选项。
4.6.2.4.4. 强化检查程序基础知识

强化检查程序被默认启用。您可以使用 --disable-hardened 命令行选项禁用强化检查程序。

4.6.2.4.4.1. 强化检查程序选项

annocheck 程序检查以下选项:

  • 使用 -z now linker 选项禁用 lazy 绑定。
  • 该程序没有堆栈在内存中的可执行区域。
  • GOT 表的重新定位被设置为只读。
  • 没有程序片段设置所有三个读取、写入和执行权限。
  • 没有针对可执行代码重新定位。
  • 在运行时查找共享库的 runpath 信息仅包含在 /usr 中根目录。
  • 程序在启用了 annobin 备注的情况下编译。
  • 程序在启用了 -fstack-protector-strong 选项的情况下被编译。
  • 程序使用 -D_FORTIFY_SOURCE=2 编译。
  • 程序使用 -D_GLIBCXX_ASSERTIONS 编译。
  • 程序被编译时启用了 -fexceptions
  • 程序在启用了 -fstack-clash-protection 的情况下被编译。
  • 程序于 -O2 或更高版本编译。
  • 程序没有处于写入状态的重新定位状态。
  • 动态可执行文件具有动态片段。
  • 共享库使用 -fPIC-fPIE 编译。
  • 动态可执行文件使用 -fPIE 编译并通过 -pie 链接。
  • 如果可用,则使用 -fcf-protection=full 选项。
  • 如果可用,则使用 -mbranch-protection 选项。
  • 如果可用,则使用 -mstackrealign 选项。
4.6.2.4.4.2. 禁用强化检查程序

下面的部分论述了如何禁用强化检查程序。

步骤

  • 要在没有强化检查程序的情况下扫描文件中的备注,请使用:

    $ annocheck --enable-notes --disable-hardened file-name

    使用文件名替换 file-name

4.6.3. 删除冗余 annobin 备注

使用 annobin 会增加二进制文件的大小。要减少使用 annobin 编译的二进制文件的大小,您可以删除冗余的 annobin 备注。要删除冗余的 annobin 注释,请使用 objcopy 程序,这是 binutils 软件包的一部分。

步骤

  • 要删除冗余的 annobin 备注,请使用:

      $ objcopy --merge-notes file-name

    用文件名替换 file-name

4.6.4. GCC Toolset 12 中的 annobin 的具体内容

在某些情况下,由于 GCC Toolset 12 中的 annobingcc 之间的同步问题,您的编译可能会失败,并显示类似如下的错误消息:

cc1: fatal error: inaccessible plugin file
opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin/gcc-annobin.so
expanded from short plugin name gcc-annobin: No such file or directory

要临时解决这个问题,请从 annobin.so 文件中创建一个符号链接到 gcc-annobin.so 文件中:

# cd /opt/rh/gcc-toolset-12/root/usr/lib/gcc/architecture-linux-gnu/12/plugin
# ln -s annobin.so gcc-annobin.so

使用您系统中使用的构架替换 architecture

  • aarch64
  • i686
  • ppc64le
  • s390x
  • x86_64