Skip to content

musl and glibc dynamic stubs are deeply flawed #8896

@LemonBoy

Description

@LemonBoy
  • glibc stubs are generated by merging together functions (marked with F in the abilist files) and variables (marked with D) and treating them as if they were functions (STT_FUNC entries). This is a huge problem when the linker performs copy relocations (eg. a static library references __stack_chk_guard using absolute addresses, even though that symbol is provided by an external shared object). Upon seeing a STT_FUNC symbol lld processes it as if it were a function, creating a PLT (!!!) entry instead of emitting a copy relocation or a GOT indirection (afaics the latter is not really used).

To understand the implications of this error here's a small snippet of ARM assembly, showing a typical function prologue where we load the stack cookie from __stack_chk_guard and store it on stack:

   3ee78: 10 4c 2d e9  	push	{r4, r10, r11, lr}
   3ee7c: 08 b0 8d e2  	add	r11, sp, #8
   3ee80: d0 d0 4d e2  	sub	sp, sp, #208
   3ee84: b0 c0 0e e3  	movw	r12, #57520
   3ee88: 07 c0 40 e3  	movt	r12, #7
   # Load from 0x7e0b0
   3ee8c: 00 c0 9c e5  	ldr	r12, [r12]
   3ee90: 0c c0 0b e5  	str	r12, [r11, #-12]

And, guess what, that address points to a PLT entry:

0007e0b0 <$a>:
   7e0b0: 00 c6 8f e2  	add	r12, pc, #0, #12
   7e0b4: 20 ca 8c e2  	add	r12, r12, #32, #20
   7e0b8: 68 f3 bc e5  	ldr	pc, [r12, #872]!

In short the program is using garbage for stack cookie and, what's worse, it's not even random data!

The fix is simple, the abilist files contain the symbol size, it's only a matter of passing this info to the .txt files used to synthesize the .s file.

  • musl stubs are a bit better, some symbols are correctly marked as objects (STT_OBJECT) but are zero-sized, making lld promptly reject those when attempting to do a copy relocation. The fix is, again, to emit .size <sym>, <size> for the symbols marked as %object.

Note that the symbol sizes may be different across platforms (eg. 32 vs 64 bit), getting the symbol size wrong is dangerous.

cc @flyx, this is the problem you were hitting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviormiscompilationThe compiler reports success but produces semantically incorrect code.os-linuxLinux

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions