Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save steven676/85b290df8942cf0fd5e8 to your computer and use it in GitHub Desktop.
Save steven676/85b290df8942cf0fd5e8 to your computer and use it in GitHub Desktop.
[PATCH 2/2] Allow targets to reenable support for non-PIE executables
From 989a14bfb86608aba038b6786a3ab312bd7aeb6e Mon Sep 17 00:00:00 2001
From: Steven Luo <[email protected]>
Date: Sat, 15 Nov 2014 17:58:48 -0800
Subject: [PATCH 2/2] Allow targets to reenable support for non-PIE
executables
Many legacy devices have non-PIE binary blob executables which are never
going to be updated by the manufacturer; allow the dynamic linker to
load these executables so that they can work.
This rolls back the following commit:
Cleanup: updated comments
* 6275f2083415d22a6ce0de55645079cd47e0cc80
Allows targets to reenable this code:
Cleanup: remove AARCH/ARM_COPY relocation support
* b906e13c55c9fe9b4157ba548534a0230434882b
And allows targets to disable this behavior if necessary:
Remove support for non-PIE executables
* 2aebf5429bb1241a3298b5b642d38f73124c2026
Derived from AOSP Change-Id Ia2501aa14bd30feb4a6ce66bdb7c9f066dba0b5f.
[[email protected]: update for Android 5.1+]
---
linker/Android.mk | 4 ++++
linker/linker.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/linker/Android.mk b/linker/Android.mk
index 4298032..84cba0f 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -39,6 +39,10 @@ LOCAL_CPPFLAGS += \
# We need to access Bionic private headers in the linker.
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../libc/
+ifeq ($(TARGET_ALLOW_NON_PIE_EXECUTABLES),true)
+ LOCAL_CFLAGS += -DTARGET_ALLOW_NON_PIE_EXECUTABLES
+endif
+
# we don't want crtbegin.o (because we have begin.o), so unset it
# just for this module
LOCAL_NO_CRT := true
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 789040b..c7ef897 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -63,6 +63,7 @@
*
* open issues / todo:
*
+ * - are we doing everything we should for ARM_COPY relocations?
* - cleaner error reporting
* - after linking, set as much stuff as possible to READONLY
* and NOEXEC
@@ -1469,17 +1470,52 @@ int soinfo::Relocate(ElfW(Rel)* rel, unsigned count) {
*reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
break;
case R_ARM_COPY:
- /*
- * ET_EXEC is not supported so this should not happen.
- *
- * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
- *
- * Section 4.7.1.10 "Dynamic relocations"
- * R_ARM_COPY may only appear in executable objects where e_type is
- * set to ET_EXEC.
- */
- DL_ERR("%s R_ARM_COPY relocations are not supported", name);
- return -1;
+#ifdef TARGET_ALLOW_NON_PIE_EXECUTABLES
+ if ((flags & FLAG_EXE) == 0) {
+#endif
+ /*
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+ *
+ * Section 4.7.1.10 "Dynamic relocations"
+ * R_ARM_COPY may only appear in executable objects where e_type is
+ * set to ET_EXEC.
+ *
+ * TODO: FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
+ * We should explicitly disallow ET_DYN executables from having
+ * R_ARM_COPY relocations.
+ */
+ DL_ERR("%s R_ARM_COPY relocations only supported for ET_EXEC", name);
+ return -1;
+#ifdef TARGET_ALLOW_NON_PIE_EXECUTABLES
+ }
+ count_relocation(kRelocCopy);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO %08x <- %d @ %08x %s", reloc, s->st_size, sym_addr, sym_name);
+ if (reloc == sym_addr) {
+ ElfW(Sym)* src = __soinfo_do_lookup(this, sym_name, &lsi, false);
+
+ if (src == NULL) {
+ DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", name);
+ return -1;
+ }
+ if (lsi->has_DT_SYMBOLIC) {
+ DL_ERR("%s invalid R_ARM_COPY relocation against DT_SYMBOLIC shared "
+ "library %s (built with -Bsymbolic?)", name, lsi->name);
+ return -1;
+ }
+ if (s->st_size < src->st_size) {
+ DL_ERR("%s R_ARM_COPY relocation size mismatch (%d < %d)",
+ name, s->st_size, src->st_size);
+ return -1;
+ }
+ memcpy(reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
+ } else {
+ DL_ERR("%s R_ARM_COPY relocation target cannot be resolved", name);
+ return -1;
+ }
+ break;
+#endif /* TARGET_ALLOW_NON_PIE_EXECUTABLES */
#elif defined(__i386__)
case R_386_JMP_SLOT:
count_relocation(kRelocAbsolute);
@@ -2407,8 +2443,12 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
if (elf_hdr->e_type != ET_DYN) {
+#ifdef TARGET_ALLOW_NON_PIE_EXECUTABLES
+ __libc_format_fd(2, "WARNING: legacy non-PIE executable, ASLR disabled\n");
+#else
__libc_format_fd(2, "error: only position independent executables (PIE) are supported.\n");
exit(EXIT_FAILURE);
+#endif
}
// Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
--
1.7.10.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment