[RFC PATCH v8 12/21] riscv: signal: Report signal frame size to userspace via auxv

From: Greentime Hu
Date: Wed Sep 08 2021 - 13:46:21 EST


From: Vincent Chen <vincent.chen@xxxxxxxxxx>

The vector register belongs to the signal context. They need to be stored
and restored as entering and leaving the signal handler. According to the
V-extension specification, the maximum length of the vector registers can
be 2^(XLEN-1). Hence, if userspace refers to the MINSIGSTKSZ to create a
sigframe, it may not be enough. To resolve this problem, this patch refers
to the commit 94b07c1f8c39c
("arm64: signal: Report signal frame size to userspace via auxv") to enable
userspace to know the minimum required sigframe size through the auxiliary
vector and use it to allocate enough memory for signal context.

Signed-off-by: Greentime Hu <greentime.hu@xxxxxxxxxx>
Signed-off-by: Vincent Chen <vincent.chen@xxxxxxxxxx>
---
arch/riscv/include/asm/elf.h | 41 +++++++++++++++++-----------
arch/riscv/include/asm/processor.h | 2 ++
arch/riscv/include/uapi/asm/auxvec.h | 1 +
arch/riscv/kernel/signal.c | 8 ++++++
4 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
index f4b490cd0e5d..1102052aa593 100644
--- a/arch/riscv/include/asm/elf.h
+++ b/arch/riscv/include/asm/elf.h
@@ -58,22 +58,31 @@ extern unsigned long elf_hwcap;
#define ELF_PLATFORM (NULL)

#ifdef CONFIG_MMU
-#define ARCH_DLINFO \
-do { \
- NEW_AUX_ENT(AT_SYSINFO_EHDR, \
- (elf_addr_t)current->mm->context.vdso); \
- NEW_AUX_ENT(AT_L1I_CACHESIZE, \
- get_cache_size(1, CACHE_TYPE_INST)); \
- NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY, \
- get_cache_geometry(1, CACHE_TYPE_INST)); \
- NEW_AUX_ENT(AT_L1D_CACHESIZE, \
- get_cache_size(1, CACHE_TYPE_DATA)); \
- NEW_AUX_ENT(AT_L1D_CACHEGEOMETRY, \
- get_cache_geometry(1, CACHE_TYPE_DATA)); \
- NEW_AUX_ENT(AT_L2_CACHESIZE, \
- get_cache_size(2, CACHE_TYPE_UNIFIED)); \
- NEW_AUX_ENT(AT_L2_CACHEGEOMETRY, \
- get_cache_geometry(2, CACHE_TYPE_UNIFIED)); \
+#define ARCH_DLINFO \
+do { \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, \
+ (elf_addr_t)current->mm->context.vdso); \
+ NEW_AUX_ENT(AT_L1I_CACHESIZE, \
+ get_cache_size(1, CACHE_TYPE_INST)); \
+ NEW_AUX_ENT(AT_L1I_CACHEGEOMETRY, \
+ get_cache_geometry(1, CACHE_TYPE_INST)); \
+ NEW_AUX_ENT(AT_L1D_CACHESIZE, \
+ get_cache_size(1, CACHE_TYPE_DATA)); \
+ NEW_AUX_ENT(AT_L1D_CACHEGEOMETRY, \
+ get_cache_geometry(1, CACHE_TYPE_DATA)); \
+ NEW_AUX_ENT(AT_L2_CACHESIZE, \
+ get_cache_size(2, CACHE_TYPE_UNIFIED)); \
+ NEW_AUX_ENT(AT_L2_CACHEGEOMETRY, \
+ get_cache_geometry(2, CACHE_TYPE_UNIFIED)); \
+ /* \
+ * Should always be nonzero unless there's a kernel bug. \
+ * If we haven't determined a sensible value to give to \
+ * userspace, omit the entry: \
+ */ \
+ if (likely(signal_minsigstksz)) \
+ NEW_AUX_ENT(AT_MINSIGSTKSZ, signal_minsigstksz); \
+ else \
+ NEW_AUX_ENT(AT_IGNORE, 0); \
} while (0)
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
struct linux_binprm;
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 1b037c69d311..62c75645c606 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -7,6 +7,7 @@
#define _ASM_RISCV_PROCESSOR_H

#include <linux/const.h>
+#include <linux/cache.h>

#include <vdso/processor.h>

@@ -74,6 +75,7 @@ int riscv_of_parent_hartid(struct device_node *node);
extern void riscv_fill_hwcap(void);
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);

+extern unsigned long signal_minsigstksz __ro_after_init;
#endif /* __ASSEMBLY__ */

#endif /* _ASM_RISCV_PROCESSOR_H */
diff --git a/arch/riscv/include/uapi/asm/auxvec.h b/arch/riscv/include/uapi/asm/auxvec.h
index 32c73ba1d531..6610d24e6662 100644
--- a/arch/riscv/include/uapi/asm/auxvec.h
+++ b/arch/riscv/include/uapi/asm/auxvec.h
@@ -33,5 +33,6 @@

/* entries in ARCH_DLINFO */
#define AT_VECTOR_SIZE_ARCH 7
+#define AT_MINSIGSTKSZ 51

#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 6938cfa16b45..d30a3b588156 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -470,8 +470,16 @@ asmlinkage __visible void do_notify_resume(struct pt_regs *regs,
tracehook_notify_resume(regs);
}

+unsigned long __ro_after_init signal_minsigstksz;
+
void init_rt_signal_env(void);
void __init init_rt_signal_env(void)
{
rvv_sc_size = sizeof(struct __sc_riscv_v_state) + riscv_vsize;
+ /*
+ * Determine the stack space required for guaranteed signal delivery.
+ * The signal_minsigstksz will be populated into the AT_MINSIGSTKSZ entry
+ * in the auxiliary array at process startup.
+ */
+ signal_minsigstksz = cal_rt_frame_size();
}
--
2.31.1