Chapter 15. The Annobin project

The Annobin project is an implementation of the Watermark specification project. Watermark specification project intends to add markers to Executable and Linkable Format (ELF) objects to determine their properties. The Annobin project consists of the annobin plugin and the annockeck program.

The annobin plugin scans the GNU Compiler Collection (GCC) command line, the compilation state, and the compilation process, and generates the ELF notes. The ELF notes record how the binary was built and provide information for the annocheck program to perform security hardening checks.

The security hardening checker is part of the annocheck program and is enabled by default. It checks the binary files to determine whether the program was built with necessary security hardening options and compiled correctly. annocheck is able to recursively scan directories, archives, and RPM packages for ELF object files.

Note

The files must be in ELF format. annocheck does not handle any other binary file types.

The following section describes how to:

  • Use the annobin plugin
  • Use the annocheck program
  • Remove redundant annobin notes

15.1. Using the annobin plugin

The following section describes how to:

  • Enable the annobin plugin
  • Pass options to the annobin plugin

15.1.1. Enabling the annobin plugin

The following section describes how to enable the annobin plugin via gcc and via clang.

Procedure

  • To enable the annobin plugin with gcc, use:

    $ gcc -fplugin=annobin
    • If gcc does not find the annobin plugin, use:

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

      Replace /path/to/directory/containing/annobin/ with the absolute path to the directory that contains annobin.

    • To find the directory containing the annobin plugin, use:

      $ gcc --print-file-name=plugin
  • To enable the annobin plugin with clang, use:

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

    Replace /path/to/directory/containing/annobin/ with the absolute path to the directory that contains annobin.

15.1.2. Passing options to the annobin plugin

The following section describes how to pass options to the annobin plugin via gcc and via clang.

Procedure

  • To pass options to the annobin plugin with gcc, use:

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

    Replace option with the annobin command line arguments and replace file-name with the name of the file.

    Example

    • To display additional details about what annobin it is doing, use:

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

      Replace file-name with the name of the file.

  • To pass options to the annobin plugin with clang, use:

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

    Replace option with the annobin command line arguments and replace /path/to/directory/containing/annobin/ with the absolute path to the directory containing annobin.

    Example

    • To display additional details about what annobin it is doing, use:

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

      Replace file-name with the name of the file.

15.2. Using the annocheck program

The following section describes how to use annocheck to examine:

  • Files
  • Directories
  • RPM packages
  • annocheck extra tools
Note

annocheck recursively scans directories, archives, and RPM packages for ELF object files. The files have to be in the ELF format. annocheck does not handle any other binary file types.

15.2.1. Using annocheck to examine files

The following section describes how to examine ELF files using annocheck.

Procedure

  • To examine a file, use:

    $ annocheck file-name

    Replace file-name with the name of a file.

Note

The files must be in ELF format. annocheck does not handle any other binary file types. annocheck processes static libraries that contain ELF object files.

Additional information

  • For more information about annocheck and possible command line options, see the annocheck man page.

15.2.2. Using annocheck to examine directories

The following section describes how to examine ELF files in a directory using annocheck.

Procedure

  • To scan a directory, use:

    $ annocheck directory-name

    Replace directory-name with the name of a directory. annocheck automatically examines the contents of the directory, its sub-directories, and any archives and RPM packages within the directory.

Note

annocheck only looks for ELF files. Other file types are ignored.

Additional information

  • For more information about annocheck and possible command line options, see the annocheck man page.

15.2.3. Using annocheck to examine RPM packages

The following section describes how to examine ELF files in an RPM package using annocheck.

Procedure

  • To scan an RPM package, use:

    $ annocheck rpm-package-name

    Replace rpm-package-name with the name of an RPM package. annocheck recursively scans all the ELF files inside the RPM package.

Note

annocheck only looks for ELF files. Other file types are ignored.

  • To scan an RPM package with provided debug info RPM, use:

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

    Replace rpm-package-name with the name of an RPM package, and debuginfo-rpm with the name of a debug info RPM associated with the binary RPM.

Additional information

  • For more information about annocheck and possible command line options, see the annocheck man page.

15.2.4. Using annocheck extra tools

annocheck includes multiple tools for examining binary files. You can enable these tools with the command-line options.

The following section describes how to enable the:

  • built-by tool
  • notes tool
  • section-size tool

You can enable multiple tools at the same time.

Note

The hardening checker is enabled by default.

15.2.4.1. Enabling the built-by tool

You can use the annocheck built-by tool to find the name of the compiler that built the binary file.

Procedure

  • To enable the built-by tool, use:

    $ annocheck --enable-built-by

Additional information

  • For more information about the built-by tool, see the --help command-line option.

15.2.4.2. Enabling the notes tool

You can use the annocheck notes tool to display the notes stored inside a binary file created by the annobin plugin.

Procedure

  • To enable the notes tool, use:

    $ annocheck --enable-notes

    The notes are displayed in a sequence sorted by the address range.

Additional information

  • For more information about the notes tool, see the --help command-line option.

15.2.4.3. Enabling the section-size tool

You can use the annocheck section-size tool display the size of the named sections.

Procedure

  • To enable the section-size tool, use:

    $ annocheck --section-size=name

    Replace name with the name of the named section. The output is restricted to specific sections. A cumulative result is produced at the end.

Additional information

  • For more information about the section-size tool, see the --help command-line option.

15.2.4.4. Hardening checker basics

The hardening checker is enabled by default. You can disable the hardening checker with the --disable-hardened command-line option.

15.2.4.4.1. Hardening checker options

The annocheck program checks the following options:

  • Lazy binding is disabled using the -z now linker option.
  • The program does not have a stack in an executable region of memory.
  • The relocations for the GOT table are set to read only.
  • No program segment has all three of the read, write and execute permission bits set.
  • There are no relocations against executable code.
  • The runpath information for locating shared libraries at runtime includes only directories rooted at /usr.
  • The program was compiled with annobin notes enabled.
  • The program was compiled with the -fstack-protector-strong option enabled.
  • The program was compiled with -D_FORTIFY_SOURCE=2.
  • The program was compiled with -D_GLIBCXX_ASSERTIONS.
  • The program was compiled with -fexceptions enabled.
  • The program was compiled with -fstack-clash-protection enabled.
  • The program was compiled at -O2 or higher.
  • The program does not have any relocations held in a writeable.
  • Dynamic executables have a dynamic segment.
  • Shared libraries were compiled with -fPIC or -fPIE.
  • Dynamic executables were compiled with -fPIE and linked with -pie.
  • If available, the -fcf-protection=full option was used.
  • If available, the -mbranch-protection option was used.
  • If available, the -mstackrealign option was used.
15.2.4.4.2. Disabling the hardening checker

The following section describes how to disable the hardening checker.

Procedure

  • To scan the notes in a file without the hardening checker, use:

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

    Replace file-name with the name of a file.

15.3. Removing redundant annobin notes

Using annobin increases the size of binaries. To reduce the size of the binaries compiled with annobin you can remove redundant annobin notes. To remove the redundant annobin notes use the objcopy program, which is a part of the binutils package.

Procedure

  • To remove the redundant annobin notes, use:

      $ objcopy --merge-notes file-name

    Replace file-name with the name of the file.