Bug 23535

Summary: gold needs to produce two PT_NOTE segments with ELFCLASS64
Product: binutils Reporter: Florian Weimer <fweimer>
Component: goldAssignee: Cary Coutant <ccoutant>
Status: NEW ---    
Severity: normal CC: ian, mark
Priority: P2 Flags: fweimer: security-
Version: 2.31   
Target Milestone: ---   
See Also: https://sourceware.org/bugzilla/show_bug.cgi?id=28494
Host: Target:
Build: Last reconfirmed:

Description Florian Weimer 2018-08-16 14:19:10 UTC
On ELFCLASS64 targets, the GNU gABI requires 4-byte alignment for NT_GNU_ABI_TAG and NT_GNU_BUILD_ID, and 8-byte alignment for everything else.

Current gold puts NT_GNU_PROPERTY_TYPE_0 notes into a 4-byte aligned segment, where they are ignored by the glibc dynamic loader.  This is an interoperability issue that needs to be address one way or the other.

Further discussion:

https://sourceware.org/ml/binutils/2018-08/msg00292.html
Comment 1 H.J. Lu 2018-08-17 14:55:44 UTC
A testcase:

[hjl@gnu-17 tmp]$ cat x.S
	.text
	.globl	_start
	.type	_start, @function
_start:
	ret

	.section ".note", "a"
#ifdef __LP64__
	.p2align 3
#else
	.p2align 2
#endif
	.long 1f - 0f		/* name length.  */
	.long 3f - 1f		/* data length.  */
	.long  12345		/* note type.  */
0:
	.asciz "GNU"		/* vendor name.  */
1:
#ifdef __LP64__
	.p2align 3
#else
	.p2align 2
#endif
	.long 0			/* pr_type.  */
	.long 5f - 4f		/* pr_datasz.  */
4:
	.zero 0x10
5:
#ifdef __LP64__
	.p2align 3
#else
	.p2align 2
#endif
3:
[hjl@gnu-17 tmp]$ gcc -c x.S -B/bin/
[hjl@gnu-17 tmp]$ ld.gold --build-id x.o
[hjl@gnu-17 tmp]$ readelf -SlW a.out | grep NOTE
  [ 1] .note             NOTE            00000000004000e8 0000e8 000028 00   A  0   0  8
  [ 2] .note.gnu.build-id NOTE            0000000000400110 000110 000024 00   A  0   0  4
  [ 6] .note.gnu.gold-version NOTE            0000000000000000 001000 00001c 00      0   0  4
  NOTE           0x0000e8 0x00000000004000e8 0x00000000004000e8 0x00004c 0x00004c R   0x8

It is wrong to place note sections with 4 byte alignment in a NOTE segment
with 8 byte alignment.

[hjl@gnu-17 tmp]$ ld.bfd --build-id x.o
[hjl@gnu-17 tmp]$ readelf -SlW a.out | grep NOTE
  [ 1] .note             NOTE            0000000000400120 000120 000028 00   A  0   0  8
  [ 2] .note.gnu.build-id NOTE            0000000000400148 000148 000024 00   A  0   0  4
  NOTE           0x000120 0x0000000000400120 0x0000000000400120 0x000028 0x000028 R   0x8
  NOTE           0x000148 0x0000000000400148 0x0000000000400148 0x000024 0x000024 R   0x4
[hjl@gnu-17 tmp]$
Comment 2 Sourceware Commits 2020-10-13 12:30:15 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6bf4a34047452f882c5cc66bd85812ee1bb5a41c

commit 6bf4a34047452f882c5cc66bd85812ee1bb5a41c
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Oct 13 05:18:13 2020 -0700

    gold: Properly align the NT_GNU_PROPERTY_TYPE_0 note
    
    The NT_GNU_PROPERTY_TYPE_0 note should be aligned to 8 bytes for 64-bit
    ELF as specified by gABI.  A note section can be only placed in a PT_NOTE
    segment with the same alignment.
    
            PR gold/22914
            PR gold/23535
            * layout.cc (Layout::attach_allocated_section_to_segment): Place
            a note section in a PT_NOTE segment with the same alignment.  Set
            the alignment of the PT_NOTE segment from the alignment of the
            note section.
            (Layout::create_note): Align the NT_GNU_PROPERTY_TYPE_0 note to 8
            bytes for 64-bit ELF.
            (Layout::segment_precedes): Place segments with larger alignments
            first.
            * output.cc (Output_segment::Output_segment): Initialize align_.
            * output.h (Output_segment): Add align, set_align and align_.
            * testsuite/Makefile.am (gnu_property_test.stdout): Pass -lhSWn
            to $(TEST_READELF).
            (gnu_property_test): Pass --build-id to ld.
            * testsuite/Makefile.in: Regenerated.
            * testsuite/gnu_property_test.sh (check_alignment): New.
            Use check_alignment to check the NT_GNU_PROPERTY_TYPE_0 note
            alignment.  Verify that there are 2 PT_NOTE segments.