1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. |
4 | * Chen Liqin <liqin.chen@sunplusct.com> |
5 | * Lennox Wu <lennox.wu@sunplusct.com> |
6 | * Copyright (C) 2012 Regents of the University of California |
7 | */ |
8 | |
9 | #include <linux/compat.h> |
10 | #include <linux/signal.h> |
11 | #include <linux/uaccess.h> |
12 | #include <linux/syscalls.h> |
13 | #include <linux/resume_user_mode.h> |
14 | #include <linux/linkage.h> |
15 | #include <linux/entry-common.h> |
16 | |
17 | #include <asm/ucontext.h> |
18 | #include <asm/vdso.h> |
19 | #include <asm/signal.h> |
20 | #include <asm/signal32.h> |
21 | #include <asm/switch_to.h> |
22 | #include <asm/vector.h> |
23 | #include <asm/csr.h> |
24 | #include <asm/cacheflush.h> |
25 | |
26 | unsigned long signal_minsigstksz __ro_after_init; |
27 | |
28 | extern u32 __user_rt_sigreturn[2]; |
29 | static size_t riscv_v_sc_size __ro_after_init; |
30 | |
31 | #define DEBUG_SIG 0 |
32 | |
33 | struct rt_sigframe { |
34 | struct siginfo info; |
35 | struct ucontext uc; |
36 | #ifndef CONFIG_MMU |
37 | u32 sigreturn_code[2]; |
38 | #endif |
39 | }; |
40 | |
41 | #ifdef CONFIG_FPU |
42 | static long restore_fp_state(struct pt_regs *regs, |
43 | union __riscv_fp_state __user *sc_fpregs) |
44 | { |
45 | long err; |
46 | struct __riscv_d_ext_state __user *state = &sc_fpregs->d; |
47 | |
48 | err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state)); |
49 | if (unlikely(err)) |
50 | return err; |
51 | |
52 | fstate_restore(current, regs); |
53 | return 0; |
54 | } |
55 | |
56 | static long save_fp_state(struct pt_regs *regs, |
57 | union __riscv_fp_state __user *sc_fpregs) |
58 | { |
59 | long err; |
60 | struct __riscv_d_ext_state __user *state = &sc_fpregs->d; |
61 | |
62 | fstate_save(current, regs); |
63 | err = __copy_to_user(state, ¤t->thread.fstate, sizeof(*state)); |
64 | return err; |
65 | } |
66 | #else |
67 | #define save_fp_state(task, regs) (0) |
68 | #define restore_fp_state(task, regs) (0) |
69 | #endif |
70 | |
71 | #ifdef CONFIG_RISCV_ISA_V |
72 | |
73 | static long save_v_state(struct pt_regs *regs, void __user **sc_vec) |
74 | { |
75 | struct __riscv_ctx_hdr __user *hdr; |
76 | struct __sc_riscv_v_state __user *state; |
77 | void __user *datap; |
78 | long err; |
79 | |
80 | hdr = *sc_vec; |
81 | /* Place state to the user's signal context space after the hdr */ |
82 | state = (struct __sc_riscv_v_state __user *)(hdr + 1); |
83 | /* Point datap right after the end of __sc_riscv_v_state */ |
84 | datap = state + 1; |
85 | |
86 | /* datap is designed to be 16 byte aligned for better performance */ |
87 | WARN_ON(!IS_ALIGNED((unsigned long)datap, 16)); |
88 | |
89 | get_cpu_vector_context(); |
90 | riscv_v_vstate_save(¤t->thread.vstate, regs); |
91 | put_cpu_vector_context(); |
92 | |
93 | /* Copy everything of vstate but datap. */ |
94 | err = __copy_to_user(&state->v_state, ¤t->thread.vstate, |
95 | offsetof(struct __riscv_v_ext_state, datap)); |
96 | /* Copy the pointer datap itself. */ |
97 | err |= __put_user((__force void *)datap, &state->v_state.datap); |
98 | /* Copy the whole vector content to user space datap. */ |
99 | err |= __copy_to_user(datap, current->thread.vstate.datap, riscv_v_vsize); |
100 | /* Copy magic to the user space after saving all vector conetext */ |
101 | err |= __put_user(RISCV_V_MAGIC, &hdr->magic); |
102 | err |= __put_user(riscv_v_sc_size, &hdr->size); |
103 | if (unlikely(err)) |
104 | return err; |
105 | |
106 | /* Only progress the sv_vec if everything has done successfully */ |
107 | *sc_vec += riscv_v_sc_size; |
108 | return 0; |
109 | } |
110 | |
111 | /* |
112 | * Restore Vector extension context from the user's signal frame. This function |
113 | * assumes a valid extension header. So magic and size checking must be done by |
114 | * the caller. |
115 | */ |
116 | static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec) |
117 | { |
118 | long err; |
119 | struct __sc_riscv_v_state __user *state = sc_vec; |
120 | void __user *datap; |
121 | |
122 | /* |
123 | * Mark the vstate as clean prior performing the actual copy, |
124 | * to avoid getting the vstate incorrectly clobbered by the |
125 | * discarded vector state. |
126 | */ |
127 | riscv_v_vstate_set_restore(current, regs); |
128 | |
129 | /* Copy everything of __sc_riscv_v_state except datap. */ |
130 | err = __copy_from_user(¤t->thread.vstate, &state->v_state, |
131 | offsetof(struct __riscv_v_ext_state, datap)); |
132 | if (unlikely(err)) |
133 | return err; |
134 | |
135 | /* Copy the pointer datap itself. */ |
136 | err = __get_user(datap, &state->v_state.datap); |
137 | if (unlikely(err)) |
138 | return err; |
139 | /* |
140 | * Copy the whole vector content from user space datap. Use |
141 | * copy_from_user to prevent information leak. |
142 | */ |
143 | return copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize); |
144 | } |
145 | #else |
146 | #define save_v_state(task, regs) (0) |
147 | #define __restore_v_state(task, regs) (0) |
148 | #endif |
149 | |
150 | static long restore_sigcontext(struct pt_regs *regs, |
151 | struct sigcontext __user *sc) |
152 | { |
153 | void __user *sc_ext_ptr = &sc->sc_extdesc.hdr; |
154 | __u32 rsvd; |
155 | long err; |
156 | /* sc_regs is structured the same as the start of pt_regs */ |
157 | err = __copy_from_user(to: regs, from: &sc->sc_regs, n: sizeof(sc->sc_regs)); |
158 | if (unlikely(err)) |
159 | return err; |
160 | |
161 | /* Restore the floating-point state. */ |
162 | if (has_fpu()) { |
163 | err = restore_fp_state(regs, &sc->sc_fpregs); |
164 | if (unlikely(err)) |
165 | return err; |
166 | } |
167 | |
168 | /* Check the reserved word before extensions parsing */ |
169 | err = __get_user(rsvd, &sc->sc_extdesc.reserved); |
170 | if (unlikely(err)) |
171 | return err; |
172 | if (unlikely(rsvd)) |
173 | return -EINVAL; |
174 | |
175 | while (!err) { |
176 | __u32 magic, size; |
177 | struct __riscv_ctx_hdr __user *head = sc_ext_ptr; |
178 | |
179 | err |= __get_user(magic, &head->magic); |
180 | err |= __get_user(size, &head->size); |
181 | if (unlikely(err)) |
182 | return err; |
183 | |
184 | sc_ext_ptr += sizeof(*head); |
185 | switch (magic) { |
186 | case END_MAGIC: |
187 | if (size != END_HDR_SIZE) |
188 | return -EINVAL; |
189 | |
190 | return 0; |
191 | case RISCV_V_MAGIC: |
192 | if (!(has_vector() || has_xtheadvector()) || !riscv_v_vstate_query(regs) || |
193 | size != riscv_v_sc_size) |
194 | return -EINVAL; |
195 | |
196 | err = __restore_v_state(regs, sc_ext_ptr); |
197 | break; |
198 | default: |
199 | return -EINVAL; |
200 | } |
201 | sc_ext_ptr = (void __user *)head + size; |
202 | } |
203 | return err; |
204 | } |
205 | |
206 | static size_t get_rt_frame_size(bool cal_all) |
207 | { |
208 | struct rt_sigframe __user *frame; |
209 | size_t frame_size; |
210 | size_t total_context_size = 0; |
211 | |
212 | frame_size = sizeof(*frame); |
213 | |
214 | if (has_vector() || has_xtheadvector()) { |
215 | if (cal_all || riscv_v_vstate_query(task_pt_regs(current))) |
216 | total_context_size += riscv_v_sc_size; |
217 | } |
218 | |
219 | frame_size += total_context_size; |
220 | |
221 | frame_size = round_up(frame_size, 16); |
222 | return frame_size; |
223 | } |
224 | |
225 | SYSCALL_DEFINE0(rt_sigreturn) |
226 | { |
227 | struct pt_regs *regs = current_pt_regs(); |
228 | struct rt_sigframe __user *frame; |
229 | struct task_struct *task; |
230 | sigset_t set; |
231 | size_t frame_size = get_rt_frame_size(cal_all: false); |
232 | |
233 | /* Always make any pending restarted system calls return -EINTR */ |
234 | current->restart_block.fn = do_no_restart_syscall; |
235 | |
236 | frame = (struct rt_sigframe __user *)regs->sp; |
237 | |
238 | if (!access_ok(frame, frame_size)) |
239 | goto badframe; |
240 | |
241 | if (__copy_from_user(to: &set, from: &frame->uc.uc_sigmask, n: sizeof(set))) |
242 | goto badframe; |
243 | |
244 | set_current_blocked(&set); |
245 | |
246 | if (restore_sigcontext(regs, sc: &frame->uc.uc_mcontext)) |
247 | goto badframe; |
248 | |
249 | if (restore_altstack(&frame->uc.uc_stack)) |
250 | goto badframe; |
251 | |
252 | regs->cause = -1UL; |
253 | |
254 | return regs->a0; |
255 | |
256 | badframe: |
257 | task = current; |
258 | if (show_unhandled_signals) { |
259 | pr_info_ratelimited( |
260 | "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n" , |
261 | task->comm, task_pid_nr(task), __func__, |
262 | frame, (void *)regs->epc, (void *)regs->sp); |
263 | } |
264 | force_sig(SIGSEGV); |
265 | return 0; |
266 | } |
267 | |
268 | static long setup_sigcontext(struct rt_sigframe __user *frame, |
269 | struct pt_regs *regs) |
270 | { |
271 | struct sigcontext __user *sc = &frame->uc.uc_mcontext; |
272 | struct __riscv_ctx_hdr __user *sc_ext_ptr = &sc->sc_extdesc.hdr; |
273 | long err; |
274 | |
275 | /* sc_regs is structured the same as the start of pt_regs */ |
276 | err = __copy_to_user(to: &sc->sc_regs, from: regs, n: sizeof(sc->sc_regs)); |
277 | /* Save the floating-point state. */ |
278 | if (has_fpu()) |
279 | err |= save_fp_state(regs, &sc->sc_fpregs); |
280 | /* Save the vector state. */ |
281 | if ((has_vector() || has_xtheadvector()) && riscv_v_vstate_query(regs)) |
282 | err |= save_v_state(regs, (void __user **)&sc_ext_ptr); |
283 | /* Write zero to fp-reserved space and check it on restore_sigcontext */ |
284 | err |= __put_user(0, &sc->sc_extdesc.reserved); |
285 | /* And put END __riscv_ctx_hdr at the end. */ |
286 | err |= __put_user(END_MAGIC, &sc_ext_ptr->magic); |
287 | err |= __put_user(END_HDR_SIZE, &sc_ext_ptr->size); |
288 | |
289 | return err; |
290 | } |
291 | |
292 | static inline void __user *get_sigframe(struct ksignal *ksig, |
293 | struct pt_regs *regs, size_t framesize) |
294 | { |
295 | unsigned long sp; |
296 | /* Default to using normal stack */ |
297 | sp = regs->sp; |
298 | |
299 | /* |
300 | * If we are on the alternate signal stack and would overflow it, don't. |
301 | * Return an always-bogus address instead so we will die with SIGSEGV. |
302 | */ |
303 | if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) |
304 | return (void __user __force *)(-1UL); |
305 | |
306 | /* This is the X/Open sanctioned signal stack switching. */ |
307 | sp = sigsp(sp, ksig) - framesize; |
308 | |
309 | /* Align the stack frame. */ |
310 | sp &= ~0xfUL; |
311 | |
312 | return (void __user *)sp; |
313 | } |
314 | |
315 | static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, |
316 | struct pt_regs *regs) |
317 | { |
318 | struct rt_sigframe __user *frame; |
319 | long err = 0; |
320 | unsigned long __maybe_unused addr; |
321 | size_t frame_size = get_rt_frame_size(cal_all: false); |
322 | |
323 | frame = get_sigframe(ksig, regs, framesize: frame_size); |
324 | if (!access_ok(frame, frame_size)) |
325 | return -EFAULT; |
326 | |
327 | err |= copy_siginfo_to_user(to: &frame->info, from: &ksig->info); |
328 | |
329 | /* Create the ucontext. */ |
330 | err |= __put_user(0, &frame->uc.uc_flags); |
331 | err |= __put_user(NULL, &frame->uc.uc_link); |
332 | err |= __save_altstack(&frame->uc.uc_stack, regs->sp); |
333 | err |= setup_sigcontext(frame, regs); |
334 | err |= __copy_to_user(to: &frame->uc.uc_sigmask, from: set, n: sizeof(*set)); |
335 | if (err) |
336 | return -EFAULT; |
337 | |
338 | /* Set up to return from userspace. */ |
339 | #ifdef CONFIG_MMU |
340 | regs->ra = (unsigned long)VDSO_SYMBOL( |
341 | current->mm->context.vdso, rt_sigreturn); |
342 | #else |
343 | /* |
344 | * For the nommu case we don't have a VDSO. Instead we push two |
345 | * instructions to call the rt_sigreturn syscall onto the user stack. |
346 | */ |
347 | if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn, |
348 | sizeof(frame->sigreturn_code))) |
349 | return -EFAULT; |
350 | |
351 | addr = (unsigned long)&frame->sigreturn_code; |
352 | /* Make sure the two instructions are pushed to icache. */ |
353 | flush_icache_range(addr, addr + sizeof(frame->sigreturn_code)); |
354 | |
355 | regs->ra = addr; |
356 | #endif /* CONFIG_MMU */ |
357 | |
358 | /* |
359 | * Set up registers for signal handler. |
360 | * Registers that we don't modify keep the value they had from |
361 | * user-space at the time we took the signal. |
362 | * We always pass siginfo and mcontext, regardless of SA_SIGINFO, |
363 | * since some things rely on this (e.g. glibc's debug/segfault.c). |
364 | */ |
365 | regs->epc = (unsigned long)ksig->ka.sa.sa_handler; |
366 | regs->sp = (unsigned long)frame; |
367 | regs->a0 = ksig->sig; /* a0: signal number */ |
368 | regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */ |
369 | regs->a2 = (unsigned long)(&frame->uc); /* a2: ucontext pointer */ |
370 | |
371 | #if DEBUG_SIG |
372 | pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n" , |
373 | current->comm, task_pid_nr(current), ksig->sig, |
374 | (void *)regs->epc, (void *)regs->ra, frame); |
375 | #endif |
376 | |
377 | return 0; |
378 | } |
379 | |
380 | static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
381 | { |
382 | sigset_t *oldset = sigmask_to_save(); |
383 | int ret; |
384 | |
385 | rseq_signal_deliver(ksig, regs); |
386 | |
387 | /* Set up the stack frame */ |
388 | if (is_compat_task()) |
389 | ret = compat_setup_rt_frame(ksig, oldset, regs); |
390 | else |
391 | ret = setup_rt_frame(ksig, set: oldset, regs); |
392 | |
393 | signal_setup_done(failed: ret, ksig, stepping: 0); |
394 | } |
395 | |
396 | void arch_do_signal_or_restart(struct pt_regs *regs) |
397 | { |
398 | unsigned long continue_addr = 0, restart_addr = 0; |
399 | int retval = 0; |
400 | struct ksignal ksig; |
401 | bool syscall = (regs->cause == EXC_SYSCALL); |
402 | |
403 | /* If we were from a system call, check for system call restarting */ |
404 | if (syscall) { |
405 | continue_addr = regs->epc; |
406 | restart_addr = continue_addr - 4; |
407 | retval = regs->a0; |
408 | |
409 | /* Avoid additional syscall restarting via ret_from_exception */ |
410 | regs->cause = -1UL; |
411 | |
412 | /* |
413 | * Prepare for system call restart. We do this here so that a |
414 | * debugger will see the already changed PC. |
415 | */ |
416 | switch (retval) { |
417 | case -ERESTARTNOHAND: |
418 | case -ERESTARTSYS: |
419 | case -ERESTARTNOINTR: |
420 | case -ERESTART_RESTARTBLOCK: |
421 | regs->a0 = regs->orig_a0; |
422 | regs->epc = restart_addr; |
423 | break; |
424 | } |
425 | } |
426 | |
427 | /* |
428 | * Get the signal to deliver. When running under ptrace, at this point |
429 | * the debugger may change all of our registers. |
430 | */ |
431 | if (get_signal(ksig: &ksig)) { |
432 | /* |
433 | * Depending on the signal settings, we may need to revert the |
434 | * decision to restart the system call, but skip this if a |
435 | * debugger has chosen to restart at a different PC. |
436 | */ |
437 | if (regs->epc == restart_addr && |
438 | (retval == -ERESTARTNOHAND || |
439 | retval == -ERESTART_RESTARTBLOCK || |
440 | (retval == -ERESTARTSYS && |
441 | !(ksig.ka.sa.sa_flags & SA_RESTART)))) { |
442 | regs->a0 = -EINTR; |
443 | regs->epc = continue_addr; |
444 | } |
445 | |
446 | /* Actually deliver the signal */ |
447 | handle_signal(ksig: &ksig, regs); |
448 | return; |
449 | } |
450 | |
451 | /* |
452 | * Handle restarting a different system call. As above, if a debugger |
453 | * has chosen to restart at a different PC, ignore the restart. |
454 | */ |
455 | if (syscall && regs->epc == restart_addr && retval == -ERESTART_RESTARTBLOCK) |
456 | regs->a7 = __NR_restart_syscall; |
457 | |
458 | /* |
459 | * If there is no signal to deliver, we just put the saved |
460 | * sigmask back. |
461 | */ |
462 | restore_saved_sigmask(); |
463 | } |
464 | |
465 | void init_rt_signal_env(void); |
466 | void __init init_rt_signal_env(void) |
467 | { |
468 | riscv_v_sc_size = sizeof(struct __riscv_ctx_hdr) + |
469 | sizeof(struct __sc_riscv_v_state) + riscv_v_vsize; |
470 | /* |
471 | * Determine the stack space required for guaranteed signal delivery. |
472 | * The signal_minsigstksz will be populated into the AT_MINSIGSTKSZ entry |
473 | * in the auxiliary array at process startup. |
474 | */ |
475 | signal_minsigstksz = get_rt_frame_size(cal_all: true); |
476 | } |
477 | |
478 | #ifdef CONFIG_DYNAMIC_SIGFRAME |
479 | bool sigaltstack_size_valid(size_t ss_size) |
480 | { |
481 | return ss_size > get_rt_frame_size(cal_all: false); |
482 | } |
483 | #endif /* CONFIG_DYNAMIC_SIGFRAME */ |
484 | |