@@ -105,6 +105,15 @@ do { \
get_cache_size(3, CACHE_TYPE_UNIFIED)); \
NEW_AUX_ENT(AT_L3_CACHEGEOMETRY, \
get_cache_geometry(3, 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;
@@ -7,6 +7,7 @@
#define _ASM_RISCV_PROCESSOR_H
#include <linux/const.h>
+#include <linux/cache.h>
#include <vdso/processor.h>
@@ -81,6 +82,7 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid);
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 */
@@ -35,5 +35,6 @@
/* entries in ARCH_DLINFO */
#define AT_VECTOR_SIZE_ARCH 9
+#define AT_MINSIGSTKSZ 51
#endif /* _UAPI_ASM_RISCV_AUXVEC_H */
@@ -22,6 +22,8 @@
#include <asm/vector.h>
#include <asm/csr.h>
+unsigned long signal_minsigstksz __ro_after_init;
+
extern u32 __user_rt_sigreturn[2];
static size_t riscv_v_sc_size __ro_after_init;
@@ -196,7 +198,7 @@ static long restore_sigcontext(struct pt_regs *regs,
return err;
}
-static size_t get_rt_frame_size(void)
+static size_t get_rt_frame_size(bool cal_all)
{
struct rt_sigframe __user *frame;
size_t frame_size;
@@ -204,8 +206,10 @@ static size_t get_rt_frame_size(void)
frame_size = sizeof(*frame);
- if (has_vector() && riscv_v_vstate_query(task_pt_regs(current)))
- total_context_size += riscv_v_sc_size;
+ if (has_vector()) {
+ if (cal_all || riscv_v_vstate_query(task_pt_regs(current)))
+ total_context_size += riscv_v_sc_size;
+ }
/*
* Preserved a __riscv_ctx_hdr for END signal context header if an
* extension uses __riscv_extra_ext_header
@@ -225,7 +229,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
struct rt_sigframe __user *frame;
struct task_struct *task;
sigset_t set;
- size_t frame_size = get_rt_frame_size();
+ size_t frame_size = get_rt_frame_size(false);
/* Always make any pending restarted system calls return -EINTR */
current->restart_block.fn = do_no_restart_syscall;
@@ -321,7 +325,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
{
struct rt_sigframe __user *frame;
long err = 0;
- size_t frame_size = get_rt_frame_size();
+ size_t frame_size = get_rt_frame_size(false);
frame = get_sigframe(ksig, regs, frame_size);
if (!access_ok(frame, frame_size))
@@ -458,4 +462,10 @@ void __init init_rt_signal_env(void)
{
riscv_v_sc_size = sizeof(struct __riscv_ctx_hdr) +
sizeof(struct __sc_riscv_v_state) + riscv_v_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 = get_rt_frame_size(true);
}