summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBreno Rodrigues Guimaraes <brenorg@gmail.com>2023-02-20 18:22:17 -0300
committerBreno Rodrigues Guimaraes <brenorg@gmail.com>2023-02-24 20:39:11 -0300
commitde3e1f5e11f533d8678474eb9234ba35efa960d6 (patch)
tree276fecc1cba3f3543d241ea34115f6ef4030733c
parent69a7ae54d27513d7553b4d8bd77ade017e674e22 (diff)
downloadpatchelf-de3e1f5e11f533d8678474eb9234ba35efa960d6.tar.gz
Add one extra page to avoid overlapping with next page if its rounded down
-rw-r--r--src/patchelf.cc4
-rw-r--r--tests/Makefile.am4
-rwxr-xr-xtests/overlapping-segments-after-roundingbin0 -> 227896 bytes
-rwxr-xr-xtests/overlapping-segments-after-rounding.sh23
4 files changed, 29 insertions, 2 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc
index ca247c1..b78210c 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -985,7 +985,9 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsExecutable()
/* Calculate how many bytes are needed out of the additional pages. */
size_t extraSpace = neededSpace - startOffset;
- unsigned int neededPages = roundUp(extraSpace, getPageSize()) / getPageSize();
+ // Always give one extra page to avoid colliding with segments that start at
+ // unaligned addresses and will be rounded down when loaded
+ unsigned int neededPages = 1 + roundUp(extraSpace, getPageSize()) / getPageSize();
debug("needed pages is %d\n", neededPages);
if (neededPages * getPageSize() > firstPage)
error("virtual address space underrun!");
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4a08c14..b3f0b97 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -47,6 +47,7 @@ src_TESTS = \
print-execstack.sh \
modify-execstack.sh \
rename-dynamic-symbols.sh \
+ overlapping-segments-after-rounding.sh \
empty-note.sh
build_TESTS = \
@@ -54,7 +55,8 @@ build_TESTS = \
TESTS = $(src_TESTS) $(build_TESTS)
-EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness empty-note
+EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness empty-note \
+ overlapping-segments-after-rounding
TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 STRIP=$(STRIP) OBJDUMP=$(OBJDUMP) READELF=$(READELF) OBJCOPY=$(OBJCOPY)
diff --git a/tests/overlapping-segments-after-rounding b/tests/overlapping-segments-after-rounding
new file mode 100755
index 0000000..ecad537
--- /dev/null
+++ b/tests/overlapping-segments-after-rounding
Binary files differ
diff --git a/tests/overlapping-segments-after-rounding.sh b/tests/overlapping-segments-after-rounding.sh
new file mode 100755
index 0000000..d7c87b1
--- /dev/null
+++ b/tests/overlapping-segments-after-rounding.sh
@@ -0,0 +1,23 @@
+#! /bin/sh -e
+
+PATCHELF=$(readlink -f "../src/patchelf")
+SCRATCH="scratch/$(basename "$0" .sh)"
+READELF=${READELF:-readelf}
+
+EXEC_NAME="overlapping-segments-after-rounding"
+
+if test "$(uname -i)" = x86_64 && test "$(uname)" = Linux; then
+ rm -rf "${SCRATCH}"
+ mkdir -p "${SCRATCH}"
+
+ cp "${srcdir}/${EXEC_NAME}" "${SCRATCH}/"
+ cd "${SCRATCH}"
+
+ ${PATCHELF} --force-rpath --remove-rpath --output modified1 "${EXEC_NAME}"
+
+ ldd modified1
+
+ ${PATCHELF} --force-rpath --set-rpath "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --output modified2 modified1
+
+ ldd modified2
+fi