lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 17 Sep 2013 05:43:32 -0700
From:	Russ Dill <Russ.Dill@...com>
To:	linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org,
	linux-omap@...r.kernel.org
Cc:	linux-kbuild@...r.kernel.org,
	Ard Biesheuvel <ard.biesheuvel@...aro.org>, mans@...sr.com,
	Shawn Guo <shawn.guo@...aro.org>,
	Dave Martin <Dave.Martin@....com>,
	Russell King - ARM Linux <linux@....linux.org.uk>
Subject: [RFC PATCH 06/11] ARM: PIE: Add position independent executable embedding to ARM

Add support to ARM for embedding PIEs into the kernel, loading them into
genalloc pools (such as SRAM) and executing them. Support for ARM means
performing R_ARM_RELATIVE fixups within the .rel.dyn section.

Signed-off-by: Russ Dill <Russ.Dill@...com>
---
 arch/arm/Kconfig              |  1 +
 arch/arm/Makefile             |  5 +++
 arch/arm/include/asm/elf.h    |  1 +
 arch/arm/kernel/.gitignore    |  1 +
 arch/arm/kernel/Makefile      |  4 ++-
 arch/arm/kernel/pie.c         | 83 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm/kernel/pie.lds.S     | 40 +++++++++++++++++++++
 arch/arm/kernel/vmlinux.lds.S |  2 ++
 arch/arm/libpie/.gitignore    |  3 ++
 arch/arm/libpie/Makefile      | 32 +++++++++++++++++
 arch/arm/libpie/empty.S       | 12 +++++++
 11 files changed, 183 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/kernel/pie.c
 create mode 100644 arch/arm/kernel/pie.lds.S
 create mode 100644 arch/arm/libpie/.gitignore
 create mode 100644 arch/arm/libpie/Makefile
 create mode 100644 arch/arm/libpie/empty.S

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 43594d5..de7b7603 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -49,6 +49,7 @@ config ARM
 	select HAVE_MEMBLOCK
 	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
 	select HAVE_PERF_EVENTS
+	select HAVE_PIE
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_UID16
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6fd2cea..a673d36 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -128,6 +128,8 @@ KBUILD_AFLAGS	+=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/uni
 
 CHECKFLAGS	+= -D__arm__
 
+OBJCOPY_OUTPUT_FORMAT := elf32-littlearm
+
 #Default value
 head-y		:= arch/arm/kernel/head$(MMUEXT).o
 textofs-y	:= 0x00008000
@@ -273,6 +275,9 @@ drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 
 libs-y				:= arch/arm/lib/ $(libs-y)
 
+PIE_LDS				:= arch/arm/kernel/pie.lds
+libpie-$(CONFIG_PIE)		+= arch/arm/libpie/
+
 # Default target when executing plain make
 ifeq ($(CONFIG_XIP_KERNEL),y)
 KBUILD_IMAGE := xipImage
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 56211f2..a8d036b 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
 #define R_ARM_NONE		0
 #define R_ARM_PC24		1
 #define R_ARM_ABS32		2
+#define R_ARM_RELATIVE		23
 #define R_ARM_CALL		28
 #define R_ARM_JUMP24		29
 #define R_ARM_V4BX		40
diff --git a/arch/arm/kernel/.gitignore b/arch/arm/kernel/.gitignore
index c5f676c..a055a48 100644
--- a/arch/arm/kernel/.gitignore
+++ b/arch/arm/kernel/.gitignore
@@ -1 +1,2 @@
 vmlinux.lds
+pie.lds
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 86d10dd..652312e 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -96,4 +96,6 @@ obj-y				+= psci.o
 obj-$(CONFIG_SMP)		+= psci_smp.o
 endif
 
-extra-y := $(head-y) vmlinux.lds
+obj-$(CONFIG_PIE)		+= pie.o
+
+extra-y := $(head-y) vmlinux.lds pie.lds
diff --git a/arch/arm/kernel/pie.c b/arch/arm/kernel/pie.c
new file mode 100644
index 0000000..5dff5d6
--- /dev/null
+++ b/arch/arm/kernel/pie.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013 Texas Instruments, Inc.
+ *	Russ Dill <russ.dill@...com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pie.h>
+#include <linux/elf.h>
+
+#include <asm/elf.h>
+
+extern char __pie_rel_dyn_start[];
+extern char __pie_rel_dyn_end[];
+extern char __pie_tail_offset[];
+
+struct arm_pie_tail {
+	int count;
+	uintptr_t offset[0];
+};
+
+int pie_arch_fill_tail(void *tail, void *common_start, void *common_end,
+			void *overlay_start, void *code_start, void *code_end)
+{
+	Elf32_Rel *rel;
+	int records;
+	int i;
+	struct arm_pie_tail *pie_tail = tail;
+	int count;
+
+	rel = (Elf32_Rel *) __pie_rel_dyn_start;
+	records = (__pie_rel_dyn_end - __pie_rel_dyn_start) /
+						sizeof(*rel);
+
+	count = 0;
+	for (i = 0; i < records; i++, rel++) {
+		void *kern_off;
+		if (ELF32_R_TYPE(rel->r_info) != R_ARM_RELATIVE)
+			return -ENOEXEC;
+
+		/* Adjust offset to match area in kernel */
+		kern_off = common_start + rel->r_offset;
+
+		if (kern_off >= common_start && kern_off < code_end) {
+			if (tail)
+				pie_tail->offset[count] = rel->r_offset;
+			count++;
+		} else if (kern_off >= code_start && kern_off < code_end) {
+			if (tail)
+				pie_tail->offset[count] = rel->r_offset -
+						(code_start - overlay_start);
+			count++;
+		}
+	}
+
+	if (tail)
+		pie_tail->count = count;
+
+	return count * sizeof(uintptr_t) + sizeof(*pie_tail);
+}
+EXPORT_SYMBOL_GPL(pie_arch_fill_tail);
+
+/*
+ * R_ARM_RELATIVE: B(S) + A
+ * B(S) - Addressing origin of the output segment defining the symbol S.
+ * A - Addend for the relocation.
+ */
+int pie_arch_fixup(struct pie_chunk *chunk, void *base, void *tail,
+						unsigned long offset)
+{
+	struct arm_pie_tail *pie_tail = tail;
+	int i;
+
+	/* Perform relocation fixups for given offset */
+	for (i = 0; i < pie_tail->count; i++)
+		*((uintptr_t *) (pie_tail->offset[i] + base)) += offset;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pie_arch_fixup);
diff --git a/arch/arm/kernel/pie.lds.S b/arch/arm/kernel/pie.lds.S
new file mode 100644
index 0000000..4fd5ac5
--- /dev/null
+++ b/arch/arm/kernel/pie.lds.S
@@ -0,0 +1,40 @@
+/*
+ * ld script to make ARM PIEs
+ * taken from the ARM vmlinux.lds.S version by Russ Dill <russ.dill@...com.
+ */
+
+#include <asm-generic/pie.lds.h>
+
+OUTPUT_ARCH(arm)
+
+SECTIONS
+{
+	. = 0x0;
+
+	PIE_COMMON_START
+	.got.plt : {
+		*(.got)
+		*(.got.plt)
+	}
+	.text : {
+		PIE_TEXT_TEXT
+	}
+	PIE_COMMON_END
+
+	PIE_OVERLAY_START
+	OVERLAY : NOCROSSREFS {
+	}
+	PIE_OVERLAY_SEND
+
+	__pie_rel_dyn_start : {
+		VMLINUX_SYMBOL(__pie_rel_dyn_start) = .;
+	}
+	.rel.dyn : {
+		KEEP(*(.rel*))
+	}
+	__pie_rel_dyn_end : {
+		VMLINUX_SYMBOL(__pie_rel_dyn_end) = .;
+	}
+
+	PIE_DISCARDS
+}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 7bcee5c..8c11235 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -77,6 +77,8 @@ SECTIONS
 #ifndef CONFIG_SMP_ON_UP
 		*(.alt.smp.init)
 #endif
+		*(.pie.*)
+		*(.ARM.exidx.pie.*.text)
 		*(.discard)
 		*(.discard.*)
 	}
diff --git a/arch/arm/libpie/.gitignore b/arch/arm/libpie/.gitignore
new file mode 100644
index 0000000..02e3cd5
--- /dev/null
+++ b/arch/arm/libpie/.gitignore
@@ -0,0 +1,3 @@
+lib1funcs.S
+ashldi3.S
+string.c
diff --git a/arch/arm/libpie/Makefile b/arch/arm/libpie/Makefile
new file mode 100644
index 0000000..5662e99
--- /dev/null
+++ b/arch/arm/libpie/Makefile
@@ -0,0 +1,32 @@
+#
+# linux/arch/arm/libpie/Makefile
+#
+ccflags-y	:= -fpic -mno-single-pic-base -fno-builtin
+
+obj-y		:= empty.o
+obj-y		+= lib1funcs.o ashldi3.o string.o
+
+# string library code (-Os is enforced to keep it much smaller)
+string = $(obj)/string.o
+CFLAGS_string.o := -Os
+
+$(obj)/string.c: $(srctree)/arch/$(SRCARCH)/boot/compressed/string.c
+	$(call cmd,shipped)
+
+# For __aeabi_uidivmod
+lib1funcs = $(obj)/lib1funcs.o
+
+$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
+	$(call cmd,shipped)
+
+# For __aeabi_llsl
+ashldi3 = $(obj)/ashldi3.o
+
+$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S
+	$(call cmd,shipped)
+
+$(obj)/libpie.o: $(string) $(lib1funcs) $(ashldi3) $(addprefix $(obj)/,$(OBJS))
+	$(call if_changed,ld)
+
+# Make sure files are removed during clean
+extra-y		+= string.c lib1funcs.S ashldi3.S
diff --git a/arch/arm/libpie/empty.S b/arch/arm/libpie/empty.S
new file mode 100644
index 0000000..2416862
--- /dev/null
+++ b/arch/arm/libpie/empty.S
@@ -0,0 +1,12 @@
+#include <linux/linkage.h>
+
+ENTRY(__div0)
+ENTRY(__aeabi_unwind_cpp_pr0)
+ENTRY(__aeabi_unwind_cpp_pr1)
+ENTRY(__aeabi_unwind_cpp_pr2)
+	mov	pc, lr
+ENDPROC(__div0)
+ENDPROC(__aeabi_unwind_cpp_pr0)
+ENDPROC(__aeabi_unwind_cpp_pr1)
+ENDPROC(__aeabi_unwind_cpp_pr2)
+
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ