Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUGFIX: Fix endianness issues with PIE binaries #245

Merged

Conversation

ratschance
Copy link

Description

A few endianness issues were encountered when setting an RPATH on ppc32 PIEs (since they are of type DYN). This pull request fixes those issues, and adds regression tests for:

  1. PHDR errors when running readelf on the final binary
  2. Incorrect virtual address set for the PHDR segment
  3. Incorrect default alignment for LOAD segments

The no-rpath-pie-powerpc was generated by compiling the foo.c bar.c and main.c in the tests directory with a ppc32 cross toolchain and -pie -fpie arguments.

Previous readelf -l results after patching

Elf file type is DYN (Shared object file)
Entry point 0x46c
There are 9 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x009ac 0x009ac R E 0x10000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
  INTERP         0x000134 0x00000134 0x00000134 0x0001d 0x0001d R   0x4
      [Requesting program interpreter: ]
  GNU_EH_FRAME   0x0008f8 0x000008f8 0x000008f8 0x00024 0x00024 R   0x4
  LOAD           0x00fef4 0x0001fef4 0x0001fef4 0x00144 0x10001f4 RWE 0x10000
  GNU_RELRO      0x00fef4 0x0001fef4 0x0001fef4 0x0010c 0x0010c R   0x1
  DYNAMIC        0x011000 0x01021000 0x01021000 0x000c8 0x000c8 RW  0x4
  LOAD           0x011000 0x01021000 0x01021000 0x0016c 0x0016c RW  0x1000
  PHDR           0x000034 0x34000000 0x34000000 0x00120 0x00120 R   0x4
readelf: Error: the PHDR segment must occur before any LOAD segment
readelf: Error: the PHDR segment is not covered by a LOAD segment

 Section to Segment mapping:
  Segment Sections...
   00     .interp .hash .gnu.hash .dynsym .rela.dyn .rela.plt .init .text .fini .rodata .eh_frame_hdr .eh_frame 
   01     
   02     .interp 
   03     .eh_frame_hdr 
   04     .ctors .dtors .got2 .data .got .plt .bss 
   05     .ctors .dtors .got2 
   06     .dynamic 
   07     .dynamic .dynstr 
   08     

New readelf -l results after patching

Elf file type is DYN (Shared object file)
Entry point 0x46c
There are 9 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00000034 0x00000034 0x00120 0x00120 R   0x4
  LOAD           0x000000 0x00000000 0x00000000 0x009ac 0x009ac R E 0x10000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
  GNU_EH_FRAME   0x0008f8 0x000008f8 0x000008f8 0x00024 0x00024 R   0x4
  LOAD           0x00fef4 0x0001fef4 0x0001fef4 0x00144 0x10001f4 RWE 0x10000
  GNU_RELRO      0x00fef4 0x0001fef4 0x0001fef4 0x0010c 0x0010c R   0x1
  DYNAMIC        0x020000 0x01030000 0x01030000 0x000c8 0x000c8 RW  0x4
  LOAD           0x020000 0x01030000 0x01030000 0x001c8 0x001c8 RW  0x10000
  INTERP         0x0201a8 0x010301a8 0x010301a8 0x0001d 0x0001d R   0x4
      [Requesting program interpreter: /lib/ld-uClibc.so.0]

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .gnu.hash .dynsym .rela.dyn .rela.plt .init .text .fini .rodata .eh_frame_hdr .eh_frame 
   02     
   03     .eh_frame_hdr 
   04     .ctors .dtors .got2 .data .got .plt .bss 
   05     .ctors .dtors .got2 
   06     .dynamic 
   07     .dynamic .dynstr .hash .interp 
   08     .interp 

Previously when running `patchelf --set-rpath "/usr/sbin" my_bin` on a
PIE ppc32 binary that had no RPATH a few issues were encountered.

This commit fixes:

1. The PT_PHDR being sorted improperly due to the type being read in
   incorrect endianness

2. The aligment being set to default 0x1000 due to the machine arch
   being read in incorrect endianness

3. The interpreter being clobbered due to the replace sections routine
   reading sh_offset and sh_size in incorrect endianness

4. The PHDR segment having an incorrect virt and phys address due to
   reading the e_phoff in the incorrect endianness

This also fixes a read of the shdr.sh_type in writeReplacedSections but
this was not encountered during testing.
@edolstra edolstra merged commit 47dc18d into NixOS:master Oct 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants