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

Implement --append-null-phdr option #534

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions src/patchelf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@ ElfFile<ElfFileParamNames>::ElfFile(FileContents fContents)
if (rdi(phdrs[i].p_type) == PT_INTERP) isExecutable = true;
}

trailingNullPhdrs = 0;

for (int i = 0; i < rdi(hdr()->e_shnum); ++i) {
Elf_Shdr *shdr = (Elf_Shdr *) (fileContents->data() + rdi(hdr()->e_shoff)) + i;

Expand Down Expand Up @@ -1162,7 +1164,7 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
if (rdi(phdr.p_type) == PT_PHDR) {
phdr.p_offset = hdr()->e_phoff;
wri(phdr.p_vaddr, wri(phdr.p_paddr, phdrAddress));
wri(phdr.p_filesz, wri(phdr.p_memsz, phdrs.size() * sizeof(Elf_Phdr)));
wri(phdr.p_filesz, wri(phdr.p_memsz, (phdrs.size() + trailingNullPhdrs) * sizeof(Elf_Phdr)));
break;
}
}
Expand All @@ -1171,6 +1173,17 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
sortPhdrs();
}

if (trailingNullPhdrs) {
Elf_Phdr nullPhdr = {};
nullPhdr.p_type = PT_NULL;

for (int i = 0; i < trailingNullPhdrs; ++i) {
phdrs.push_back(nullPhdr);
}

wri(hdr()->e_phnum, rdi(hdr()->e_phnum) + trailingNullPhdrs);
}

for (unsigned int i = 0; i < phdrs.size(); ++i)
* ((Elf_Phdr *) (fileContents->data() + rdi(hdr()->e_phoff)) + i) = phdrs.at(i);

Expand Down Expand Up @@ -1298,7 +1311,13 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
}
}


template<ElfFileParams>
void ElfFile<ElfFileParamNames>::appendNullPhdrs(int count)
{
trailingNullPhdrs += count;
rewriteHeaders(rdi(hdr()->e_phoff));
changed = true;
}

static void setSubstr(std::string & s, unsigned int pos, const std::string & t)
{
Expand Down Expand Up @@ -2376,6 +2395,7 @@ static bool addDebugTag = false;
static bool renameDynamicSymbols = false;
static bool printRPath = false;
static std::string newRPath;
static int nullPhdrsToAppend;
static std::set<std::string> neededLibsToRemove;
static std::map<std::string, std::string> neededLibsToReplace;
static std::set<std::string> neededLibsToAdd;
Expand Down Expand Up @@ -2444,6 +2464,9 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con
if (renameDynamicSymbols)
elfFile.renameDynamicSymbols(symbolsToRename);

if (nullPhdrsToAppend)
elfFile.appendNullPhdrs(nullPhdrsToAppend);

if (elfFile.isChanged()){
writeFile(fileName, elfFile.fileContents);
} else if (alwaysWrite) {
Expand Down Expand Up @@ -2496,6 +2519,8 @@ static void showHelp(const std::string & progName)
[--allowed-rpath-prefixes PREFIXES]\t\tWith '--shrink-rpath', reject rpath entries not starting with the allowed prefix\n\
[--print-rpath]\n\
[--force-rpath]\n\
[--append-null-phdr]\t\tAppends a PT_NULL program header to the end of the table; may be used multiple times\n\
[--append-null-phdrs N]\t\tAppends N PT_NULL program headers to the end of the table; may be used multiple times\n\
[--add-needed LIBRARY]\n\
[--remove-needed LIBRARY]\n\
[--replace-needed LIBRARY NEW_LIBRARY]\n\
Expand Down Expand Up @@ -2600,6 +2625,13 @@ static int mainWrapped(int argc, char * * argv)
else if (arg == "--no-sort") {
noSort = true;
}
else if (arg == "--append-null-phdr") {
++nullPhdrsToAppend;
}
else if (arg == "--append-null-phdrs") {
if (++i == argc) error("missing argument");
nullPhdrsToAppend += std::stoi(argv[i]);
}
else if (arg == "--add-needed") {
if (++i == argc) error("missing argument");
neededLibsToAdd.insert(resolveArgument(argv[i]));
Expand Down
4 changes: 4 additions & 0 deletions src/patchelf.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class ElfFile
std::vector<Elf_Phdr> phdrs;
std::vector<Elf_Shdr> shdrs;

int trailingNullPhdrs;

bool littleEndian;

bool changed = false;
Expand Down Expand Up @@ -167,6 +169,8 @@ class ElfFile

void addDebugTag();

void appendNullPhdrs(int count);

void renameDynamicSymbols(const std::unordered_map<std::string_view, std::string>&);

void clearSymbolVersions(const std::set<std::string> & syms);
Expand Down
7 changes: 6 additions & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ src_TESTS = \
basic-flags.sh \
set-empty-rpath.sh \
phdr-corruption.sh \
append-null-phdr.sh \
replace-needed.sh \
replace-add-needed.sh \
add-debug-tag.sh \
Expand Down Expand Up @@ -123,7 +124,7 @@ check_DATA = libbig-dynstr.debug
# - with libtool, it is difficult to control options
# - with libtool, it is not possible to compile convenience *dynamic* libraries :-(
check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so libsimple-execstack.so libbuildid.so libtoomanystrtab.so \
phdr-corruption.so many-syms-main libmany-syms.so liboveralign.so libshared-rpath.so
phdr-corruption.so append-null-phdr.so many-syms-main libmany-syms.so liboveralign.so libshared-rpath.so

libbuildid_so_SOURCES = simple.c
libbuildid_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,--build-id
Expand Down Expand Up @@ -180,6 +181,10 @@ phdr_corruption_so_SOURCES = void.c phdr-corruption.ld
phdr_corruption_so_LDFLAGS = -nostdlib -shared -Wl,-T$(srcdir)/phdr-corruption.ld
phdr_corruption_so_CFLAGS =

append_null_phdr_so_SOURCES = void.c
append_null_phdr_so_LDFLAGS = -nostdlib -shared
append_null_phdr_so_CFLAGS =

many-syms.c:
i=1; while [ $$i -le 2000 ]; do echo "void f$$i() {};"; i=$$(($$i + 1)); done > $@

Expand Down
22 changes: 22 additions & 0 deletions tests/append-null-phdr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#! /bin/sh -e

PATCHELF="../src/patchelf"
SONAME="phdr-corruption.so"
SCRATCH="scratch/$(basename "$0" .sh)"
SCRATCH_SO="${SCRATCH}/${SONAME}"
READELF=${READELF:-readelf}

rm -rf "${SCRATCH}"
mkdir -p "${SCRATCH}"
cp "${SONAME}" "${SCRATCH}"

"${PATCHELF}" --append-null-phdr --append-null-phdrs 2 "${SCRATCH_SO}"

# Check for PT_NULL entries
readelfData=$(${READELF} -l "${SCRATCH_SO}" 2>&1)

if [ "$(echo "$readelfData" | grep -c "NULL")" != 3 ]; then
# Triggered if patchelf doesn't append two PT_NULL entries
echo "ERROR: PT_NULL segments were not appended to the program header table!"
exit 1
fi