Commit 1a490a90 authored by Yury Norov's avatar Yury Norov Committed by Yang Yingliang
Browse files

arm64: ilp32: introduce ilp32-specific sigframe and ucontext



hulk inclusion
category: feature
bugzilla: NA
CVE: NA
---------------------------

ILP32 uses AARCH32 compat structures and syscall handlers for signals. But
ILP32 rt_sigframe and ucontext structures differ from both LP64 and AARCH32.
>From software point of view ILP32 is typical 32-bit compat ABI, and from
hardware point of view, it's just like LP64.

struct rt_sigframe defined in this patch in
arch/arm64/kernel/signal_ilp32.c redefines one in
arch/arm64/kernel/signal.c. And functions located in
arch/arm64/include/signal_common.h pick up new structure to generate the
code suitable for ILP32.

Signed-off-by: default avatarYury Norov <ynorov@caviumnetworks.com>

 Conflicts:
	arch/arm64/kernel/signal.c
[wangxiongfeng: fix small conflict because of we include 'asm/ras.h' in
arch/arm64/kernel/signal.c ]
Signed-off-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: default avatarHanjun Guo &lt;guohanjun@huawei.com <mailto:guohanjun@huawei.com&gt;>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parent b1bcebbc
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0+ */

#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 */
+2 −1
Original line number Diff line number Diff line
@@ -29,7 +29,8 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE

arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
					   sys_compat.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
arm64-obj-$(CONFIG_COMPAT)		+= sys32_common.o signal32_common.o
arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
+3 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@
#include <asm/traps.h>
#include <asm/vdso.h>
#include <asm/ras.h>
#include <asm/signal_ilp32.h>

#define get_sigset(s, m) __copy_from_user(s, m, sizeof(*s))
#define put_sigset(s, m) __copy_to_user(m, s, sizeof(*s))
@@ -587,6 +588,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
			ret = a32_setup_rt_frame(usig, ksig, oldset, regs);
		else
			ret = a32_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);
	}
+67 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0+

/*
 * Copyright (C) 1995-2009 Russell King
 * Copyright (C) 2012 ARM Ltd.
 * Copyright (C) 2018 Cavium Networks.
 * Yury Norov <ynorov@caviumnetworks.com>
 */

#include <linux/compat.h>
#include <linux/signal.h>
#include <linux/syscalls.h>

#include <asm/fpsimd.h>
#include <asm/unistd.h>
#include <asm/ucontext.h>
#include <asm/vdso.h>

#include <asm/signal_ilp32.h>
#include <asm/signal32_common.h>

#define get_sigset(s, m) get_sigset_t(s, m)
#define put_sigset(s, m) put_sigset_t(m, s)

#define restore_altstack(stack) compat_restore_altstack(stack)
#define __save_altstack(stack, sp) __compat_save_altstack(stack, sp)
#define copy_siginfo_to_user(frame_info, ksig_info) \
		copy_siginfo_to_user32(frame_info, ksig_info)

#define setup_return(regs, ka, user_layout, usig)			\
{									\
	__setup_return(regs, ka, user_layout, usig);			\
	regs->regs[30] =						\
		(unsigned long)VDSO_SYMBOL(current->mm->context.vdso,	\
						    sigtramp_ilp32);	\
}

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 rt_sigframe {
	struct compat_siginfo info;
	struct ilp32_ucontext uc;
};

#include <asm/signal_common.h>

COMPAT_SYSCALL_DEFINE0(ilp32_rt_sigreturn)
{
	struct pt_regs *regs = current_pt_regs();

	return __sys_rt_sigreturn(regs);
}

int ilp32_setup_rt_frame(int usig, struct ksignal *ksig,
			  sigset_t *set, struct pt_regs *regs)
{
	return __setup_rt_frame(usig, ksig, set, regs);
}
+6 −0
Original line number Diff line number Diff line
@@ -48,6 +48,12 @@
#define __arm64_compat_sys_fstatfs64		__arm64_compat_sys_aarch32_fstatfs64
#define __arm64_compat_sys_statfs64		__arm64_compat_sys_aarch32_statfs64

/*
 * Using custom wrapper for rt_sigreturn() to handle custom
 * struct rt_sigframe.
 */
#define __arm64_compat_sys_rt_sigreturn		__arm64_compat_sys_ilp32_rt_sigreturn

/*
 * Wrappers to pass the pt_regs argument.
 */