Commit e9353665 authored by Yury Norov's avatar Yury Norov Committed by Chen Jun
Browse files

arm64: ilp32: introduce ilp32-specific sigframe and ucontext

maillist inclusion
category: feature
bugzilla: 46790
CVE: NA

Reference: https://github.com/norov/linux/commits/ilp32-5.2



--------------------------------

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>
Signed-off-by: default avatarYury Norov <ynorov@marvell.com>
Signed-off-by: default avatarXiongfeng Wang <wangxiongfeng2@huawei.com>
Acked-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: default avatarChen Jun <chenjun102@huawei.com>
parent 47648303
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-$(CONFIG_AARCH32_EL0) += binfmt_elf32.o sys32.o signal32.o \
					   sys_compat.o
obj-$(CONFIG_AARCH32_EL0)			+= sigreturn32.o
obj-$(CONFIG_KUSER_HELPERS)		+= kuser32.o
obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o 		\
					   signal_ilp32.o
obj-$(CONFIG_COMPAT)		+= sys32_common.o signal32_common.o
obj-$(CONFIG_FUNCTION_TRACER)		+= ftrace.o entry-ftrace.o
obj-$(CONFIG_MODULES)			+= module.o
+3 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <asm/signal32.h>
#include <asm/traps.h>
#include <asm/vdso.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))
@@ -591,6 +592,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
@@ -55,6 +55,12 @@
#define __arm64_compat_sys_msgctl		__arm64_compat_sys_old_msgctl
#define __arm64_compat_sys_shmctl		__arm64_compat_sys_old_shmctl

/*
 * 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.
 */