From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933807AbbLOVvS (ORCPT ); Tue, 15 Dec 2015 16:51:18 -0500 Received: from mail-bn1on0088.outbound.protection.outlook.com ([157.56.110.88]:61312 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932469AbbLOVvO (ORCPT ); Tue, 15 Dec 2015 16:51:14 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Yuri.Norov@caviumnetworks.com; From: Yury Norov To: , , , CC: , , , , , , , , , , , , , Subject: [PATCH v6 17/20] arm64: ilp32: introduce ilp32-specific handlers for sigframe Date: Wed, 16 Dec 2015 00:42:43 +0300 Message-ID: <1450215766-14765-18-git-send-email-ynorov@caviumnetworks.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1450215766-14765-1-git-send-email-ynorov@caviumnetworks.com> References: <1450215766-14765-1-git-send-email-ynorov@caviumnetworks.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [95.143.213.121] X-ClientProxiedBy: AM3PR08CA0007.eurprd08.prod.outlook.com (25.160.207.145) To DM2PR07MB624.namprd07.prod.outlook.com (10.141.177.154) X-Microsoft-Exchange-Diagnostics: 1;DM2PR07MB624;2:MlTwjiUu1YgGi9frS2DUlSizHPdaDJnPK1Gc4JD9bVpMYUQIzEixhWRrpOeEHAxqZi8VEu0qwLF0eHhBUYFoArPNvXWQ1ZntnfNC/rdYg6cDMUncVrzZRZxrslWdjMsLtyQy8XRwDfoFs0mYXU690Q==;3:PAoqyGVAkevguSSvC5MObCzx+7g0RAkoxSFUYCvXOb2+8w+BgZwnE8aOcCr/PC73XILSrOOOduPkTrBXtG8Icq9Axo6+4vW8fZvhAyUiGPdPBFoqnOvFx6ePzqzV/5m9;25:o9yu528F6hSBahOlvJ1ETl2Y8yImmp9FgX0/3t7VPQzdz1SsjI+DFQoy+QJiQJ+KMzDWWc8WrQ/J58xZEqxzGK+h+bU4VdrggExEP8VPiluc5PXV0YkGzqA1urekjFksXADzXpDU109f8K9PFZz0Pkbt2pChQQL6WUb1l9tsQydSSdqSbDeW5oGBA3X51y2nLt/6Nvn9N0197zWAMrok8FNgXMtOsf2m1Xdzo+KSZ1M9YcHjiEy+Bm9yIoP5XM0MwcxY60PxVQTxs7CPhXt7Tg== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DM2PR07MB624; X-Microsoft-Exchange-Diagnostics: 1;DM2PR07MB624;20:CJSEXQu9jDBoqJFkHeKu0HdxJ8VRaMQqkrf2P6WW2Gu0BKupLWoEV6bbyhYFk9N6Y6jofHiLAa1DxDhq60mj6BQ4tQuLW7l7inBqHSEgfZ/91aRcGcRHbFPL3PEfZXAbSEFNhR/l9c8I4teiI81u3YeHhRms7r2FjjtVjEIUh98LUJIowt7Q1cQX2XE8bOTKqMeafyV2OQbFZdrQnMYP+CFT8E/etCIFRvvV05+eUPyCGlyu6bmlJ+a9r662RmRKmW1msraWHSSuQiCEhltaYPwd7SBetM7uVpqf7tr36fPsV7vc38FWH8gaMOHdJHWSbl6G6lYtcZIIcVty7BLk9TixYzzqcHTY/OoTAHvDwZ2M9xq/ATxmCY9J2skyXW4Z23XfewuqgsKk3g+KtZosIselxQnaIG244JQ9DyJufoe2UHGFzZHnxG9xbKMsCpMYTuBY1+a37qAlbXLJ/0hp27R1CJnziTah5VlDdmilgOAzzWjphCYayuIeohJxw1Z43kw4A2Yz3iLAv/sV8Wrdla+cB+/+ehZlQIeu5QSXjLD+vFNzX4aUNrKAazxdc5Is26zxQ1o66VQTupskLDeE1Rdvp3+SYmBfC7FO+9uY6J0= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(236414709691187); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(8121501046)(5005006)(520078)(10201501046)(3002001);SRVR:DM2PR07MB624;BCL:0;PCL:0;RULEID:;SRVR:DM2PR07MB624; X-Microsoft-Exchange-Diagnostics: 1;DM2PR07MB624;4:sSBfG8TxZ1cMn/XtdQSsn5C3p+F+1MFvWYaslAvupRKRqMG0aVgIFIcPoH+/locqjNlwskZDSEFK4enQVqk47E6VU3/xlLI72V5aOm7Mny0eNHwhjHA5CbRo12z1F8c94vQXF1SBub/jHKwmraIcj+ZOZJvnEwb5s+4KM4qpoxtE5jsdUe2NZpTrBmCoNWD3NrVLEN+UGbjDQqrwDAZDo7nLrwb4/CK3huuwjGNSe9O5Qf7thGiCdx3BaolRpL2lh8yhKmTZGh5KfvbXnkusKNeABTzr/RdTnoeg/Sj7rimtUhhzzOhAfYD7u2m8HnstrK2jk6gkJip0xTIS0Opeg2fUl3fI0pmyouAJEH/CMprSzKvNniO1wUhkfV4ZKPZbU4DMKKI6m/me1KsMxP2/dlrVtxWmcBLSg9NcaUC5gvD7Cj6gK8H8ElCwYLmqurfp X-Forefront-PRVS: 07915F544A X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6009001)(6069001)(43544003)(199003)(189002)(87976001)(66066001)(229853001)(77096005)(42186005)(2201001)(122386002)(5008740100001)(92566002)(105586002)(50986999)(76176999)(76506005)(40100003)(106356001)(2950100001)(5003940100001)(19580405001)(3846002)(15975445007)(5001770100001)(50226001)(50466002)(47776003)(5004730100002)(5001960100002)(33646002)(19580395003)(101416001)(81156007)(586003)(36756003)(6116002)(189998001)(48376002)(97736004)(1096002)(2004002)(2101003);DIR:OUT;SFP:1101;SCL:1;SRVR:DM2PR07MB624;H:localhost;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;DM2PR07MB624;23:/6djVCL2X0daLumsrGGHlTPLDe6aS6tcUNc6n23ugH?= =?us-ascii?Q?5fUoWTtqAUoWVLk1ZnKZriMmGGrlgqxnd6uotxtz50GXhAwZ+VgnUjRPNGe4?= =?us-ascii?Q?3BCE+OKFp++qqwS2UCG+LIv6aCSyn4KKDf+lNQSijaQgWpz+OGPLd56wYG6K?= =?us-ascii?Q?x8tn6WtWg6X3iMg10xw7/UJSXHplrfVieMNgz3PDw1ID1ndkKHX4NHD78nn3?= =?us-ascii?Q?O02GzbTBXOk367Cx+kprsrC2SYsFdHSwRt3eMtiPstlz9ZPCk/Z4CCy1dZT5?= =?us-ascii?Q?uRrgBA9PPF//Kc4OpwxspoIYR3vfNsbE9jesv3U026yTTA6X/fqnbdpS1V95?= =?us-ascii?Q?Thsuv3hQAxB+gmTxgjK41CZStFmcPHhbVKnLKE8lv8Soe8iCKWr/z27GoNw+?= =?us-ascii?Q?RyIz+UMhO58BsrIgQWjW+nAocTewFmbcqDIZVI01PeFstzUgm5kvknIjeXnv?= =?us-ascii?Q?l+D7yJ1wR8DutkkI/XhNQflvzpcGmdGgP2M2pkwH3rBqeTk6jphc4VCmPYzi?= =?us-ascii?Q?cEeVgKDw1AoSAD0PSvTCHY1dh6eRzRQMdKSUkVWVbx99DEobB2l0B1D98myC?= =?us-ascii?Q?QwIhTUFFdP8uIjuBy6+ibUxLcQupNpPr/EvCPKVfPEL+F06lR8OH6tKqbIT/?= =?us-ascii?Q?wfPwuNRQ1tENN5oBBhSdYlmWay66CwDcrDZzy2ZlLd1QSeFiW2lZ77vb7fz0?= =?us-ascii?Q?HokQSkSElJ+b0oWw1oAuDqJ6bBMgOaj8LX4ItgwjbdmDPlAOBQQvzLDt4Ivu?= =?us-ascii?Q?VaRwQuCMLRKouQYtqwhawDU8MvwW7c0I+O7MPgWrOTmquES7Yz7wD0BmOW8g?= =?us-ascii?Q?YUnGgCBtoU0dhC+yz9QPYJR/43TNmj5kFmF1P0XwBfV+LWWGaZoJzjWKgLm/?= =?us-ascii?Q?YoSv8/8ZrtHZfOHEVba3mDKtyMwXRrxQRIuhytv5z5/z3RHKj6AdgG4KHMiR?= =?us-ascii?Q?za4X1qBd5G3FM4p8GgA+trrFWHwEXX/Fpuxj7l8iguf+SAR+WMr96NMWDLqO?= =?us-ascii?Q?/Fuk/rzzmFZy2MdbuVS9T6wOSRkGqNCmcG5E/C60pfoFPYnDTVSy32EGCfc/?= =?us-ascii?Q?TLFQS6TP9/iSX9e7o+hDvUmKvSPrkwO8nrdAHxkSLeAfYidj2++c2AfA74dk?= =?us-ascii?Q?k7Uv6ArombK3sONIQJVbPtbnrkGq1IyF9LLOlLTS2E9FErvy7onw=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;DM2PR07MB624;5:uLbdgElsKmq0t1SrPvrGbAWfU479qEqQwC0ErR78MzWSl41wQS2p+6OhwUTpA5bER+5VjizHQIsQ2Q53jGQ9swju7kVZrKQZtlYkSZOaS+yEoryHwReapr9APNM+Lsf7DP19LIzCRKQJAAUgZ8v7fQ==;24:XRcxnverO96eVgAlng868g03ls5uJvLOrRGRKUd1X5lqsy6CFkD1B/MpApzAn4k/Rz2LWFgWzLjofGX1IWnu1NB596I6wL2oEArCE7HyQUo= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Dec 2015 21:51:10.8662 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR07MB624 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org ILP32 uses AARCH32 compat structures and syscall handlers for signals. But ILP32 struct rt_sigframe differs from both LP64 and AARCH32. So some specific mechanism is needed to take care of it. Signed-off-by: Yury Norov --- arch/arm64/include/asm/signal_ilp32.h | 38 ++++++++++ arch/arm64/kernel/Makefile | 2 +- arch/arm64/kernel/entry_ilp32.S | 32 +++++++++ arch/arm64/kernel/signal.c | 3 + arch/arm64/kernel/signal_ilp32.c | 126 ++++++++++++++++++++++++++++++++++ arch/arm64/kernel/sys_ilp32.c | 3 + 6 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/include/asm/signal_ilp32.h create mode 100644 arch/arm64/kernel/entry_ilp32.S create mode 100644 arch/arm64/kernel/signal_ilp32.c diff --git a/arch/arm64/include/asm/signal_ilp32.h b/arch/arm64/include/asm/signal_ilp32.h new file mode 100644 index 0000000..81e1909 --- /dev/null +++ b/arch/arm64/include/asm/signal_ilp32.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 Cavium Networks. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef __ASM_SIGNAL_ILP32_H +#define __ASM_SIGNAL_ILP32_H + +#ifdef __KERNEL__ +#ifdef CONFIG_ARM64_ILP32 + +#include + +int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, + struct pt_regs *regs); + +#else + +static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, + struct pt_regs *regs) +{ + return -ENOSYS; +} + +#endif /* CONFIG_ARM64_ILP32 */ + +#endif /* __KERNEL__ */ +#endif /* __ASM_SIGNAL_ILP32_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index f90fb08..f92e707 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -24,7 +24,7 @@ arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \ sys_compat.o entry32.o \ ../../arm/kernel/opcodes.o arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o -arm64-obj-$(CONFIG_ARM64_ILP32) += sys_ilp32.o +arm64-obj-$(CONFIG_ARM64_ILP32) += signal_ilp32.o sys_ilp32.o entry_ilp32.o arm64-obj-$(CONFIG_COMPAT) += entry32-common.o signal32_common.o arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o diff --git a/arch/arm64/kernel/entry_ilp32.S b/arch/arm64/kernel/entry_ilp32.S new file mode 100644 index 0000000..424060f --- /dev/null +++ b/arch/arm64/kernel/entry_ilp32.S @@ -0,0 +1,32 @@ +/* + * ILP32 system call wrappers + * + * Copyright (C) 2015 Cavium Networks. + * Author: Yury Norov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include +#include +#include +#include + +ENTRY(ilp32_sys_rt_sigreturn_wrapper) + mov x0, sp + b ilp32_sys_rt_sigreturn +ENDPROC(ilp32_sys_rt_sigreturn_wrapper) + diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 4b8efe5..d67a9b8 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. @@ -153,6 +154,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) ret = compat_setup_rt_frame(usig, ksig, oldset, regs); else ret = compat_setup_frame(usig, ksig, oldset, regs); + } else if (is_ilp32_compat_task()) { + ret = ilp32_setup_rt_frame(usig, ksig, oldset, regs); } else { ret = setup_rt_frame(usig, ksig, oldset, regs); } diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c new file mode 100644 index 0000000..d38434b --- /dev/null +++ b/arch/arm64/kernel/signal_ilp32.c @@ -0,0 +1,126 @@ +/* + * Based on arch/arm/kernel/signal.c + * + * Copyright (C) 2015 Cavium Networks. + * Yury Norov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +struct ilp32_rt_sigframe { + struct compat_siginfo info; + struct sigframe sig; +}; + +asmlinkage int ilp32_sys_rt_sigreturn(struct pt_regs *regs) +{ + struct ilp32_rt_sigframe __user *frame; + + /* Always make any pending restarted system calls return -EINTR */ + current->restart_block.fn = do_no_restart_syscall; + + /* + * Since we stacked the signal on a 64-bit boundary, + * then 'sp' should be word aligned here. If it's + * not, then the user is trying to mess with us. + */ + if (regs->sp & 15) + goto badframe; + + frame = (struct ilp32_rt_sigframe __user *)regs->sp; + + if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) + goto badframe; + + if (restore_sigframe(regs, &frame->sig)) + goto badframe; + + if (restore_altstack(&frame->sig.uc.uc_stack)) + goto badframe; + + return regs->regs[0]; + +badframe: + if (show_unhandled_signals) + pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n", + current->comm, task_pid_nr(current), __func__, + regs->pc, regs->compat_sp); + force_sig(SIGSEGV, current); + return 0; +} + +static struct ilp32_rt_sigframe __user *ilp32_get_sigframe(struct ksignal *ksig, + struct pt_regs *regs) +{ + unsigned long sp, sp_top; + struct ilp32_rt_sigframe __user *frame; + + sp = sp_top = sigsp(regs->sp, ksig); + + sp = (sp - sizeof(struct ilp32_rt_sigframe)) & ~15; + frame = (struct ilp32_rt_sigframe __user *)sp; + + /* + * Check that we can actually write to the signal frame. + */ + if (!access_ok(VERIFY_WRITE, frame, sp_top - sp)) + frame = NULL; + + return frame; +} + +/* + * ILP32 signal handling routines called from signal.c + */ +int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, + sigset_t *set, struct pt_regs *regs) +{ + struct ilp32_rt_sigframe __user *frame; + int err = 0; + + frame = ilp32_get_sigframe(ksig, regs); + + if (!frame) + return 1; + + __put_user_error(0, &frame->sig.uc.uc_flags, err); + __put_user_error(NULL, &frame->sig.uc.uc_link, err); + + err |= __save_altstack(&frame->sig.uc.uc_stack, regs->sp); + err |= setup_sigframe(&frame->sig, regs, set); + if (err == 0) { + setup_return(regs, &ksig->ka, frame, + offsetof(struct ilp32_rt_sigframe, sig), usig); + if (ksig->ka.sa.sa_flags & SA_SIGINFO) { + err |= copy_siginfo_to_user32(&frame->info, &ksig->info); + regs->regs[1] = (unsigned long)&frame->info; + regs->regs[2] = (unsigned long)&frame->sig.uc; + } + } + + return err; +} + diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c index c282fa2..1882bb3 100644 --- a/arch/arm64/kernel/sys_ilp32.c +++ b/arch/arm64/kernel/sys_ilp32.c @@ -54,6 +54,9 @@ asmlinkage long compat_sys_fstatfs64_wrapper(void); asmlinkage long compat_sys_statfs64_wrapper(void); #define compat_sys_statfs64 compat_sys_statfs64_wrapper +asmlinkage long ilp32_sys_rt_sigreturn_wrapper(void); +#define compat_sys_rt_sigreturn ilp32_sys_rt_sigreturn_wrapper + #include #undef __SYSCALL -- 2.5.0 From mboxrd@z Thu Jan 1 00:00:00 1970 From: ynorov@caviumnetworks.com (Yury Norov) Date: Wed, 16 Dec 2015 00:42:43 +0300 Subject: [PATCH v6 17/20] arm64: ilp32: introduce ilp32-specific handlers for sigframe In-Reply-To: <1450215766-14765-1-git-send-email-ynorov@caviumnetworks.com> References: <1450215766-14765-1-git-send-email-ynorov@caviumnetworks.com> Message-ID: <1450215766-14765-18-git-send-email-ynorov@caviumnetworks.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org ILP32 uses AARCH32 compat structures and syscall handlers for signals. But ILP32 struct rt_sigframe differs from both LP64 and AARCH32. So some specific mechanism is needed to take care of it. Signed-off-by: Yury Norov --- arch/arm64/include/asm/signal_ilp32.h | 38 ++++++++++ arch/arm64/kernel/Makefile | 2 +- arch/arm64/kernel/entry_ilp32.S | 32 +++++++++ arch/arm64/kernel/signal.c | 3 + arch/arm64/kernel/signal_ilp32.c | 126 ++++++++++++++++++++++++++++++++++ arch/arm64/kernel/sys_ilp32.c | 3 + 6 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/include/asm/signal_ilp32.h create mode 100644 arch/arm64/kernel/entry_ilp32.S create mode 100644 arch/arm64/kernel/signal_ilp32.c diff --git a/arch/arm64/include/asm/signal_ilp32.h b/arch/arm64/include/asm/signal_ilp32.h new file mode 100644 index 0000000..81e1909 --- /dev/null +++ b/arch/arm64/include/asm/signal_ilp32.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 Cavium Networks. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef __ASM_SIGNAL_ILP32_H +#define __ASM_SIGNAL_ILP32_H + +#ifdef __KERNEL__ +#ifdef CONFIG_ARM64_ILP32 + +#include + +int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, + struct pt_regs *regs); + +#else + +static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, + struct pt_regs *regs) +{ + return -ENOSYS; +} + +#endif /* CONFIG_ARM64_ILP32 */ + +#endif /* __KERNEL__ */ +#endif /* __ASM_SIGNAL_ILP32_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index f90fb08..f92e707 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -24,7 +24,7 @@ arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \ sys_compat.o entry32.o \ ../../arm/kernel/opcodes.o arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o -arm64-obj-$(CONFIG_ARM64_ILP32) += sys_ilp32.o +arm64-obj-$(CONFIG_ARM64_ILP32) += signal_ilp32.o sys_ilp32.o entry_ilp32.o arm64-obj-$(CONFIG_COMPAT) += entry32-common.o signal32_common.o arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o diff --git a/arch/arm64/kernel/entry_ilp32.S b/arch/arm64/kernel/entry_ilp32.S new file mode 100644 index 0000000..424060f --- /dev/null +++ b/arch/arm64/kernel/entry_ilp32.S @@ -0,0 +1,32 @@ +/* + * ILP32 system call wrappers + * + * Copyright (C) 2015 Cavium Networks. + * Author: Yury Norov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include +#include +#include +#include + +ENTRY(ilp32_sys_rt_sigreturn_wrapper) + mov x0, sp + b ilp32_sys_rt_sigreturn +ENDPROC(ilp32_sys_rt_sigreturn_wrapper) + diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 4b8efe5..d67a9b8 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. @@ -153,6 +154,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) ret = compat_setup_rt_frame(usig, ksig, oldset, regs); else ret = compat_setup_frame(usig, ksig, oldset, regs); + } else if (is_ilp32_compat_task()) { + ret = ilp32_setup_rt_frame(usig, ksig, oldset, regs); } else { ret = setup_rt_frame(usig, ksig, oldset, regs); } diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c new file mode 100644 index 0000000..d38434b --- /dev/null +++ b/arch/arm64/kernel/signal_ilp32.c @@ -0,0 +1,126 @@ +/* + * Based on arch/arm/kernel/signal.c + * + * Copyright (C) 2015 Cavium Networks. + * Yury Norov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +struct ilp32_rt_sigframe { + struct compat_siginfo info; + struct sigframe sig; +}; + +asmlinkage int ilp32_sys_rt_sigreturn(struct pt_regs *regs) +{ + struct ilp32_rt_sigframe __user *frame; + + /* Always make any pending restarted system calls return -EINTR */ + current->restart_block.fn = do_no_restart_syscall; + + /* + * Since we stacked the signal on a 64-bit boundary, + * then 'sp' should be word aligned here. If it's + * not, then the user is trying to mess with us. + */ + if (regs->sp & 15) + goto badframe; + + frame = (struct ilp32_rt_sigframe __user *)regs->sp; + + if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) + goto badframe; + + if (restore_sigframe(regs, &frame->sig)) + goto badframe; + + if (restore_altstack(&frame->sig.uc.uc_stack)) + goto badframe; + + return regs->regs[0]; + +badframe: + if (show_unhandled_signals) + pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n", + current->comm, task_pid_nr(current), __func__, + regs->pc, regs->compat_sp); + force_sig(SIGSEGV, current); + return 0; +} + +static struct ilp32_rt_sigframe __user *ilp32_get_sigframe(struct ksignal *ksig, + struct pt_regs *regs) +{ + unsigned long sp, sp_top; + struct ilp32_rt_sigframe __user *frame; + + sp = sp_top = sigsp(regs->sp, ksig); + + sp = (sp - sizeof(struct ilp32_rt_sigframe)) & ~15; + frame = (struct ilp32_rt_sigframe __user *)sp; + + /* + * Check that we can actually write to the signal frame. + */ + if (!access_ok(VERIFY_WRITE, frame, sp_top - sp)) + frame = NULL; + + return frame; +} + +/* + * ILP32 signal handling routines called from signal.c + */ +int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, + sigset_t *set, struct pt_regs *regs) +{ + struct ilp32_rt_sigframe __user *frame; + int err = 0; + + frame = ilp32_get_sigframe(ksig, regs); + + if (!frame) + return 1; + + __put_user_error(0, &frame->sig.uc.uc_flags, err); + __put_user_error(NULL, &frame->sig.uc.uc_link, err); + + err |= __save_altstack(&frame->sig.uc.uc_stack, regs->sp); + err |= setup_sigframe(&frame->sig, regs, set); + if (err == 0) { + setup_return(regs, &ksig->ka, frame, + offsetof(struct ilp32_rt_sigframe, sig), usig); + if (ksig->ka.sa.sa_flags & SA_SIGINFO) { + err |= copy_siginfo_to_user32(&frame->info, &ksig->info); + regs->regs[1] = (unsigned long)&frame->info; + regs->regs[2] = (unsigned long)&frame->sig.uc; + } + } + + return err; +} + diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c index c282fa2..1882bb3 100644 --- a/arch/arm64/kernel/sys_ilp32.c +++ b/arch/arm64/kernel/sys_ilp32.c @@ -54,6 +54,9 @@ asmlinkage long compat_sys_fstatfs64_wrapper(void); asmlinkage long compat_sys_statfs64_wrapper(void); #define compat_sys_statfs64 compat_sys_statfs64_wrapper +asmlinkage long ilp32_sys_rt_sigreturn_wrapper(void); +#define compat_sys_rt_sigreturn ilp32_sys_rt_sigreturn_wrapper + #include #undef __SYSCALL -- 2.5.0