From patchwork Thu Aug 17 07:23:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 9905145 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 6CE0860386 for ; Thu, 17 Aug 2017 07:25:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5E5EC28ABE for ; Thu, 17 Aug 2017 07:25:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5343B28AC1; Thu, 17 Aug 2017 07:25:46 +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=-2.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW 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 70A1228ABE for ; Thu, 17 Aug 2017 07:25:45 +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=zbkARkir4TBYHwjr9SBWXIe4sgIiz0LY+UY8Q3iYCJs=; b=E+VIFMtq1DMuhzptImvBbiYOls VYHhq9tKtbpQt8xt8qxXO8Aql7DDyrfKaWovFQzgzP6uXq7azdwM3aonFNdhC7xssj4tYRTth84m8 gn2AjHwGFeFb5u6EMYV8+BXxXzd9PflZgkny1TKo3SRPZlY6I8N3uflrLXtKXpXRWpW/f6TVH62oo Zp0FzINcQXJhai/g5NWmAT3M+B2U3OgU8J8A0X6EiEAgwKWNAEeWkmu1OY6okLsQgYHfyg14WPQBq abaP4pvrXl+WkYMgXNkS2LF5dL1+GpCEKC3QyePZhJhuV5PhQjIx3slRnzpX8rIwUcYck0t6aaqu2 xQWD22bQ==; 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 1diFBU-0007a9-3J; Thu, 17 Aug 2017 07:25:40 +0000 Received: from merlin.infradead.org ([205.233.59.134]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1diFAU-0005OH-Pf for linux-arm-kernel@bombadil.infradead.org; Thu, 17 Aug 2017 07:24:38 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=ooHNEsEzxqsw8W4Nlsa/FlOxQTepIihmmtUBHAwR2Xo=; b=ghJcQpzC/EP02htifc5sYZQrI Ra4Dqo/c5A+cL6Nv7CROHQXy7jEOp42+YdEZ1Pa1SFTmtKMDIdlgvkSHx7TWgSDnCT9nYwLnULWcC hfkWcqUJC5S4wntr0yAxTf27GP/76nl9xC7eOC2veE82Albm7fACHjF4Qgfb9PHddo+TSq9/ru39G G74SOkfw7zWTIGouyU4RCeDoIkCjrTXc/tBRO98Kry7V1YbJLOgogBawZStDRebSu4xC5XnYP17a5 puwv3BqWI6KtOBipGPoTAB3Dv+ZbI2cSWXRDIYvBk0fCfzut+qo4mG0hhXNat9MUG7jjpQsjVbwJU RsEEb7CdQ==; Received: from pb-smtp2.pobox.com ([64.147.108.71] helo=sasl.smtp.pobox.com) by merlin.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1diFAQ-0003FH-Vv for linux-arm-kernel@lists.infradead.org; Thu, 17 Aug 2017 07:24:38 +0000 Received: from sasl.smtp.pobox.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 399EF97896; Thu, 17 Aug 2017 03:24:10 -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=cXNO gOW66GFb1duKAgV1O2z2V4Y=; b=YPiqBOJVLwQo61yXAKp+agiQzN0tFJ8jYoFu cxC6/kFSR79GZ4rntETnOh+JdvYNzDcdesQXDU22JmopCHai3ssygvg4q2/+mfJR /L/eeiHela8IybQxXRJKAaLP1c3qDoVSbPY42JSrXXmrLNEbJjcKCH6yS/rQ+QJZ ZjdCX/o= Received: from pb-smtp2.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 3071697894; Thu, 17 Aug 2017 03:24:10 -0400 (EDT) Received: from yoda.home (unknown [70.80.200.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp2.pobox.com (Postfix) with ESMTPSA id 94D3697890; Thu, 17 Aug 2017 03:24:09 -0400 (EDT) Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id E6CD42DA0698; Thu, 17 Aug 2017 03:24:08 -0400 (EDT) From: Nicolas Pitre To: Russell King - ARM Linux , linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 4/8] ARM: signal handling support for FDPIC_FUNCPTRS functions Date: Thu, 17 Aug 2017 03:23:43 -0400 Message-Id: <20170817072347.19990-5-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20170817072347.19990-1-nicolas.pitre@linaro.org> References: <20170817072347.19990-1-nicolas.pitre@linaro.org> X-Pobox-Relay-ID: 0F8C6C82-831D-11E7-8A23-9D2B0D78B957-78420484!pb-smtp2.pobox.com 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 Signal handlers are not direct function pointers but pointers to function descriptor in that case. Therefore we must retrieve the actual function address and load the GOT value into r9 from the descriptor before branching to the actual handler. If a restorer is provided, we also have to load its address and GOT from its descriptor. That descriptor address and the code to load it is pushed onto the stack to be executed as soon as the signal handler returns. However, to be compatible with NX stacks, the FDPIC bounce code is also copied to the signal page along with the other code stubs. Therefore this code must get at the descriptor address whether it executes from the stack or the signal page. To do so we use the stack pointer which points at the signal stack frame where the descriptor address was stored. Because the rt signal frame is different from the simpler frame, two versions of the bounce code are needed, and two variants (ARM and Thumb) as well. The asm-offsets facility is used to determine the actual offset in the signal frame for each version, meaning that struct sigframe and rt_sigframe had to be moved to a separate file. Signed-off-by: Nicolas Pitre Tested-by: Vincent Abriou --- arch/arm/include/asm/ucontext.h | 1 + arch/arm/kernel/asm-offsets.c | 4 +++ arch/arm/kernel/signal.c | 53 +++++++++++++++++++++++++----------- arch/arm/kernel/signal.h | 11 ++++++++ arch/arm/kernel/sigreturn_codes.S | 56 +++++++++++++++++++++++++++++++++++---- 5 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 arch/arm/kernel/signal.h diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h index 921d827485..b42c75ae0d 100644 --- a/arch/arm/include/asm/ucontext.h +++ b/arch/arm/include/asm/ucontext.h @@ -2,6 +2,7 @@ #define _ASMARM_UCONTEXT_H #include +#include /* * struct sigcontext only has room for the basic registers, but struct diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 608008229c..13c1558508 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -28,6 +28,7 @@ #include #include #include +#include "signal.h" /* * Make sure that the compiler and target are compatible. @@ -112,6 +113,9 @@ int main(void) DEFINE(SVC_ADDR_LIMIT, offsetof(struct svc_pt_regs, addr_limit)); DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs)); BLANK(); + DEFINE(SIGFRAME_RC3_OFFSET, offsetof(struct sigframe, retcode[3])); + DEFINE(RT_SIGFRAME_RC3_OFFSET, offsetof(struct rt_sigframe, sig.retcode[3])); + BLANK(); #ifdef CONFIG_CACHE_L2X0 DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base)); DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl)); diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 5814298ef0..1f3574ec4f 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -18,11 +18,12 @@ #include #include #include -#include #include #include -extern const unsigned long sigreturn_codes[7]; +#include "signal.h" + +extern const unsigned long sigreturn_codes[17]; static unsigned long signal_return_offset; @@ -171,15 +172,6 @@ static int restore_vfp_context(char __user **auxp) /* * Do a signal return; undo the signal stack. These are aligned to 64-bit. */ -struct sigframe { - struct ucontext uc; - unsigned long retcode[2]; -}; - -struct rt_sigframe { - struct siginfo info; - struct sigframe sig; -}; static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) { @@ -365,9 +357,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 = 0; unsigned long retcode; - int thumb = 0; + unsigned int idx, 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; @@ -407,9 +410,26 @@ 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 load the function descriptor. + * That code follows the standard sigreturn code + * (6 words), and is made of 3 + 2 words for each + * variant. The 4th copied word is the actual FD + * address that the assembly code expects. + */ + idx = 6 + thumb * 3; + if (ksig->ka.sa.sa_flags & SA_SIGINFO) + idx += 5; + if (__put_user(sigreturn_codes[idx], rc ) || + __put_user(sigreturn_codes[idx+1], rc+1) || + __put_user(sigreturn_codes[idx+2], rc+2) || + __put_user(retcode, rc+3)) + return 1; + goto rc_finish; + } } else { - unsigned int idx = thumb << 1; - + idx = thumb << 1; if (ksig->ka.sa.sa_flags & SA_SIGINFO) idx += 3; @@ -421,6 +441,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, __put_user(sigreturn_codes[idx+1], rc+1)) return 1; +rc_finish: #ifdef CONFIG_MMU if (cpsr & MODE32_BIT) { struct mm_struct *mm = current->mm; @@ -440,7 +461,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig, * the return code written onto the stack. */ flush_icache_range((unsigned long)rc, - (unsigned long)(rc + 2)); + (unsigned long)(rc + 3)); retcode = ((unsigned long)rc) + thumb; } @@ -450,6 +471,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/signal.h b/arch/arm/kernel/signal.h new file mode 100644 index 0000000000..b7b838b052 --- /dev/null +++ b/arch/arm/kernel/signal.h @@ -0,0 +1,11 @@ +#include + +struct sigframe { + struct ucontext uc; + unsigned long retcode[4]; +}; + +struct rt_sigframe { + struct siginfo info; + struct sigframe sig; +}; diff --git a/arch/arm/kernel/sigreturn_codes.S b/arch/arm/kernel/sigreturn_codes.S index b84d0cb136..2c7b22e321 100644 --- a/arch/arm/kernel/sigreturn_codes.S +++ b/arch/arm/kernel/sigreturn_codes.S @@ -14,6 +14,8 @@ * GNU General Public License for more details. */ +#include +#include #include /* @@ -51,6 +53,17 @@ ARM_OK( .arm ) .thumb .endm + .macro arm_fdpic_slot n + .org sigreturn_codes + 24 + 20 * (\n) +ARM_OK( .arm ) + .endm + + .macro thumb_fdpic_slot n + .org sigreturn_codes + 24 + 20 * (\n) + 12 + .thumb + .endm + + #if __LINUX_ARM_ARCH__ <= 4 /* * Note we manually set minimally required arch that supports @@ -90,13 +103,46 @@ ARM_OK( swi #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE) ) movs r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE) swi #0 + /* ARM sigreturn restorer FDPIC bounce code snippet */ + arm_fdpic_slot 0 +ARM_OK( ldr r3, [sp, #SIGFRAME_RC3_OFFSET] ) +ARM_OK( ldmia r3, {r3, r9} ) +#ifdef CONFIG_ARM_THUMB +ARM_OK( bx r3 ) +#else +ARM_OK( ret r3 ) +#endif + + /* Thumb sigreturn restorer FDPIC bounce code snippet */ + thumb_fdpic_slot 0 + ldr r3, [sp, #SIGFRAME_RC3_OFFSET] + ldmia r3, {r2, r3} + mov r9, r3 + bx r2 + + /* ARM sigreturn_rt restorer FDPIC bounce code snippet */ + arm_fdpic_slot 1 +ARM_OK( ldr r3, [sp, #RT_SIGFRAME_RC3_OFFSET] ) +ARM_OK( ldmia r3, {r3, r9} ) +#ifdef CONFIG_ARM_THUMB +ARM_OK( bx r3 ) +#else +ARM_OK( ret r3 ) +#endif + + /* Thumb sigreturn_rt restorer FDPIC bounce code snippet */ + thumb_fdpic_slot 1 + ldr r3, [sp, #RT_SIGFRAME_RC3_OFFSET] + ldmia r3, {r2, r3} + mov r9, r3 + bx r2 + /* - * Note on addtional space: setup_return in signal.c - * algorithm uses two words copy regardless whether - * it is thumb case or not, so we need additional - * word after real last entry. + * Note on additional space: setup_return in signal.c + * always copies the same number of words regardless whether + * it is thumb case or not, so we need one additional padding + * word after the last entry. */ - arm_slot 2 .space 4 .size sigreturn_codes, . - sigreturn_codes