Package: binutils-bpf
Version: 2.44-3+3
Severity: normal
X-Debbugs-Cc: [email protected]
Dear Maintainer,
When linking BPF objects, bpf-ld merges string literals incorrectly. The
resulting literal addresses in the final binary are shifted by one byte,
so literals point into the middle of other merged strings. This breaks
code that relies on correct literal pointers.
Reproduction:
a.c
__attribute__((noinline)) int check_empty(const char *s) {
return s[0] == '\0' ? 0 : 1;
}
__attribute__((noinline)) int check_char(const char *s, char c) {
return s[0] == c ? 0 : 1;
}
b.c
extern int check_empty(const char *s);
extern int check_char(const char *s, char c);
int main(void) {
int r = 0;
r += check_empty("");
r += check_char("w", 'w');
r += check_char("fopen(", 'f');
return r;
}
Build/link
clang -std=c11 -target bpf -mcpu=v4 -O1 -ffreestanding -fno-builtin
-fno-stack-protector -g \
-c a.c -o a.o
clang -std=c11 -target bpf -mcpu=v4 -O1 -ffreestanding -fno-builtin
-fno-stack-protector -g \
-c b.c -o b.o
bpf-ld a.o b.o -e main -o repro.out
Inspect:
readelf -W -S repro.out | rg -n "rodata|str1"
llvm-objdump -s -j .rodata repro.out | head -n 10
llvm-objdump -d repro.out | sed -n '1,120p'
Actual results:
.rodata contains "w\0fopen(\0" contiguously, but the addresses used in
main are off by one:
- "" points to "w"
- "w" points to ""
- "fopen(" points to "open(" (offset +1)
This indicates incorrect addends when merging string literals.
Expected results:
Each literal should point to its correct base:
- "" -> NUL byte after "w"
- "w" -> 'w'
- "fopen(" -> 'f'
Workaround:
If merge flags are stripped from .rodata.str1.1 (e.g. via
llvm-objcopy --set-section-flags .rodata.str1.1=alloc,readonly,data),
the problem disappears.
Versions:
- bpf-ld: GNU ld 2.44 (Debian binutils-bpf 2.44-3+3)
- clang: 19.1.7
-- System Information:
Debian Release: 13.3
APT prefers stable-updates
APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 6.12.57+deb13-amd64 (SMP w/32 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE,
TAINT_UNSIGNED_MODULE
Locale: LANG=zh_CN.UTF-8, LC_CTYPE=zh_CN.UTF-8 (charmap=UTF-8), LANGUAGE=zh_CN
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages binutils-bpf depends on:
ii libc6 2.41-12+deb13u1
ii libzstd1 1.5.7+dfsg-1
ii zlib1g 1:1.3.dfsg+really1.3.1-1+b1
binutils-bpf recommends no packages.
binutils-bpf suggests no packages.
-- no debconf information