Skip to content

Commit e92f469

Browse files
VincentZWCpalmer-dabbelt
authored andcommitted
riscv: signal: Report signal frame size to userspace via auxv
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^16. 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 94b07c1 ("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. Note that auxv always reports size of the sigframe as if V exists for all starting processes, whenever the kernel has CONFIG_RISCV_ISA_V. The reason is that users usually reference this value to allocate an alternative signal stack, and the user may use V anytime. So the user must reserve a space for V-context in sigframe in case that the signal handler invokes after the kernel allocating V. Signed-off-by: Greentime Hu <[email protected]> Signed-off-by: Vincent Chen <[email protected]> Signed-off-by: Andy Chiu <[email protected]> Acked-by: Conor Dooley <[email protected]> Reviewed-by: Björn Töpel <[email protected]> Reviewed-by: Guo Ren <[email protected]> Reviewed-by: Heiko Stuebner <[email protected]> Tested-by: Heiko Stuebner <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 8ee0b41 commit e92f469

File tree

4 files changed

+27
-5
lines changed

4 files changed

+27
-5
lines changed

arch/riscv/include/asm/elf.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ do { \
105105
get_cache_size(3, CACHE_TYPE_UNIFIED)); \
106106
NEW_AUX_ENT(AT_L3_CACHEGEOMETRY, \
107107
get_cache_geometry(3, CACHE_TYPE_UNIFIED)); \
108+
/* \
109+
* Should always be nonzero unless there's a kernel bug. \
110+
* If we haven't determined a sensible value to give to \
111+
* userspace, omit the entry: \
112+
*/ \
113+
if (likely(signal_minsigstksz)) \
114+
NEW_AUX_ENT(AT_MINSIGSTKSZ, signal_minsigstksz); \
115+
else \
116+
NEW_AUX_ENT(AT_IGNORE, 0); \
108117
} while (0)
109118
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
110119
struct linux_binprm;

arch/riscv/include/asm/processor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define _ASM_RISCV_PROCESSOR_H
88

99
#include <linux/const.h>
10+
#include <linux/cache.h>
1011

1112
#include <vdso/processor.h>
1213

@@ -81,6 +82,7 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid);
8182
extern void riscv_fill_hwcap(void);
8283
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
8384

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

8688
#endif /* _ASM_RISCV_PROCESSOR_H */

arch/riscv/include/uapi/asm/auxvec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@
3535

3636
/* entries in ARCH_DLINFO */
3737
#define AT_VECTOR_SIZE_ARCH 9
38+
#define AT_MINSIGSTKSZ 51
3839

3940
#endif /* _UAPI_ASM_RISCV_AUXVEC_H */

arch/riscv/kernel/signal.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <asm/csr.h>
2424
#include <asm/cacheflush.h>
2525

26+
unsigned long signal_minsigstksz __ro_after_init;
27+
2628
extern u32 __user_rt_sigreturn[2];
2729
static size_t riscv_v_sc_size __ro_after_init;
2830

@@ -197,16 +199,18 @@ static long restore_sigcontext(struct pt_regs *regs,
197199
return err;
198200
}
199201

200-
static size_t get_rt_frame_size(void)
202+
static size_t get_rt_frame_size(bool cal_all)
201203
{
202204
struct rt_sigframe __user *frame;
203205
size_t frame_size;
204206
size_t total_context_size = 0;
205207

206208
frame_size = sizeof(*frame);
207209

208-
if (has_vector() && riscv_v_vstate_query(task_pt_regs(current)))
209-
total_context_size += riscv_v_sc_size;
210+
if (has_vector()) {
211+
if (cal_all || riscv_v_vstate_query(task_pt_regs(current)))
212+
total_context_size += riscv_v_sc_size;
213+
}
210214
/*
211215
* Preserved a __riscv_ctx_hdr for END signal context header if an
212216
* extension uses __riscv_extra_ext_header
@@ -226,7 +230,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
226230
struct rt_sigframe __user *frame;
227231
struct task_struct *task;
228232
sigset_t set;
229-
size_t frame_size = get_rt_frame_size();
233+
size_t frame_size = get_rt_frame_size(false);
230234

231235
/* Always make any pending restarted system calls return -EINTR */
232236
current->restart_block.fn = do_no_restart_syscall;
@@ -323,7 +327,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
323327
struct rt_sigframe __user *frame;
324328
long err = 0;
325329
unsigned long __maybe_unused addr;
326-
size_t frame_size = get_rt_frame_size();
330+
size_t frame_size = get_rt_frame_size(false);
327331

328332
frame = get_sigframe(ksig, regs, frame_size);
329333
if (!access_ok(frame, frame_size))
@@ -465,4 +469,10 @@ void __init init_rt_signal_env(void)
465469
{
466470
riscv_v_sc_size = sizeof(struct __riscv_ctx_hdr) +
467471
sizeof(struct __sc_riscv_v_state) + riscv_v_vsize;
472+
/*
473+
* Determine the stack space required for guaranteed signal delivery.
474+
* The signal_minsigstksz will be populated into the AT_MINSIGSTKSZ entry
475+
* in the auxiliary array at process startup.
476+
*/
477+
signal_minsigstksz = get_rt_frame_size(true);
468478
}

0 commit comments

Comments
 (0)