From: Yury Norov ynorov@caviumnetworks.com
maillist inclusion category: feature bugzilla: 46790 CVE: NA
Reference: https://github.com/norov/linux/commits/ilp32-5.2
--------------------------------
ILP32 needs to mix 32bit struct siginfo and 64bit sigframe for its signal handlers. Move the existing compat code for copying siginfo to user space and manipulating signal masks into signal32_common.c so it can be used to deliver aarch32 and ilp32 signals.
Signed-off-by: Yury Norov ynorov@caviumnetworks.com Signed-off-by: Yury Norov ynorov@marvell.com Signed-off-by: Xiongfeng Wang wangxiongfeng2@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Chen Jun chenjun102@huawei.com
Conflicts: arch/arm64/kernel/Makefile arch/arm64/kernel/signal32.c
Signed-off-by: Chen Jiahao chenjiahao16@huawei.com --- arch/arm64/include/asm/signal32_common.h | 13 +++++++++ arch/arm64/include/asm/signal_common.h | 4 +-- arch/arm64/kernel/Makefile | 2 +- arch/arm64/kernel/signal32.c | 23 +-------------- arch/arm64/kernel/signal32_common.c | 37 ++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 arch/arm64/include/asm/signal32_common.h create mode 100644 arch/arm64/kernel/signal32_common.c
diff --git a/arch/arm64/include/asm/signal32_common.h b/arch/arm64/include/asm/signal32_common.h new file mode 100644 index 000000000000..4b365b31d37e --- /dev/null +++ b/arch/arm64/include/asm/signal32_common.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_SIGNAL32_COMMON_H +#define __ASM_SIGNAL32_COMMON_H + +#ifdef CONFIG_COMPAT + +int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set); +int get_sigset_t(sigset_t *set, const compat_sigset_t __user *uset); + +#endif /* CONFIG_COMPAT*/ + +#endif /* __ASM_SIGNAL32_COMMON_H */ diff --git a/arch/arm64/include/asm/signal_common.h b/arch/arm64/include/asm/signal_common.h index 460efa29d5a6..3a00144c6952 100644 --- a/arch/arm64/include/asm/signal_common.h +++ b/arch/arm64/include/asm/signal_common.h @@ -157,7 +157,7 @@ static int get_sigframe(struct rt_sigframe_user_layout *user, /* * Check that we can actually write to the signal frame. */ - if (!access_ok(VERIFY_WRITE, user->sigframe, sp_top - sp)) + if (!access_ok(user->sigframe, sp_top - sp)) return -EFAULT;
return 0; @@ -340,7 +340,7 @@ static long __sys_rt_sigreturn(struct pt_regs *regs)
frame = (struct rt_sigframe __user *)regs->sp;
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + if (!access_ok(frame, sizeof(*frame))) goto badframe;
if (restore_sigframe(regs, frame)) diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 3c0673bfe03e..3c30c86ea379 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -42,7 +42,7 @@ obj-$(CONFIG_AARCH32_EL0) += sigreturn32.o obj-$(CONFIG_COMPAT_ALIGNMENT_FIXUPS) += compat_alignment.o obj-$(CONFIG_KUSER_HELPERS) += kuser32.o obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o -obj-$(CONFIG_COMPAT) += sys32_common.o +obj-$(CONFIG_COMPAT) += sys32_common.o signal32_common.o obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c index 374880d75856..320cdd823a53 100644 --- a/arch/arm64/kernel/signal32.c +++ b/arch/arm64/kernel/signal32.c @@ -16,6 +16,7 @@ #include <asm/fpsimd.h> #include <asm/signal32.h> #include <asm/traps.h> +#include <asm/signal32_common.h> #include <linux/uaccess.h> #include <asm/unistd.h> #include <asm/vdso.h> @@ -46,28 +47,6 @@ struct a32_aux_sigframe { unsigned long end_magic; } __attribute__((__aligned__(8)));
-static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set) -{ - compat_sigset_t cset; - - cset.sig[0] = set->sig[0] & 0xffffffffull; - cset.sig[1] = set->sig[0] >> 32; - - return copy_to_user(uset, &cset, sizeof(*uset)); -} - -static inline int get_sigset_t(sigset_t *set, - const compat_sigset_t __user *uset) -{ - compat_sigset_t s32; - - if (copy_from_user(&s32, uset, sizeof(*uset))) - return -EFAULT; - - set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); - return 0; -} - /* * VFP save/restore code. * diff --git a/arch/arm64/kernel/signal32_common.c b/arch/arm64/kernel/signal32_common.c new file mode 100644 index 000000000000..4844d2c5fd89 --- /dev/null +++ b/arch/arm64/kernel/signal32_common.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Based on arch/arm/kernel/signal.c + * + * Copyright (C) 1995-2009 Russell King + * Copyright (C) 2012 ARM Ltd. + * Modified by Will Deacon will.deacon@arm.com + */ + +#include <linux/compat.h> +#include <linux/signal.h> +#include <linux/uaccess.h> + +#include <asm/signal32_common.h> +#include <asm/unistd.h> + +int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set) +{ + compat_sigset_t cset; + + cset.sig[0] = set->sig[0] & 0xffffffffull; + cset.sig[1] = set->sig[0] >> 32; + + return copy_to_user(uset, &cset, sizeof(*uset)); +} + +int get_sigset_t(sigset_t *set, const compat_sigset_t __user *uset) +{ + compat_sigset_t s32; + + if (copy_from_user(&s32, uset, sizeof(*uset))) + return -EFAULT; + + set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); + return 0; +}