From patchwork Sat Jul 29 03:51:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 9869725 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 399A26035E for ; Sat, 29 Jul 2017 03:53:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2B5B328799 for ; Sat, 29 Jul 2017 03:53:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1EF42287AE; Sat, 29 Jul 2017 03:53:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 622CE28799 for ; Sat, 29 Jul 2017 03:53:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=U76hHxQb6xN4xHjvNWgKHK8/ztXlKC1sLak+DV6YOYY=; b=tZ1sRlO3TN3Cw6mFh3g1WkvXmA 01CRiP9sbGtKExf27r/hKOI6UIY3yWVhlL7tbeVDTE+aC6qcCoO5xIRZdENItYxLLdiitzPRAucAW wu1jI5BeW/uNOIo1vk5Rld5Us+EUWQArTtx4MGzqkl/NLbQdScobcfZ8PQtSWZeegzOIFuHjWPj3U Xp4Pw3ntGE2CH5d9hUrROGO0t6PgHWE5dvu1Z+Lofd3ITlvajmYTszgAOBURCRFfgRZC9O/UaEsGD VOm+OJgtttlPxFarchplerlErP5jqoa+qfLUZMHFS1wkNw6TRzsKsfvB/RM5cMS5HRjMBIXPwmGCp rm8nk9Sw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dbIp1-0002ow-R1; Sat, 29 Jul 2017 03:53:47 +0000 Received: from pb-smtp1.pobox.com ([64.147.108.70] helo=sasl.smtp.pobox.com) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dbInb-0001c0-D8 for linux-arm-kernel@lists.infradead.org; Sat, 29 Jul 2017 03:52:24 +0000 Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by pb-smtp1.pobox.com (Postfix) with ESMTP id C5AC19EE26; Fri, 28 Jul 2017 23:51:56 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; s=sasl; bh=nfu1 Vw1Lzh2O45Fu0ChBlxR5CgI=; b=BEgdpIJJ3cRC5l1qjfSHRHpbtIr8XIkBk1dc XOqgYBi603jh0WLNz1HJi+kyuyf7kUMqAqEJDdBvdGYiUc5rQaWVqXORGTY+AZ8Y a1r+PdqMnbUGAm6z5eaJLept9X/Oga/e6PIP/RdIevPkHsiGm3eywg61kjo7hnwR GceNtBM= Received: from pb-smtp1.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp1.pobox.com (Postfix) with ESMTP id BC8C09EE25; Fri, 28 Jul 2017 23:51:56 -0400 (EDT) Received: from yoda.home (unknown [96.23.157.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp1.pobox.com (Postfix) with ESMTPSA id 22CCC9EE21; Fri, 28 Jul 2017 23:51:56 -0400 (EDT) Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id 6DBC52DA0692; Fri, 28 Jul 2017 23:51:55 -0400 (EDT) From: Nicolas Pitre To: Russell King - ARM Linux , linux-arm-kernel@lists.infradead.org Subject: [PATCH 4/4] ARM: add ELF_FDPIC support Date: Fri, 28 Jul 2017 23:51:50 -0400 Message-Id: <20170729035150.5214-5-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170729035150.5214-1-nicolas.pitre@linaro.org> References: <20170729035150.5214-1-nicolas.pitre@linaro.org> X-Pobox-Relay-ID: 43F6B254-7411-11E7-BF09-FE4B1A68708C-78420484!pb-smtp1.pobox.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170728_205219_620611_A0F47B97 X-CRM114-Status: GOOD ( 20.49 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Mickael Guene ." , Alexandre Torgue MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This includes the necessary code to recognise the FDPIC format on ARM, the handling of signal return code where function pointers are actually function descriptor pointers, and the ptrace command definitions used by the common ptrace code. Based on patches originally from Mickael Guene . Signed-off-by: Nicolas Pitre --- arch/arm/include/asm/elf.h | 12 ++++++++++++ arch/arm/include/asm/mmu.h | 4 ++++ arch/arm/include/uapi/asm/ptrace.h | 4 ++++ arch/arm/kernel/signal.c | 28 ++++++++++++++++++++++++++++ arch/arm/kernel/sigreturn_codes.S | 22 ++++++++++++++++++++++ fs/Kconfig.binfmt | 2 +- 6 files changed, 71 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index e2786acf82..ad0ca4f2ba 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -100,6 +100,11 @@ struct elf32_hdr; extern int elf_check_arch(const struct elf32_hdr *); #define elf_check_arch elf_check_arch +#define ELFOSABI_ARM_FDPIC 65 /* ARM FDPIC platform */ +#define elf_check_fdpic(x) ((x)->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC) +#define elf_check_const_displacement(x) ((x)->e_flags & EF_ARM_PIC) +#define ELF_FDPIC_CORE_EFLAGS 0 + #define vmcore_elf64_check_arch(x) (0) extern int arm_elf_read_implies_exec(int); @@ -120,6 +125,13 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs); have no such handler. */ #define ELF_PLAT_INIT(_r, load_addr) (_r)->ARM_r0 = 0 +#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, dynamic_addr) \ + do { \ + (_r)->ARM_r7 = _exec_map_addr; \ + (_r)->ARM_r8 = _interp_map_addr; \ + (_r)->ARM_r9 = dynamic_addr; \ + } while(0) + extern void elf_set_personality(const struct elf32_hdr *); #define SET_PERSONALITY(ex) elf_set_personality(&(ex)) diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index a5b4742105..e0eb16680a 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -33,6 +33,10 @@ typedef struct { */ typedef struct { unsigned long end_brk; +#ifdef CONFIG_BINFMT_ELF_FDPIC + unsigned long exec_fdpic_loadmap; + unsigned long interp_fdpic_loadmap; +#endif } mm_context_t; #endif diff --git a/arch/arm/include/uapi/asm/ptrace.h b/arch/arm/include/uapi/asm/ptrace.h index 5af0ed1b82..3173eb9751 100644 --- a/arch/arm/include/uapi/asm/ptrace.h +++ b/arch/arm/include/uapi/asm/ptrace.h @@ -31,6 +31,10 @@ #define PTRACE_SETVFPREGS 28 #define PTRACE_GETHBPREGS 29 #define PTRACE_SETHBPREGS 30 +#define PTRACE_GETFDPIC 31 + +#define PTRACE_GETFDPIC_EXEC 0 +#define PTRACE_GETFDPIC_INTERP 1 /* * PSR bits diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 7b8f214142..1deb6a3ab8 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -23,6 +23,7 @@ #include extern const unsigned long sigreturn_codes[7]; +extern const unsigned long sigreturn_fdpic_codes[6]; static unsigned long signal_return_offset; @@ -323,9 +324,20 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, unsigned long __user *rc, void __user *frame) { unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler; + unsigned long handler_fdpic_GOT; unsigned long retcode; int thumb = 0; unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT); + bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) && + (current->personality & FDPIC_FUNCPTRS); + + if (fdpic) { + unsigned long __user *fdpic_func_desc = + (unsigned long __user *)handler; + if (__get_user(handler, &fdpic_func_desc[0]) || + __get_user(handler_fdpic_GOT, &fdpic_func_desc[1])) + return 1; + } cpsr |= PSR_ENDSTATE; @@ -365,6 +377,20 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, if (ksig->ka.sa.sa_flags & SA_RESTORER) { retcode = (unsigned long)ksig->ka.sa.sa_restorer; + if (fdpic) { + /* We need code to process the function descriptor */ + const unsigned long *opcodes = sigreturn_fdpic_codes; + opcodes += thumb + (thumb << 1); + if (__put_user(opcodes[0], rc) || + __put_user(opcodes[1], rc+1) || + __put_user(opcodes[2], rc+2) || + __put_user(retcode, rc+3)) + return 1; + /* Last word is not executed, hence 3 words to flush */ + flush_icache_range((unsigned long)rc, + (unsigned long)(rc + 3)); + retcode = (unsigned long)rc + thumb; + } } else { unsigned int idx = thumb << 1; @@ -408,6 +434,8 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, regs->ARM_sp = (unsigned long)frame; regs->ARM_lr = retcode; regs->ARM_pc = handler; + if (fdpic) + regs->ARM_r9 = handler_fdpic_GOT; regs->ARM_cpsr = cpsr; return 0; diff --git a/arch/arm/kernel/sigreturn_codes.S b/arch/arm/kernel/sigreturn_codes.S index b84d0cb136..9bbb5bb883 100644 --- a/arch/arm/kernel/sigreturn_codes.S +++ b/arch/arm/kernel/sigreturn_codes.S @@ -100,3 +100,25 @@ ARM_OK( swi #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE) ) .space 4 .size sigreturn_codes, . - sigreturn_codes + +#ifdef CONFIG_BINFMT_ELF_FDPIC + + .global sigreturn_fdpic_codes + .type sigreturn_fdpic_codes, #object + .align +sigreturn_fdpic_codes: + +ARM_OK( .arm ) +ARM_OK( ldr ip, [pc, #4] ) /* get function descriptor */ +ARM_OK( ldr r9, [ip, #4] ) /* setup GOT register */ +ARM_OK( ldr pc, [ip] ) /* branch to function */ + + .org sigreturn_fdpic_codes + 3*4 + .thumb + ldr ip, [pc, #8] /* get function descriptor */ + ldr r9, [ip, #4] /* setup GOT register */ + ldr pc, [ip] /* branch to function */ + + .size sigreturn_fdpic_codes, . - sigreturn_fdpic_codes + +#endif diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index b2f82cf6bf..6ef70ce8e9 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -35,7 +35,7 @@ config ARCH_BINFMT_ELF_STATE config BINFMT_ELF_FDPIC bool "Kernel support for FDPIC ELF binaries" default y - depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X) + depends on ((ARM && !MMU) || FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X) select ELFCORE help ELF FDPIC binaries are based on ELF, but allow the individual load