From patchwork Tue Sep 17 12:43:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russ Dill X-Patchwork-Id: 2902291 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 36D90BFF05 for ; Tue, 17 Sep 2013 12:46:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 330272038C for ; Tue, 17 Sep 2013 12:46:15 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E7F082038B for ; Tue, 17 Sep 2013 12:46:08 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VLuea-0000dt-H8; Tue, 17 Sep 2013 12:45:17 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VLueL-0004D3-Hq; Tue, 17 Sep 2013 12:45:01 +0000 Received: from mail-pb0-x231.google.com ([2607:f8b0:400e:c01::231]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VLudh-00045s-NE for linux-arm-kernel@lists.infradead.org; Tue, 17 Sep 2013 12:44:29 +0000 Received: by mail-pb0-f49.google.com with SMTP id xb4so5477471pbc.22 for ; Tue, 17 Sep 2013 05:44:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=ml++wUG3RSXEeSPCJ7GzboV5zhYl/TcPJxJ6+HJlqMQ=; b=lH/7ohJsphGoHGJaaw+ozw3Nqb90ztm2SCwFYeXC4tWUs154SFexQbluxASJ4TwG32 MpT3nbWef8qD1UZO013fWKCCqQV0dnmS7qDrM5U/xNLH7CFBXiQIzprDs0BvJZWh+YVJ MHTZW7nTvMpcuRG4cDG9cdVgYiP9cGOCUtB39OWzdcCx+pS4LfUOFxDHDkiMtE1rRC7J K5/5dunPsgsGgRFgS2CdvN9K8swWbOsKPx+gR1KRVFLDBdOYJYHz1rYuHTouAygf/vWH VS1A0gJORbOuCV3wm+bgOr3a+8UqKfeWaeAYao/C2XQNh46KsIWTO1HjXtrrmMWNtQeC F/Fw== X-Received: by 10.68.200.136 with SMTP id js8mr13366814pbc.114.1379421844746; Tue, 17 Sep 2013 05:44:04 -0700 (PDT) Received: from localhost (pool-71-189-49-9.lsanca.fios.verizon.net. [71.189.49.9]) by mx.google.com with ESMTPSA id ct4sm38013072pbb.41.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 17 Sep 2013 05:44:04 -0700 (PDT) From: Russ Dill To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-omap@vger.kernel.org Subject: [RFC PATCH 06/11] ARM: PIE: Add position independent executable embedding to ARM Date: Tue, 17 Sep 2013 05:43:32 -0700 Message-Id: <1379421817-15759-7-git-send-email-Russ.Dill@ti.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1379421817-15759-1-git-send-email-Russ.Dill@ti.com> References: <1379421817-15759-1-git-send-email-Russ.Dill@ti.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130917_084422_014936_8157F189 X-CRM114-Status: GOOD ( 21.28 ) X-Spam-Score: -1.9 (-) Cc: mans@mansr.com, Russell King - ARM Linux , Ard Biesheuvel , linux-kbuild@vger.kernel.org, Shawn Guo , Dave Martin X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 + * + * 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 +#include +#include + +#include + +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 + +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 + +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) +