aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Mower <mowerm@gmail.com>2017-01-25 11:39:38 -0600
committerZhao Wei Liew <zhaoweiliew@gmail.com>2017-02-11 01:41:20 +0000
commit55db1141913a77289abd293bca807e0520fd600a (patch)
tree06eb29d4efd9a8c5c012347f3bad4db4522c5809
parent4e0733db7e943a3ee892b7f55db8f91ea3b812db (diff)
downloadandroid_bionic-staging/cm-14.1-cafrebase.tar.gz
android_bionic-staging/cm-14.1-cafrebase.tar.bz2
android_bionic-staging/cm-14.1-cafrebase.zip
linker: Allow only specified non-PIE executablesstaging/cm-14.1-cafrebase
For devices that rely on (hopefully a small number of) vendor provided non position independent executables, a listing of those executables can be provided to the linker to allow them to run. This limits the severity of bypassing this security feature entirely. Header file linker_non_pie_executables.h should be created per-device, where the syntax of linker_non_pie_executables[] can be referenced from linker_non_pie.cpp in this commit. The linker is made aware of the header's existence via: LINKER_NON_PIE_EXECUTABLES_HEADER_DIR := path/to/include This commit is designed very closely to commit 'non-pie: Allow only select libs to be non-pie' (Ife1b2fcc75b418379fc382ae276e63905e8528e0) by Anthony King, but has been amended for use with Android 7.1. Change-Id: If4fe98e64bbdd91bfdec5de83247ea3d5688437e (cherry picked from commit 91b06f97680cfceabba61c1b7859de18d1709312)
-rw-r--r--linker/Android.mk6
-rw-r--r--linker/linker.cpp64
-rw-r--r--linker/linker_non_pie.cpp36
-rw-r--r--linker/linker_non_pie.h22
4 files changed, 94 insertions, 34 deletions
diff --git a/linker/Android.mk b/linker/Android.mk
index e729bff54..5e37812b3 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -59,8 +59,10 @@ LOCAL_CPPFLAGS += -DTARGET_NEEDS_PLATFORM_TEXT_RELOCATIONS
# We need to access Bionic private headers in the linker.
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../libc/
-ifeq ($(TARGET_NEEDS_NON_PIE_SUPPORT),true)
- LOCAL_CFLAGS += -DENABLE_NON_PIE_SUPPORT
+ifneq ($(LINKER_NON_PIE_EXECUTABLES_HEADER_DIR),)
+ LOCAL_CFLAGS += -DENABLE_NON_PIE_SUPPORT
+ LOCAL_C_INCLUDES += $(LINKER_NON_PIE_EXECUTABLES_HEADER_DIR)
+ LOCAL_SRC_FILES += linker_non_pie.cpp
endif
# we don't want crtbegin.o (because we have begin.o), so unset it
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 583dfd1f6..bff9b9fc6 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -60,6 +60,9 @@
#include "linker_relocs.h"
#include "linker_reloc_iterators.h"
#include "linker_utils.h"
+#ifdef ENABLE_NON_PIE_SUPPORT
+#include "linker_non_pie.h"
+#endif
#include "android-base/strings.h"
#include "ziparchive/zip_archive.h"
@@ -3132,7 +3135,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
*reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
break;
case R_ARM_COPY:
-#ifndef ENABLE_NON_PIE_SUPPORT
/*
* ET_EXEC is not supported so this should not happen.
*
@@ -3142,52 +3144,43 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
* 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", get_realpath());
- return false;
-#else
- if ((flags_ & FLAG_EXE) == 0) {
- /*
- * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
- *
- * Section 4.6.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.
- */
+#ifdef ENABLE_NON_PIE_SUPPORT
+ if (allow_non_pie(get_realpath())) {
+ if ((flags_ & FLAG_EXE) == 0) {
DL_ERR("%s R_ARM_COPY relocations only supported for ET_EXEC", get_realpath());
return false;
- }
- 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) {
+ }
+ 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) {
const ElfW(Sym)* src = nullptr;
if (!soinfo_do_lookup(NULL, sym_name, vi, &lsi, global_group, local_group, &src)) {
- DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", get_realpath());
- return false;
+ DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", get_realpath());
+ return false;
}
if (lsi->has_DT_SYMBOLIC) {
- DL_ERR("%s invalid R_ARM_COPY relocation against DT_SYMBOLIC shared "
- "library %s (built with -Bsymbolic?)", get_realpath(), lsi->soname_);
- return false;
+ DL_ERR("%s invalid R_ARM_COPY relocation against DT_SYMBOLIC shared "
+ "library %s (built with -Bsymbolic?)", get_realpath(), lsi->soname_);
+ return false;
}
if (s->st_size < src->st_size) {
- DL_ERR("%s R_ARM_COPY relocation size mismatch (%d < %d)",
- get_realpath(), s->st_size, src->st_size);
- return false;
+ DL_ERR("%s R_ARM_COPY relocation size mismatch (%d < %d)",
+ get_realpath(), s->st_size, src->st_size);
+ return false;
}
memcpy(reinterpret_cast<void*>(reloc),
reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
- } else {
+ } else {
DL_ERR("%s R_ARM_COPY relocation target cannot be resolved", get_realpath());
return false;
+ }
+ break;
}
- break;
#endif
+ DL_ERR("%s R_ARM_COPY relocations are not supported", get_realpath());
+ return false;
#elif defined(__i386__)
case R_386_32:
count_relocation(kRelocRelative);
@@ -4393,12 +4386,19 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
}
si->dynamic = nullptr;
-#ifndef ENABLE_NON_PIE_SUPPORT
+#ifdef ENABLE_NON_PIE_SUPPORT
+ if (allow_non_pie(executable_path)) {
+ DL_WARN("Non position independent executable (non PIE) allowed: %s",
+ executable_path);
+ } else {
+#endif
ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
if (elf_hdr->e_type != ET_DYN) {
__libc_fatal("\"%s\": error: only position independent executables (PIE) are supported.",
args.argv[0]);
}
+#ifdef ENABLE_NON_PIE_SUPPORT
+ }
#endif
// Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
diff --git a/linker/linker_non_pie.cpp b/linker/linker_non_pie.cpp
new file mode 100644
index 000000000..311f0ac1a
--- /dev/null
+++ b/linker/linker_non_pie.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * linker_non_pie_executables.h syntax:
+ *
+ * const char* linker_non_pie_executables[] = {
+ * "/path/to/executable1",
+ * "/path/to/executable2",
+ * };
+ */
+
+#include <string.h>
+#include "linker_non_pie_executables.h"
+
+bool allow_non_pie(const char* executable) {
+ const int array_len = sizeof(linker_non_pie_executables)/sizeof(*linker_non_pie_executables);
+ for (int i = 0; i < array_len; i++) {
+ if (!strcmp(linker_non_pie_executables[i], executable))
+ return true;
+ }
+ return false;
+}
diff --git a/linker/linker_non_pie.h b/linker/linker_non_pie.h
new file mode 100644
index 000000000..f6f66c653
--- /dev/null
+++ b/linker/linker_non_pie.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LINKER_NON_PIE_H_
+#define _LINKER_NON_PIE_H_
+
+bool allow_non_pie(const char* executable);
+
+#endif // _LINKER_NON_PIE_H_