Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20260902205500.GX23438@brightrain.aerifal.cx>
Date: Wed, 2 Sep 2026 16:55:01 -0400
From: Rich Felker <dalias@...c.org>
To: Xusheng Zhi <xusheng142@...il.com>
Cc: musl@...ts.openwall.com
Subject: Re: [BUG] ldso applies load bias to SHN_ABS symbols during
 x86_64 R_X86_64_64 relocation

On Wed, Sep 02, 2026 at 03:15:28PM -0500, Xusheng Zhi wrote:
> Hello,
> 
> I believe musl's dynamic linker applies the load bias to an x86-64
> R_X86_64_64 relocation when the resolved symbol definition is SHN_ABS.
> 
> The expected result for R_X86_64_64 is S + A. For an SHN_ABS symbol, the ELF
> gABI says the symbol value is absolute and is not affected by relocation.
> The
> observed affected behavior is B + S + A, where B is the load base of the DSO
> that defines the absolute symbol.
> 
> Minimal reproducer:
> 
>   See the attached repro/ directory.
> 
>   bash repro/repro.sh
> 
> The reproducer builds:
> 
>   * libabs_provider.so, which exports:
>       abs_sym = 0x12345678
>     as an SHN_ABS symbol.
> 
>   * main, a freestanding PIE containing one data slot:
>       .quad abs_sym + 1
> 
>     The PIE exits 0 if the relocated slot equals 0x12345679, otherwise it
> exits
>     42.
> 
> Observed locally:
> 
>   This reproduces with the system musl 1.2.4 loader from Ubuntu's musl
> 1.2.4-2
>   package and with a local build of the official musl 1.2.6 release tarball.
> 
>     glibc loader: 0
>     musl 1.2.4 loader: 42
>     musl 1.2.6 loader: 42
> 
>     provider symbol:
>       0000000012345678     8 OBJECT  GLOBAL DEFAULT  ABS abs_sym
> 
>     main relocation:
>       R_X86_64_64 abs_sym + 1
> 
> Expected:
> 
>   The relocated slot should be 0x12345679, and the reproducer should exit 0.
> 
> Actual on the affected musl loader:
> 
>   The reproducer exits 42 when run through musl's loader. The same binary
> exits
>   0 with glibc's loader.
> 
> Root-cause pointer:
> 
>   On x86-64, R_X86_64_64 uses the symbolic relocation path. In
> ldso/dynlink.c,
>   the resolved symbol value appears to be computed as laddr(def.dso,
>   def.sym->st_value) for all definitions. That is correct for
> section-relative
>   symbol values, but not for SHN_ABS definitions, where st_value is already
>   absolute.
> 
> Source pointer and possible minimal fix:
> 
>   In the official musl 1.2.6 release:
> 
>     arch/x86_64/reloc.h:3:
>       #define REL_SYMBOLIC    R_X86_64_64
> 
>     ldso/dynlink.c:453:
>       sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0;
> 
>     ldso/dynlink.c:467:
>       case REL_SYMBOLIC:
> 
>     ldso/dynlink.c:470:
>       *reloc_addr = sym_val + addend;
> 
>   The smallest relocation-only change matching the reproducer appears to be:
> 
>     sym_val = def.sym ? (def.sym->st_shndx == SHN_ABS ? def.sym->st_value :
> (size_t)laddr(def.dso, def.sym->st_value)) : 0;
> 
>   I am presenting this as a root-cause pointer rather than a fully audited
>   patch. There is a similar-looking laddr(def.dso, def.sym->st_value)
> return in
>   the dlsym path at ldso/dynlink.c:2289, but the attached reproducer only
>   covers relocation processing.
> 
> Duplicate search:
> 
>   I searched the musl list archive for SHN_ABS/R_X86_64_64/load-bias
> reports and
>   did not find an existing report for this specific case.
> 
> Environment:
> 
>   musl tested version:
>     musl 1.2.6 release, built locally from:
>       https://musl.libc.org/releases/musl-1.2.6.tar.gz
>       sha256
> d585fd3b613c66151fc3249e8ed44f77020cb5e6c1e635a616d3f9f82460512a
>       configure command:
>         ./configure --prefix=/tmp/verilink-musl-1.2.6.zy4nlJ/install
>     system musl 1.2.4, Ubuntu package 1.2.4-2, also reproduces
>   local loaders used:
>     musl 1.2.6 build:
>       /tmp/verilink-musl-1.2.6.zy4nlJ/musl-1.2.6/lib/libc.so
>     system musl 1.2.4:
>       /lib/ld-musl-x86_64.so.1 -> /lib/x86_64-linux-musl/libc.so
>       sha256
> 6e8ff8ad02f4a3a0b70029577e2eb9df8f6526aea302a60a8d649874d6fa45ea
>   binutils version used for preliminary reproducer:
>     GNU ld 2.42, Ubuntu package 2.42-4ubuntu2.10
>   host OS/kernel/architecture:
>     Ubuntu 24.04.4 LTS
>     Linux Hihi142-Linux 7.0.0-30-generic x86_64 GNU/Linux
>   full local output:
>     repro/build/report-system-musl-1.2.4.txt
>     repro/build/report-upstream-musl-1.2.6.txt
> 
> I am happy to test a proposed patch or adjust the reproducer if this case is
> outside musl's intended dynamic-linker scope.
> 
> If this message is delayed for moderation because I am not subscribed,
> please
> keep me Cc'd on replies.

OK, it looks like the issue is basically that we just don't currently
support SHN_ABS. It's not functionality needed for implementing C or
other languages I'm aware of, but it is functionality that's intended
to be there by the linker, and that's probably useful for certain
things. A couple I can think of offhand are:

1. Letting a shared library provide symbols that are not really
   addresses but rather integer constants, which get patched into the
   referring module's .data at load time.

2. Letting a shared library define addresses of special fixed-address
   maps provided by some OS layer (like the ARM kuser_helper page)
   other than the library. This usage is probably deemed 'unsafe' in a
   modern setting where ASLR is normal, but it would still make sense
   in certain embedded/nommu applications.

I'm fine with adding this, and it look straightforward and not costly.

BTW there was no need for such a verbose report. Just "musl ldso
doesn't support SHN_ABS but we'd like it to" would have sufficed. :-)

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.