From: ynorov@caviumnetworks.com (Yury Norov)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 17/20] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext
Date: Mon, 9 Jan 2017 16:59:54 +0530 [thread overview]
Message-ID: <1483961397-8599-18-git-send-email-ynorov@caviumnetworks.com> (raw)
In-Reply-To: <1483961397-8599-1-git-send-email-ynorov@caviumnetworks.com>
From: Andrew Pinski <apinski@cavium.com>
ILP32 uses AARCH32 compat structures and syscall handlers for signals.
But ILP32 struct rt_sigframe and ucontext differs from both LP64 and
AARCH32. So some specific mechanism is needed to take care of it.
Signed-off-by: Andrew Pinski <Andrew.Pinski@caviumnetworks.com>
Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
---
arch/arm64/include/asm/signal_ilp32.h | 38 ++++++++
arch/arm64/kernel/Makefile | 3 +-
arch/arm64/kernel/entry_ilp32.S | 22 +++++
arch/arm64/kernel/signal.c | 3 +
arch/arm64/kernel/signal_ilp32.c | 170 ++++++++++++++++++++++++++++++++++
5 files changed, 235 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..3c6d737
--- /dev/null
+++ b/arch/arm64/include/asm/signal_ilp32.h
@@ -0,0 +1,38 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/signal32_common.h>
+#include <asm/signal_common.h>
+
+#ifndef __ASM_SIGNAL_ILP32_H
+#define __ASM_SIGNAL_ILP32_H
+
+#ifdef CONFIG_ARM64_ILP32
+
+#include <linux/compat.h>
+
+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 /* __ASM_SIGNAL_ILP32_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index fdc0052..af400fb 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -29,7 +29,8 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o entry32.o binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o \
+ signal_ilp32.o entry_ilp32.o
arm64-obj-$(CONFIG_COMPAT) += entry32_common.o signal32_common.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
diff --git a/arch/arm64/kernel/entry_ilp32.S b/arch/arm64/kernel/entry_ilp32.S
new file mode 100644
index 0000000..a8bb94b
--- /dev/null
+++ b/arch/arm64/kernel/entry_ilp32.S
@@ -0,0 +1,22 @@
+/*
+ * ILP32 system call wrappers
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+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 9f2ea60..b78f4c2 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -35,6 +35,7 @@
#include <asm/signal32.h>
#include <asm/vdso.h>
#include <asm/signal_common.h>
+#include <asm/signal_ilp32.h>
#define RT_SIGFRAME_FP_POS (offsetof(struct rt_sigframe, sig) \
+ offsetof(struct sigframe, fp))
@@ -325,6 +326,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..b9a3372
--- /dev/null
+++ b/arch/arm64/kernel/signal_ilp32.c
@@ -0,0 +1,170 @@
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2017 Cavium Networks.
+ * Yury Norov <ynorov@caviumnetworks.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compat.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/ratelimit.h>
+
+#include <asm/esr.h>
+#include <asm/fpsimd.h>
+#include <asm/signal_ilp32.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/ucontext.h>
+
+
+#define ILP32_RT_SIGFRAME_FP_POS (offsetof(struct ilp32_rt_sigframe, sig) \
+ + offsetof(struct ilp32_sigframe, fp))
+
+struct ilp32_ucontext {
+ u32 uc_flags;
+ u32 uc_link;
+ compat_stack_t uc_stack;
+ compat_sigset_t uc_sigmask;
+ /* glibc uses a 1024-bit sigset_t */
+ __u8 __unused[1024 / 8 - sizeof(compat_sigset_t)];
+ /* last for future expansion */
+ struct sigcontext uc_mcontext;
+};
+
+struct ilp32_sigframe {
+ struct ilp32_ucontext uc;
+ u64 fp;
+ u64 lr;
+};
+
+struct ilp32_rt_sigframe {
+ struct compat_siginfo info;
+ struct ilp32_sigframe sig;
+};
+
+static int restore_ilp32_sigframe(struct pt_regs *regs,
+ struct ilp32_sigframe __user *sf)
+{
+ sigset_t set;
+ int err;
+ err = get_sigset_t(&set, &sf->uc.uc_sigmask);
+ if (err == 0)
+ set_current_blocked(&set);
+ err |= restore_sigcontext(regs, &sf->uc.uc_mcontext);
+ return err;
+}
+
+static int setup_ilp32_sigframe(struct ilp32_sigframe __user *sf,
+ struct pt_regs *regs, sigset_t *set)
+{
+ int err = 0;
+ /* set up the stack frame for unwinding */
+ __put_user_error(regs->regs[29], &sf->fp, err);
+ __put_user_error(regs->regs[30], &sf->lr, err);
+
+ err |= put_sigset_t(&sf->uc.uc_sigmask, set);
+ err |= setup_sigcontext(&sf->uc.uc_mcontext, regs);
+ return err;
+}
+
+asmlinkage long 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 128-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_ilp32_sigframe(regs, &frame->sig))
+ goto badframe;
+
+ if (compat_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->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;
+
+ err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
+
+ __put_user_error(0, &frame->sig.uc.uc_flags, err);
+ __put_user_error(0, &frame->sig.uc.uc_link, err);
+
+ err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->sp);
+ err |= setup_ilp32_sigframe(&frame->sig, regs, set);
+ if (err == 0) {
+ setup_return(regs, &ksig->ka, frame, ILP32_RT_SIGFRAME_FP_POS, usig);
+ regs->regs[1] = (unsigned long)&frame->info;
+ regs->regs[2] = (unsigned long)&frame->sig.uc;
+ }
+
+ return err;
+}
--
2.7.4
next prev parent reply other threads:[~2017-01-09 11:29 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-09 11:29 [PATCH v7 00/20] ILP32 for ARM64 Yury Norov
2017-01-09 11:29 ` [PATCH 01/20] compat ABI: use non-compat openat and open_by_handle_at variants Yury Norov
2017-01-09 11:29 ` [PATCH 02/20] 32-bit ABI: introduce ARCH_32BIT_OFF_T config option Yury Norov
2017-01-09 11:29 ` [PATCH 04/20] arm64: ilp32: add documentation on the ILP32 ABI for ARM64 Yury Norov
2017-01-09 11:29 ` [PATCH 05/20] arm64: rename COMPAT to AARCH32_EL0 in Kconfig Yury Norov
2017-01-09 11:29 ` [PATCH 06/20] arm64: ensure the kernel is compiled for LP64 Yury Norov
2017-01-09 11:29 ` [PATCH 07/20] arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64 Yury Norov
2017-01-09 11:29 ` [PATCH 08/20] thread: move thread bits accessors to separated file Yury Norov
2017-01-09 11:29 ` [PATCH 09/20] arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat) Yury Norov
2017-01-09 11:29 ` [PATCH 10/20] arm64: ilp32: add is_ilp32_compat_{task, thread} and TIF_32BIT_AARCH64 Yury Norov
2017-01-09 11:29 ` [PATCH 11/20] arm64: introduce binfmt_elf32.c Yury Norov
2017-01-09 11:29 ` [PATCH 12/20] arm64: ilp32: introduce binfmt_ilp32.c Yury Norov
2017-01-09 11:29 ` [PATCH 13/20] arm64: ilp32: share aarch32 syscall handlers Yury Norov
2017-01-09 11:29 ` [PATCH 14/20] arm64: ilp32: add sys_ilp32.c and a separate table (in entry.S) to use it Yury Norov
2017-01-09 11:29 ` [PATCH 15/20] arm64: signal: share lp64 signal routines to ilp32 Yury Norov
2017-01-09 11:29 ` [PATCH 16/20] arm64: signal32: move ilp32 and aarch32 common code to separated file Yury Norov
2017-01-09 11:29 ` Yury Norov [this message]
2017-01-09 11:29 ` [PATCH 18/20] arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32 Yury Norov
2017-01-09 11:29 ` [PATCH 19/20] arm64:ilp32: add vdso-ilp32 and use for signal return Yury Norov
2017-01-09 11:29 ` [PATCH 20/20] arm64:ilp32: add ARM64_ILP32 to Kconfig Yury Norov
2017-01-30 5:42 ` [PATCH v7 00/20] ILP32 for ARM64 Yury Norov
2017-02-12 13:07 ` Andrew Pinski
2017-02-16 13:23 ` Maxim Kuvyrkov
-- strict thread matches above, loose matches on Subject: below --
2017-03-01 19:19 [PATCH v7 resend " Yury Norov
2017-03-01 19:19 ` [PATCH 17/20] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext Yury Norov
2017-06-04 11:59 No subject Yury Norov
2017-06-04 12:00 ` [PATCH 17/20] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext Yury Norov
2017-06-19 15:49 [PATCH v8 00/20] ILP32 for ARM64 Yury Norov
2017-06-19 15:50 ` [PATCH 17/20] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext Yury Norov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1483961397-8599-18-git-send-email-ynorov@caviumnetworks.com \
--to=ynorov@caviumnetworks.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox