4.2.4 What to do if annocheck reports that it could not find compiled code.

The hardening checker will automatically skip some tests if it cannot prove that the file being checked was created by a known compiler, or if the code was created from assembler sources, rather than a high level language. This is because the test being skipped is checking for a specific feature of a specific compiler.

The checker uses several different methods for determining if an executable was compiled:

notes

If there are annobin notes present, these include a description of the compiler used to create the executable.

DWARF

If DWARF debug information is available, the compiler can usually be found in the DW_AT_producer tag.

comment

If there is a .comment section in the file, then this usually contains the name of the compiler.

GO note

The presence of a .note.go.buildid section indicates that the file contains GO compiler code.

GO symbol

The presence of a variable called ‘go1.<V>’ in the read-only data section. Again this indicates the presence of GO compiled code.

executable segments

If the file contains one or more program segments with the executable flag set, then this indicates that it is likely to contain compiled code.

There are several reasons why annocheck might think that the file does not originate from compiled source code:

fake assembler

Sometimes when compiling code it is desireable to be able to build it without certain security options, but also without annocheck complaining about them. This is used by glibc for example because it does not use stack checking or function fortification.

This effect can be achieved with GCC by using the -Wa,--generate-missing-build-notes command line option. This tells the assembler to generate a fake annobin note that tells annocheck to treat all of the code as if it has been produced from assembler sources and to ignore tests specific to high level languages.

real assembler

The file was created from assembler source code or some other low level language. In this case futher manual checking is warranted. If the source code has not been written with the particular security feature in mind, then it may be vulnerable.

If on the other hand it does not need the security feature or it has been written to support it, then adding an annobin note to the assembler sources will stop annocheck from complaining.

For example the following will add a note about strong stack protection:

	.pushsection .gnu.build.attributes, "o", %note, .text
	.balign 4
	.dc.l 2f - 1f	# Size of the name field.
	.dc.l 0		# Empty description field.
	.dc.l 0x100	# This is an OPEN note which applies to all the code in the covered region.
      1:
	.dc.b 'G', 'A', # This is a GNU attribute
        .dc.b '*'       # It contains a numeric value
        .dc.b 0x2       # For the -fstack-protector option
        .dc.b 0x3       # The value is 3, which indicated -fstack-protector-strong
        .dc.b 0         # Since this field is nominally a name, it ends with a NUL byte.
      2:
	.dc.b 0, 0 	# Padding to ensure note ends on a 4 byte boundary.
	.popsection

Compiling a simple C program with the -S -fverbose-asm -fplugin=annobin <security option> options should provide an example of how to encode a note about <security option>.

Note - in order for annobin notes to work at least one of them needs to specify the address range that they cover. This is usually done by a version note, which details the version number of the tool used to produce the code. For assembler this note would look like this:

	.pushsection .gnu.build.attributes, "o", %note, .text
	.balign 4
	.dc.l 2f - 1f   # Size of the name field.
	.dc.l 16	# Size of the description field (= 2 * sizeof (address)).
	.dc.l 0x100	# This is an OPEN note which applies to all the code in the covered region.
      1:
	.dc.b 'G', 'A', # This is a GNU Attribute note.
        .dc.b '$'       # It contains a string value.
        .dc.b 0x1       # The string is a VERSION string.
        .dc.b '3',      # Version 3 of the Watermark Protocol is being used.
        .dc.b 'a',      # The code has been produced by an 'a'ssembler.
        .dc.b '2'       # The assembler's major version number is 2.
        .dc.b 0         # Since this field is nominally a name, it ends with a NUL byte.
      2:
                        # Coincidentally, no padding is needed here.
        .quad <insert-start-symbol-here>
	.quad <insert-end-symbol-here>
	.popsection
unsupported source language

The file was created by compiling high-level language source code, but in a language with which annocheck is unfamiliar. In this case it may still make sense to skip the test, if it is checking for a feature that is not supported by the language’s compiler.

annobin annotation not enabled

The file was created by compiling C and/or C++ but without any annobin notation enabled, and without any debug information generation. In this case there may be a problem, since the test being skipped might actually fail if annocheck knew that the file was compiled.

Fixing this problem involves investigating how the executable was built and adding the necessary rules to invoke the annobin plugin and the sought after security hardening options.

stripped of symbols and notes

The file was built normally, but then stripped of most of the useful information, including its symbol table, debug information, annobin notes and so on.

Restoring the stripped information should solve this problem.