From patchwork Mon Apr 13 19:44:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Tomsich X-Patchwork-Id: 6211621 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7107E9F313 for ; Mon, 13 Apr 2015 20:26:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 85887202E6 for ; Mon, 13 Apr 2015 20:26:13 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7B5BD202D1 for ; Mon, 13 Apr 2015 20:26:12 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Yhks7-0005iq-N4; Mon, 13 Apr 2015 20:22:19 +0000 Received: from vegas.theobroma-systems.com ([144.76.126.164] helo=mail.theobroma-systems.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YhkoI-0001kw-Az for linux-arm-kernel@lists.infradead.org; Mon, 13 Apr 2015 20:18:23 +0000 Received: from [86.59.122.178] (port=55147 helo=android.com) by mail.theobroma-systems.com with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1YhkIP-0001rr-GE; Mon, 13 Apr 2015 21:45:25 +0200 From: Philipp Tomsich To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v4 22/24] arm64:ilp32: use compat for stack_t Date: Mon, 13 Apr 2015 21:44:32 +0200 Message-Id: <09081413bd99e0a04e9783dc44fcd52eaeab1af1.1428953303.git.philipp.tomsich@theobroma-systems.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: References: In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150413_131822_582980_4271336D X-CRM114-Status: GOOD ( 15.86 ) X-Spam-Score: -0.0 (/) Cc: Andreas Kraschitzer , Benedikt Huber , Catalin Marinas , Andrew Pinski , Kumar Sankaran , Philipp Tomsich , Christoph Muellner X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 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.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, 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 We use a 'natively sized' stack_t in glibc (i.e. having a 32bit pointer for ss_sp), which requires the invocation of the compat layer for the following functionality: * sigaltstack * saving and restoring uc_stack during signal setup and returns As the userspace stack_t is natively sized, we avoid code duplication in the syscall table and can use the compat-functions to zero-extend the pointers involved. Signed-off-by: Philipp Tomsich Signed-off-by: Christoph Muellner --- arch/arm64/kernel/signal.c | 19 +++++++++++++++++++ arch/arm64/kernel/sys_ilp32.c | 44 +------------------------------------------ 2 files changed, 20 insertions(+), 43 deletions(-) diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 99e36be..b3f6e52 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -34,6 +34,7 @@ #include #include #include +#include /* * Do a signal return; undo the signal stack. These are aligned to 128-bit. @@ -148,9 +149,22 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigframe(regs, frame)) goto badframe; + +#if defined(CONFIG_ARM64_ILP32) + if (is_ilp32_compat_task()) { + /* For ILP32, we have a different stack_t (the ss_sp + field will be only 32bit sized), which fits into + the memory area reserved for the (larger) LP64 + stack_t and which we place into uc_stack: this + implies padding after the ILP32 stack_t. */ + if (compat_restore_altstack((compat_stack_t*)&frame->uc.uc_stack)) + goto badframe; + } else +#endif if (restore_altstack(&frame->uc.uc_stack)) goto badframe; + return regs->regs[0]; badframe: @@ -264,6 +278,11 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, __put_user_error(0, &frame->uc.uc_flags, err); __put_user_error(NULL, &frame->uc.uc_link, err); +#if defined(CONFIG_ARM64_ILP32) + if (is_ilp32_compat_task()) + err |= __compat_save_altstack((compat_stack_t*)&frame->uc.uc_stack, regs->sp); + else +#endif err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigframe(frame, regs, set); if (err == 0) { diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c index 3471f27..31f82ca 100644 --- a/arch/arm64/kernel/sys_ilp32.c +++ b/arch/arm64/kernel/sys_ilp32.c @@ -77,6 +77,7 @@ /* Pointer in struct */ #define sys_mount compat_sys_mount +#define sys_sigaltstack compat_sys_sigaltstack /* NUMA */ /* unsigned long bitmaps */ @@ -122,49 +123,6 @@ asmlinkage long ilp32_sys_mq_notify(mqd_t mqdes, const struct sigevent __user *u but need special handling due to padding for SIGEV_THREAD. */ #define sys_mq_notify ilp32_sys_mq_notify - -/* sigaltstack needs some special handling as the - padding for stack_t might not be non-zero. */ -long ilp32_sys_sigaltstack(const stack_t __user *uss_ptr, - stack_t __user *uoss_ptr) -{ - stack_t uss, uoss; - int ret; - mm_segment_t seg; - - if (uss_ptr) { - if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr))) - return -EFAULT; - if (__get_user(uss.ss_sp, &uss_ptr->ss_sp) | - __get_user(uss.ss_flags, &uss_ptr->ss_flags) | - __get_user(uss.ss_size, &uss_ptr->ss_size)) - return -EFAULT; - /* Zero extend the sp address and the size. */ - uss.ss_sp = (void *)(uintptr_t)(unsigned int)(uintptr_t)uss.ss_sp; - uss.ss_size = (size_t)(unsigned int)uss.ss_size; - } - seg = get_fs(); - set_fs(KERNEL_DS); - /* Note we need to use uoss as we have changed the segment to the - kernel one so passing an user one around is wrong. */ - ret = sys_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), - (stack_t __force __user *) &uoss); - set_fs(seg); - if (ret >= 0 && uoss_ptr) { - if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_t)) || - __put_user(uoss.ss_sp, &uoss_ptr->ss_sp) || - __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || - __put_user(uoss.ss_size, &uoss_ptr->ss_size)) - ret = -EFAULT; - } - return ret; -} - -/* sigaltstack needs some special handling as the padding - for stack_t might not be non-zero. */ -#define sys_sigaltstack ilp32_sys_sigaltstack - - #include #undef __SYSCALL