Subject: ld: arm64 executables with no static data can't be loaded

From: Ben Hutchings <[email-masked]>
Date: Sat, 06 Aug 2022 00:39:45 +0200

Package: binutils
Version: 2.38.90.20220713-2
Severity: normal

I'm doing some test builds of klibc
<https://git.kernel.org/pub/scm/libs/klibc/klibc.git> and found a
regression for arm64.  The last time I was working on klibc was late
January, so this is probably a regression after 2.38.

To reproduce:

    git clone https://git.kernel.org/pub/scm/libs/klibc/klibc.git
    cd klibc
    # Link to kernel UAPI headers
    mkdir -p linux/include
    for x in /usr/include/linux /usr/include/asm-generic \
        /usr/include/aarch64-linux-gnu/asm; do
        ln -s $x linux/include
    done
    make test
    # Change interpreter so no installation required
    patchelf --set-interpreter usr/klibc/klibc.so usr/klibc/tests/sigint.shared
    # This should show execve() failing with EFAULT, then SIGSEGV
    strace usr/klibc/tests/sigint.shared

The reason for this seems to be that:

1. The BSS section is not page-aligned (it starts at 0xffe8).
2. The kernel's ELF loader assumes that a non-page-aligned BSS section
   is placed immediately after a writable data section in memory, and
   tries to clear memory from the start of the BSS section up to the
   page boundary.
3. In this case, there is no data section and no file mapping before
   the BSS, so this results in an EFAULT.  This happens past the point
   of no return, so the kernel kills the process.

With older versions of binutils, the BSS section was still misaligned
but started within the same 4K page as another section (though it
wasn't the .data section).

It seems like binutils now tries to align the BSS section (or the data
section, if there is one) to a 64K boundary, so that read-only and
read-write sections won't end up in the same page even on Arm systems
using 64K pages.  But some existing bug causes the alignment to be
slightly off, so this doesn't work and causes this regression for
systems with smaller pages.

I've previously hit a different bug in QEMU's ELF loader with these
executables that lack static data, so maybe I should just accept that
they're liable to break and add some dummy static data to klibc's
executables.

The apparent misalignment does seem worth investigating, regardless of
whether I can work around this in klibc.

Ben.

-- System Information:
Debian Release: bookworm/sid
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'oldstable-updates'), (500, 'unstable'), (500, 'oldstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.18.0-3-amd64 (SMP w/2 CPU threads; PREEMPT)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages binutils depends on:
ii  binutils-common            2.38.90.20220713-2
ii  binutils-x86-64-linux-gnu  2.38.90.20220713-2
ii  libbinutils                2.38.90.20220713-2

binutils recommends no packages.

Versions of packages binutils suggests:
ii  binutils-doc  2.38.90.20220713-2

-- debconf-show failed