Skip to content

Corruption if libraries have more than one .shstrtab section #240

@pablogsal

Description

@pablogsal

Describe the bug

Some shared libraries are corrupted when patchelf sets the RPATH to some new value if they have more than one .shstrtab section.

Steps To Reproduce

Consider this library:

https://www.dropbox.com/s/f4s9g7mxr4fj96v/libcrypt.so.1?dl=0

This library has more than one .shstrtab sections (section 29 and section 33):

❯ readelf -S libcrypt.so.1
There are 34 section headers, starting at offset 0x9258:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.bu[...] NOTE            00000154 000154 000024 00   A  0   0  4
  [ 2] .note.ABI-tag     NOTE            00000178 000178 000020 00   A  0   0  4
  [ 3] .gnu.hash         GNU_HASH        00000198 000198 000074 04   A  4   0  4
  [ 4] .dynsym           DYNSYM          0000020c 00020c 0001e0 10   A  5   1  4
  [ 5] .dynstr           STRTAB          000003ec 0003ec 00019e 00   A  0   0  1
  [ 6] .gnu.version      VERSYM          0000058a 00058a 00003c 02   A  4   0  2
  [ 7] .gnu.version_d    VERDEF          000005c8 0005c8 000038 00   A  5   2  4
  [ 8] .gnu.version_r    VERNEED         00000600 000600 000050 00   A  5   2  4
  [ 9] .rel.dyn          REL             00000650 000650 000038 08   A  4   0  4
  [10] .rel.plt          REL             00000688 000688 0000a0 08   A  4  12  4
  [11] .init             PROGBITS        00000728 000728 000030 00  AX  0   0  4
  [12] .plt              PROGBITS        00000758 000758 000150 04  AX  0   0  4
  [13] .text             PROGBITS        000008b0 0008b0 005168 00  AX  0   0 16
  [14] .fini             PROGBITS        00005a18 005a18 00001c 00  AX  0   0  4
  [15] .rodata           PROGBITS        00005a40 005a40 000f40 00   A  0   0 32
  [16] .interp           PROGBITS        00006980 006980 000013 00   A  0   0  1
  [17] .eh_frame_hdr     PROGBITS        00006994 006994 0000a4 00   A  0   0  4
  [18] .eh_frame         PROGBITS        00006a38 006a38 000400 00   A  0   0  4
  [19] .hash             HASH            00006e38 006e38 000160 04   A  4   0  4
  [20] .ctors            PROGBITS        00007edc 007edc 000008 00  WA  0   0  4
  [21] .dtors            PROGBITS        00007ee4 007ee4 000008 00  WA  0   0  4
  [22] .jcr              PROGBITS        00007eec 007eec 000004 00  WA  0   0  4
  [23] .data.rel.ro      PROGBITS        00007ef0 007ef0 000004 00  WA  0   0  4
  [24] .dynamic          DYNAMIC         00007ef4 007ef4 0000e8 08  WA  5   0  4
  [25] .got              PROGBITS        00007fdc 007fdc 000018 04  WA  0   0  4
  [26] .got.plt          PROGBITS        00007ff4 007ff4 00005c 04  WA  0   0  4
  [27] .bss              NOBITS          00008060 008050 0270fc 00  WA  0   0 32
  [28] .comment          PROGBITS        00000000 008050 00002d 01  MS  0   0  1
  [29] .shstrtab         STRTAB          00000000 00807d 000196 00      0   0  1
  [30] .symtab           SYMTAB          00000000 008214 0008e0 10     31 113  4
  [31] .strtab           STRTAB          00000000 008af4 000622 00      0   0  1
  [32] .gnu_debuglink    PROGBITS        00000000 009118 00001c 00      0   0  4
  [33] .shstrtab         STRTAB          00000000 009134 000121 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)

when patching the library, for example with

./src/patchelf --set-rpath $ORIGIN --force-rpath libcrypt.so.1

it produces some corruption (look at the section names):

❯ readelf -S libcrypt.so.1
There are 34 section headers, starting at offset 0x9258:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .dyn              DYNSYM          0000020c 00020c 0001e0 10   A 30   1  4
  [ 2] l.plt             VERSYM          0000058a 00058a 00003c 02   A  1   0  2
  [ 3] d                 VERDEF          000005c8 0005c8 000038 00   A 30   2  4
  [ 4] _frame_hdr        VERNEED         00000600 000600 000050 00   A 30   2  4
  [ 5] text              REL             00000650 000650 000038 08   A  1   0  4
  [ 6] .got.plt          REL             00000688 000688 0000a0 08   A  1   8  4
  [ 7]                   PROGBITS        00000728 000728 000030 00  AX  0   0  4
  [ 8] .plt              PROGBITS        00000758 000758 000150 04  AX  0   0  4
  [ 9] anges             PROGBITS        000008b0 0008b0 005168 00  AX  0   0 16
  [10] d                 PROGBITS        00005a18 005a18 00001c 00  AX  0   0  4
  [11] .symtab           PROGBITS        00005a40 005a40 000f40 00   A  0   0 32
  [12] terp              PROGBITS        00006980 006980 000013 00   A  0   0  1
  [13]                   PROGBITS        00006994 006994 0000a4 00   A  0   0  4
  [14] .dynstr           PROGBITS        00006a38 006a38 000400 00   A  0   0  4
  [15] rsion_d           HASH            00006e38 006e38 000160 04   A  1   0  4
  [16] ata.rel.ro        PROGBITS        00007edc 007edc 000008 00  WA  0   0  4
  [17] .ro               PROGBITS        00007ee4 007ee4 000008 00  WA  0   0  4
  [18] frame             PROGBITS        00007eec 007eec 000004 00  WA  0   0  4
  [19] i                 PROGBITS        00007ef0 007ef0 000004 00  WA  0   0  4
  [20] ug_aranges        PROGBITS        00007fdc 007fdc 000018 04  WA  0   0  4
  [21] .bss              PROGBITS        00007ff4 007ff4 00005c 04  WA  0   0  4
  [22] namic             NOBITS          00008060 008050 0270fc 00  WA  0   0 32
  [23] ment              PROGBITS        00000000 008050 00002d 01  MS  0   0  1
  [24] b                 STRTAB          00000000 00807d 000196 00      0   0  1
  [25] .strtab           SYMTAB          00000000 008214 0008e0 10     26 113  4
  [26] .shstrtab         STRTAB          00000000 008af4 000622 00      0   0  1
  [27] .version_r        PROGBITS        00000000 009118 00001c 00      0   0  4
  [28] b                 STRTAB          00000000 009134 000121 00      0   0  1
  [29] u.build-id        DYNAMIC         00030000 00a000 0000f0 08  WA 30   0  4
  [30]                   STRTAB          000300f0 00a0f0 0001ac 00   A  0   0  4
  [31] u.version_d       GNU_HASH        0003029c 00a29c 000074 04   A  1   0  4
  [32] nu.version        NOTE            00030310 00a310 000020 00   A  0   0  4
  [33]                   NOTE            00030330 00a330 000024 00   A  0   0  4
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  p (processor specific)
readelf: Error: no .dynamic section in the dynamic segment

Expected behavior

The library is not corrupted and running the previous example works correctly without segfaulting.

patchelf --version output

patchelf 0.12

This may sound like a weird case, but the library provided in this example is taken from a system library in RHEL 6.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions