Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CACT4Y+YAPair6Ar1XzWf=VzbFVMPRzm5DvQMtmNf8JBayRxC6g@mail.gmail.com>
Date: Sat, 1 Mar 2025 18:03:24 +0100
From: Dmitry Vyukov <dvyukov@...gle.com>
To: Sertonix <sertonix@...teo.net>
Cc: musl@...ts.openwall.com, dalias@...c.org, nsz@...t70.net
Subject: Re: Support for -static-pie relocations

RIght, sorry.

I checked out the latest HEAD c47ad25ea3b484e10326f933e927c0bc8cded3da.
Standard build: ./configure --enable-debug && make
arch x86_64

Reproducible with both (standard Debian builds):
$ clang --version
Debian clang version 16.0.6 (27+build3)
$ ld -v
GNU ld (GNU Binutils for Debian) 2.43.1
$ clang /tmp/test.c lib/libc.a -O2 -g -static-pie && ./a.out
Segmentation fault (core dumped)

and
$ gcc -v
gcc version 14.2.0 (Debian 14.2.0-3+build4)
$ gcc /tmp/test.c lib/libc.a -O2 -g -static-pie && ./a.out
Segmentation fault (core dumped)

Relocations are mostly rip-relative except for global vars that
contain pointers:

$ readelf -r ./a.out
Relocation section '.rela.dyn' at offset 0x350 contains 11 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000003e48  000000000008 R_X86_64_RELATIVE                    11a0
000000003e50  000000000008 R_X86_64_RELATIVE                    1160
000000003e58  000000000008 R_X86_64_RELATIVE                    4020
000000003e60  000000000008 R_X86_64_RELATIVE                    4380
000000003fd8  000000000008 R_X86_64_RELATIVE                    3e68
000000004008  000000000008 R_X86_64_RELATIVE                    4008
000000004010  000000000008 R_X86_64_RELATIVE                    4020
000000004038  000000000008 R_X86_64_RELATIVE                    19ca
000000004068  000000000008 R_X86_64_RELATIVE                    19f5
000000004070  000000000008 R_X86_64_RELATIVE                    19ed
000000004078  000000000008 R_X86_64_RELATIVE                    41d0

> Relocations are processed in the crt entry point before
> __libc_start_main is reached. The relevant code is ldso/dlstart.c.

Am I linking musl somehow incorrectly (need to do something with crt)?

My entry function calls __libc_start_main:

Dump of assembler code for function _start:
   0x00007ffff7ffb0c0 <+0>: xor    %ebp,%ebp
   0x00007ffff7ffb0c2 <+2>: mov    %rdx,%r9
   0x00007ffff7ffb0c5 <+5>: pop    %rsi
   0x00007ffff7ffb0c6 <+6>: mov    %rsp,%rdx
   0x00007ffff7ffb0c9 <+9>: and    $0xfffffffffffffff0,%rsp
   0x00007ffff7ffb0cd <+13>: push   %rax
   0x00007ffff7ffb0ce <+14>: push   %rsp
   0x00007ffff7ffb0cf <+15>: xor    %r8d,%r8d
   0x00007ffff7ffb0d2 <+18>: xor    %ecx,%ecx
   0x00007ffff7ffb0d4 <+20>: lea    -0x4b(%rip),%rdi        #
0x7ffff7ffb090 <main>
   0x00007ffff7ffb0db <+27>: addr32 call 0x7ffff7ffb3fa <__libc_start_main>
=> 0x00007ffff7ffb0e1 <+33>: hlt


I don't see any static libs in musl build that include _start symbol...






On Sat, 1 Mar 2025 at 17:34, Sertonix <sertonix@...teo.net> wrote:
>
> On Sat Mar 1, 2025 at 5:22 PM CET, Rich Felker wrote:
> > On Sat, Mar 01, 2025 at 05:10:39PM +0100, Szabolcs Nagy wrote:
> >> * Dmitry Vyukov <dvyukov@...gle.com> [2025-03-01 16:08:52 +0100]:
> >>
> >> > Hello,
> >> >
> >> > This simple program crashes when compiled with -static-pie:
> >> >
> >> > #include <stdio.h>
> >> > int main() { fprintf(stderr, "Hello\n"); }
> >> >
> >> > Program received signal SIGSEGV, Segmentation fault.
> >> > 0x0000000000001170 in ?? ()
> >> > (gdb) bt
> >> > #0  0x0000000000001170 in ?? ()
> >> > #1  0x00007ffff7ffb3b8 in libc_start_init () at src/env/__libc_start_main.c:64
> >> > #2  0x00007ffff7ffb3e8 in libc_start_main_stage2 (main=0x7ffff7ffb180
> >> > <main>, argc=1, argv=0x7fffffffdc98)
> >> >     at src/env/__libc_start_main.c:92
> >> > #3  0x00007ffff7ffb0b1 in _start ()
> >> >
> >> > (gdb) up
> >> > #1  0x00007ffff7ffb3b8 in libc_start_init () at src/env/__libc_start_main.c:64
> >> > 64 (*(void (**)(void))a)();
> >> >
> >> > (gdb) disass
> >> > Dump of assembler code for function libc_start_init:
> >> >    0x00007ffff7ffb39b <+0>: push   %rbp
> >> >    0x00007ffff7ffb39c <+1>: push   %rbx
> >> >    0x00007ffff7ffb39d <+2>: sub    $0x8,%rsp
> >> >    0x00007ffff7ffb3a1 <+6>: call   0x7ffff7ffb000 <_init>
> >> >    0x00007ffff7ffb3a6 <+11>: lea    0x2a9b(%rip),%rbx        # 0x7ffff7ffde48
> >> >    0x00007ffff7ffb3ad <+18>: lea    0x2a9c(%rip),%rbp        # 0x7ffff7ffde50
> >> >    0x00007ffff7ffb3b4 <+25>: jmp    0x7ffff7ffb3bc <libc_start_init+33>
> >> >    0x00007ffff7ffb3b6 <+27>: call   *(%rbx)
> >> > => 0x00007ffff7ffb3b8 <+29>: add    $0x8,%rbx
> >> >    0x00007ffff7ffb3bc <+33>: cmp    %rbp,%rbx
> >> >    0x00007ffff7ffb3bf <+36>: jb     0x7ffff7ffb3b6 <libc_start_init+27>
> >> >    0x00007ffff7ffb3c1 <+38>: add    $0x8,%rsp
> >> >    0x00007ffff7ffb3c5 <+42>: pop    %rbx
> >> >    0x00007ffff7ffb3c6 <+43>: pop    %rbp
> >> >    0x00007ffff7ffb3c7 <+44>: ret
> >> > End of assembler dump.
> >> >
> >> > (gdb) p /x $rbx
> >> > $1 = 0x7ffff7ffde48
> >> > (gdb) p /x *(void**)$rbx
> >> > $2 = 0x1170
> >> >
> >> > This 0x1170 is probably a ctor pointer offset that wasn't relocated.
> >> >
> >> > A fix would probably be calling _dl_relocate_object() somewhere on the
> >> > __libc_start_main() path.
> >> >
> >> > Is there a reason this is not supported? Or merely not implemented yet?
> >> > Can't find an issue tracker nor searchable archives for previous
> >> > discussions on this...
> >> >
> >> > Thanks in advance
> >>
> >> i think this is a disagreement about what dynrelocs may appear in
> >> static pie between musl and binutils.
> >>
> >> it is a linker bug if static pie has non-relative relocs.
> >> in this case likely there is a symbolic reloc for the init array
> >> entry even though we know the symbol value at link time.
> >> check the readelf output. (alternative theory: the relocs are
> >> missing: bfd ld had bugs like that before)
> >>
> >> binutils ld is sloppy on some targets but because glibc handles
> >> symbolic relocs it is just an unnecessary runtime symbol lookup
> >> there. musl considers this unacceptable linker behaviour: it
> >> would require half of the dynlinker static linked into every
> >> static pie unnecessarily.
> >
> > I don't think we've hit that on x86_64, and it was long ago fixed on
> > the archs we did hit it on, so I don't think that's what's going on.
> >
> > But a full readelf -a of the failing binary would quickly reveal if
> > that's what happened, and would probaby shed light on whatever else if
> > wrong if not that.
> >
> > Rich
>
>
> I wasn't able to reproduce the exact same issue but I have seen -static-pie
> binaries being broken for arm 32 targets. Which arch are you testing on?
>
> Ref https://gitlab.alpinelinux.org/alpine/aports/-/issues/16942#note_484996

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.