Commit Graph

216 Commits

Author SHA1 Message Date
Julian Stecklina
fa8896a5a8 Add bounds checking for invalid section header name offsets
... otherwise strlen() (in the std::string constructor) will be called
with an out-of-bounds pointer.
2020-11-15 16:46:53 +01:00
Julian Stecklina
7a8214ce63 Gracefully handle ELF files with non-zero terminated string table 2020-11-15 16:46:53 +01:00
Julian Stecklina
cee8c8cda7 Gracefully handle ELF files with empty string table 2020-11-15 16:46:53 +01:00
Julian Stecklina
a954a08496 Gracefully handle ELF files with invalid string table size in header 2020-11-15 16:46:53 +01:00
Julian Stecklina
b552c30614 Gracefully handle ELF files with invalid string table indices in header 2020-11-15 16:46:53 +01:00
Xavier Abellan Ecija
62e8db4343 Added option --add-rpath 2020-10-05 16:59:13 +01:00
Conrad Ratschan
884eccc4f0 Fix endianness issues for powerpc PIE
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.
2020-10-03 21:55:17 -05:00
Pablo Galindo
a89d508130 Handle libraries with more than one .shstrtab section 2020-09-22 20:59:55 +01:00
Pablo Galindo
83aa89addf Use sh_offset instead of sh_addr when checking already replaced libs
When checking for already replaced libs, the check against the size must
be done using the section header offset, not the section file address.
This was not crashing in many situations because normally sh_address and
sh_offset have the same value but these two may differ and using the
sh_address value instead can cause library corruption in these
situations.
2020-09-22 01:33:49 +01:00
Rolf Eike Beer
adee501ccb fix roundUp() to not truncate 64 bit values 2020-09-16 08:38:22 +02:00
rmnull
6edec83653 mark phdrs synced with sections, avoid rechecking it when syncing note sections to segments.
This also serves as a bug fix when a previously synced note segment
overlaps with another section and creates a false alarm.
2020-08-26 03:52:46 +05:30
rmnull
5d99bcd974 skip overwriting r(un)path data when old_rpath = new_rpath.
Also handle the case of dyn rpath changed.
2020-08-19 13:59:44 +05:30
Bryce Ferguson
e88d83c8b4 patchelf: Check ELF endianness before writing new runpath
This commit modifies the way fields are written in the dynamic
section in order to account the architecture of the target ELF
file. Instead of copying the raw data, use the helper functions
to convert endianness.

Signed-off-by: Bryce Ferguson <bryce.ferguson@rockwellcollins.com>
2020-08-17 13:53:27 +02:00
rmnull
4fc4d39f6b remove unused DT_IGNORE. 2020-08-12 21:08:07 +05:30
Eelco Dolstra
126372b636 Merge pull request #226 from corngood/clear-symbol-version
add --clear-symbol-version
2020-08-11 09:27:29 +02:00
rmnull
e01f827029 use stable_sort to maintain relative order for equal elemnts in sections(&segments) 2020-08-11 05:08:15 +05:30
David McFarland
51a3d5b5ff add --clear-symbol-version
This sets the versym entry for a given symbol to 1.
2020-08-10 15:38:36 -03:00
Eelco Dolstra
61bc101769 Merge pull request #225 from Mic92/note-2
Better support relocating NOTE sections/segments + tests!
2020-07-31 10:07:17 +02:00
Pierre Bourdon
43a33482b5 Better support relocating NOTE sections/segments
SHT_NOTE sections can be mapped in memory by PT_NOTE segments. When
rewriting an SHT_NOTE, attempt to also rewrite a matching segment if it
exists.

Note that an ELF can contain multiple SHT_NOTE sections, and a given
PT_NOTE segment can theoretically map multiple contiguous sections.
There are multiple ways this could be handled, the one picked here is to
pre-normalize PT_NOTE segments so that a multi-section segment gets
broken up into multiple separate segments instead.

Also fix (or more like hack around) alignment issues with note sections.
Keeping the original alignment value when possible is important because
it determines how the data within the section needs to be parsed.
2020-06-20 14:22:40 +02:00
Pierre Bourdon
0470d6921b Improve the default section alignment choice
Currently patchelf uses the host system's page size (determined at build
time) as the default section load memory alignment. This causes multiple
issues

- Cross-compilation: when using patchelf on ELFs targetting a different
  architecture from the host, the host page size is still used by
  default.

- Variable page size architectures: ARMv8 systems can be configured in
  either 4K, 16K, or 64K page size mode depending on kernel
  configuration. An ARMv8 patchelf built on a 4K page size system will
  end up creating ELFs that cannot be used on a 64K page size system.

- Reproducibility: the page size of the machine that built patchelf
  "leaks" into the binary.

The build time --with-page-size as well as the run time --page-size
options can be used to work around some of these issues. But it's much
better to have patchelf do the right thing without explicit
configuration.

This commit adds support for inferring page size from the ELF header's
"machine" field. The default values are extracted from GNU gold's source
code. Note that both --with-page-size as well as --page-size continue to
work and take precedence on the default value.
2020-06-20 01:46:23 +02:00
Domen Kožar
7013e59d5a Merge pull request #210 from AaronDMarasco/const_cleanup
Some const-correctness and C++11 auto
2020-06-16 10:18:46 +02:00
Aaron D. Marasco
e522b14edc Add libasan build option and test print-needed
(cherry picked from commit 288eb61a173ce6f4cdf0be0d744c9c6b6b5598a4)
2020-06-10 09:51:37 -04:00
Aaron D. Marasco
208303b066 Some const-correctness and C++11 auto
(cherry picked from commit 76e2cdbee4705c45cae4eca55278530a02be2f83)
2020-06-10 09:39:53 -04:00
Domen Kožar
4aff679d9e Merge pull request #171 from lkollar/no-memset-soname
Remove zeroing out logic in modifySoname
2020-06-03 16:02:39 +02:00
Domen Kožar
640a35faaa Merge pull request #202 from rpurdie/master
Fix shared library corruption when rerunning patchelf
2020-06-03 16:01:03 +02:00
Domen Kožar
12e2b7b813 Merge pull request #127 from bartosh/master
fix adjusting startPage
2020-06-03 15:34:06 +02:00
Thomas Holder
6e5e98ce77 Consistently use --force-rpath (fixes #94) 2020-06-03 13:37:13 +02:00
Richard Purdie
ad5f1f078b Fix shared library corruption when rerunning patchelf
When running patchelf on some existing patchelf'd binaries to change to longer
RPATHS, ldd would report the binaries as invalid. The output of objdump -x on
those libraryies should show the top of the .dynamic section is getting trashed,
something like:

0x600000001 0x0000000000429000
0x335000 0x0000000000335000
0xc740 0x000000000000c740
0x1000 0x0000000000009098
SONAME libglib-2.0.so.0

(which should be RPATH and DT_NEEDED entries)

This was tracked down to the code which injects the PT_LOAD section.

The issue is that if the program headers were previously relocated to the end
of the file which was how patchelf operated previously, the relocation code
wouldn't work properly on a second run as it now assumes they're located after
the elf header. This change forces them back to immediately follow the elf
header which is where the code has made space for them.

Should fix https://github.com/NixOS/patchelf/issues/170
and https://github.com/NixOS/patchelf/issues/192

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2020-06-03 12:14:58 +01:00
Dan L. Stahlke
71ed440127 Added --output flag 2020-06-01 12:12:54 -07:00
Pau Espin Pedrol
711a20dcbf Update doc to describe multiple filename args allowed
Commit 936bae418b added support to handle
several files at once, but forgot to update the man and help output to
describe it.

Fixes: 936bae418b
2020-04-08 15:10:22 +02:00
Laszlo Kiss-Kollar
e2fe56fdf3 Remove zeroing out logic in modifySoname
The original SONAME is filled with 'X' characters in the modifySoname
function. This can cause issues if the .dynstr entry is still referenced
in other sections, e.g. some libraries use the SONAME entry as version
specifiers.
2019-05-29 08:09:45 +01:00
Ezra Cooper
52ab908394 Fix issue #66 by ignoring the first section header when sorting, and not overwriting NOBITS entries. 2018-06-21 11:14:10 -07:00
stanislav.markevich
ba2695a811 fix reading and writing big files (e.g. > 2Gb) 2018-05-08 21:28:26 +03:00
Eelco Dolstra
1fa4d36fea Merge pull request #123 from lheckemann/multiple-args
Allow multiple filenames to patch
2018-01-29 11:37:21 +01:00
Eelco Dolstra
48452cf6b4 Fix indentation 2018-01-08 19:07:17 +01:00
Eelco Dolstra
b6d0317803 Merge branch 'strict_ordering' of https://github.com/kmillar/patchelf 2018-01-08 19:06:46 +01:00
Karl Millar
71e99c549c Simplify ordering code as suggested in PR comments. 2018-01-08 09:55:47 -08:00
Eelco Dolstra
aceb96e9a8 Merge pull request #121 from dezgeg/better-error-messages
Better error messages when run on statically-linked (or otherwise weird) binaries
2018-01-05 13:07:09 +01:00
Karl Millar
a1eab1c9de Modified CompPhdr::operator() so that it provides a strict
weak ordering as required by std::sort.
2017-12-07 12:51:01 -08:00
Ed Bartosh
1cc234fea5 fix adjusting startPage
startPage is adjusted unconditionally for all executables.
This results in incorrect addresses assigned to INTERP and LOAD
program headers, which breaks patched executable.

Adjusting startPage variable only when startOffset > startPage
should fix this.

This change is related to the issue NixOS#10

Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
2017-07-21 12:49:30 +03:00
Linus Heckemann
936bae418b Allow multiple filenames to patch
This makes behaviour less confusing when multiple filenames are
passed — previously, any extra filenames would be ignored completely,
as would any options passed after a filename. Now these are taken
into account.
2017-05-28 15:46:51 +01:00
Eelco Dolstra
2a9cefd7d6 Fix multiple --add-needed
Reported by Jannis Harder.
2017-05-03 13:24:31 +02:00
Eelco Dolstra
6bfcafbba8 Merge branch 'master' of https://github.com/rpurdie/patchelf 2017-04-21 15:26:52 +02:00
Tuomas Tynkkynen
daaffbe7f3 Give a better error message if the file lacks a section header table
Currently, patchelf outputs this when run on a UPX-compressed ELF file:

patchelf: patchelf.cc:420: ElfFile<Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym, Elf_Verneed>::ElfFile(FileContents): Assertion `shstrtabIndex < shdrs.size()' failed.

Make it give a nicer error message:

patchelf: no section headers. The input file is probably a statically linked, self-decompressing binary

Fixes #63
2017-04-19 17:33:33 +03:00
Tuomas Tynkkynen
bfc3db32d2 Improve error message when run on statically linked binaries
If .dynamic, .dynstr or .interp sections aren't found, give an extra hint
to the user that the input file is statically linked.
2017-04-19 17:33:33 +03:00
Eelco Dolstra
e44c318b37 Fix Debian 7 build
http://hydra.nixos.org/build/49825195
2017-04-14 13:53:31 +02:00
Richard Purdie
c4deb5e9e1 Avoid inflating file sizes needlessly and allow binaries to be stripped
The current approach to changing sections in ET_DYN executables is to move
the INTERP section to the end of the file. +This means changing PT_PHDR to
add an extra PT_LOAD section so that the new section is mmaped into memory
by the elf loader in the kernel. In order to extend PHDR, this means moving
it to the end of the file.

Its documented in BUGS there is a kernel 'bug' which means that if you have holes
in memory between the base load address and the PT_LOAD segment that contains PHDR,
it will pass an incorrect PHDR address to ld.so and fail to load the binary, segfaulting.

To avoid this, the code currently inserts space into the binary to ensure that when
loaded into memory there are no holes between the PT_LOAD sections. This inflates the
binaries by many MBs in some cases. Whilst we could make them sparse, there is a second
issue which is that strip can fail to process these binaries:

$ strip fixincl
Not enough room for program headers, try linking with -N
[.note.ABI-tag]: Bad value

This turns out to be due to libbfd not liking the relocated PHDR section either
(https://github.com/NixOS/patchelf/issues/10).

Instead this patch implements a different approach, leaving PHDR where it is but extending
it in place to allow addition of a new PT_LOAD section. This overwrites sections in the
binary but those get moved to the end of the file in the new PT_LOAD section.

This is based on patches linked from the above github issue, however whilst the idea
was good, the implementation wasn't correct and they've been rewritten here.

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-03-07 21:08:34 +00:00
Eelco Dolstra
c1f89c077e Don't check whether DT_STRTAB matches .dynstr
We don't really care whether DT_STRTAB is correct, since we overwrite
it anyway.

https://github.com/NixOS/nixpkgs/issues/22333
2017-02-17 13:38:12 +01:00
Eelco Dolstra
03b7ecaa0c Use exceptions 2016-09-19 18:48:49 +02:00
Eelco Dolstra
a4d21661d5 --shrink-rpath: Ignore libraries for different architectures
Fixes #93.
2016-09-19 18:12:19 +02:00