1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * OpenRISC signal.c |
4 | * |
5 | * Linux architectural port borrowing liberally from similar works of |
6 | * others. All original copyrights apply as per the original source |
7 | * declaration. |
8 | * |
9 | * Modifications for the OpenRISC architecture: |
10 | * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> |
11 | * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> |
12 | */ |
13 | |
14 | #include <linux/sched.h> |
15 | #include <linux/mm.h> |
16 | #include <linux/smp.h> |
17 | #include <linux/kernel.h> |
18 | #include <linux/signal.h> |
19 | #include <linux/errno.h> |
20 | #include <linux/wait.h> |
21 | #include <linux/ptrace.h> |
22 | #include <linux/unistd.h> |
23 | #include <linux/stddef.h> |
24 | #include <linux/resume_user_mode.h> |
25 | |
26 | #include <asm/processor.h> |
27 | #include <asm/syscall.h> |
28 | #include <asm/ucontext.h> |
29 | #include <linux/uaccess.h> |
30 | |
31 | struct rt_sigframe { |
32 | struct siginfo info; |
33 | struct ucontext uc; |
34 | unsigned char retcode[16]; /* trampoline code */ |
35 | }; |
36 | |
37 | asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs); |
38 | |
39 | asmlinkage int do_work_pending(struct pt_regs *regs, unsigned int thread_flags, |
40 | int syscall); |
41 | |
42 | static int restore_sigcontext(struct pt_regs *regs, |
43 | struct sigcontext __user *sc) |
44 | { |
45 | int err = 0; |
46 | |
47 | /* Always make any pending restarted system calls return -EINTR */ |
48 | current->restart_block.fn = do_no_restart_syscall; |
49 | |
50 | /* |
51 | * Restore the regs from &sc->regs. |
52 | * (sc is already checked since the sigframe was |
53 | * checked in sys_sigreturn previously) |
54 | */ |
55 | err |= __copy_from_user(to: regs, from: sc->regs.gpr, n: 32 * sizeof(unsigned long)); |
56 | err |= __copy_from_user(to: ®s->pc, from: &sc->regs.pc, n: sizeof(unsigned long)); |
57 | err |= __copy_from_user(to: ®s->sr, from: &sc->regs.sr, n: sizeof(unsigned long)); |
58 | err |= __copy_from_user(to: ®s->fpcsr, from: &sc->fpcsr, n: sizeof(unsigned long)); |
59 | |
60 | /* make sure the SM-bit is cleared so user-mode cannot fool us */ |
61 | regs->sr &= ~SPR_SR_SM; |
62 | |
63 | regs->orig_gpr11 = -1; /* Avoid syscall restart checks */ |
64 | |
65 | /* TODO: the other ports use regs->orig_XX to disable syscall checks |
66 | * after this completes, but we don't use that mechanism. maybe we can |
67 | * use it now ? |
68 | */ |
69 | |
70 | return err; |
71 | } |
72 | |
73 | asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs) |
74 | { |
75 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->sp; |
76 | sigset_t set; |
77 | |
78 | /* |
79 | * Since we stacked the signal on a dword boundary, |
80 | * then frame should be dword aligned here. If it's |
81 | * not, then the user is trying to mess with us. |
82 | */ |
83 | if (((unsigned long)frame) & 3) |
84 | goto badframe; |
85 | |
86 | if (!access_ok(frame, sizeof(*frame))) |
87 | goto badframe; |
88 | if (__copy_from_user(to: &set, from: &frame->uc.uc_sigmask, n: sizeof(set))) |
89 | goto badframe; |
90 | |
91 | set_current_blocked(&set); |
92 | |
93 | if (restore_sigcontext(regs, sc: &frame->uc.uc_mcontext)) |
94 | goto badframe; |
95 | |
96 | if (restore_altstack(&frame->uc.uc_stack)) |
97 | goto badframe; |
98 | |
99 | return regs->gpr[11]; |
100 | |
101 | badframe: |
102 | force_sig(SIGSEGV); |
103 | return 0; |
104 | } |
105 | |
106 | /* |
107 | * Set up a signal frame. |
108 | */ |
109 | |
110 | static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
111 | { |
112 | int err = 0; |
113 | |
114 | /* copy the regs */ |
115 | /* There should be no need to save callee-saved registers here... |
116 | * ...but we save them anyway. Revisit this |
117 | */ |
118 | err |= __copy_to_user(to: sc->regs.gpr, from: regs, n: 32 * sizeof(unsigned long)); |
119 | err |= __copy_to_user(to: &sc->regs.pc, from: ®s->pc, n: sizeof(unsigned long)); |
120 | err |= __copy_to_user(to: &sc->regs.sr, from: ®s->sr, n: sizeof(unsigned long)); |
121 | err |= __copy_to_user(to: &sc->fpcsr, from: ®s->fpcsr, n: sizeof(unsigned long)); |
122 | |
123 | return err; |
124 | } |
125 | |
126 | static inline unsigned long align_sigframe(unsigned long sp) |
127 | { |
128 | return sp & ~3UL; |
129 | } |
130 | |
131 | /* |
132 | * Work out where the signal frame should go. It's either on the user stack |
133 | * or the alternate stack. |
134 | */ |
135 | |
136 | static inline void __user *get_sigframe(struct ksignal *ksig, |
137 | struct pt_regs *regs, size_t frame_size) |
138 | { |
139 | unsigned long sp = regs->sp; |
140 | |
141 | /* redzone */ |
142 | sp -= STACK_FRAME_OVERHEAD; |
143 | sp = sigsp(sp, ksig); |
144 | sp = align_sigframe(sp: sp - frame_size); |
145 | |
146 | return (void __user *)sp; |
147 | } |
148 | |
149 | /* grab and setup a signal frame. |
150 | * |
151 | * basically we stack a lot of state info, and arrange for the |
152 | * user-mode program to return to the kernel using either a |
153 | * trampoline which performs the syscall sigreturn, or a provided |
154 | * user-mode trampoline. |
155 | */ |
156 | static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, |
157 | struct pt_regs *regs) |
158 | { |
159 | struct rt_sigframe __user *frame; |
160 | unsigned long return_ip; |
161 | int err = 0; |
162 | |
163 | frame = get_sigframe(ksig, regs, frame_size: sizeof(*frame)); |
164 | |
165 | if (!access_ok(frame, sizeof(*frame))) |
166 | return -EFAULT; |
167 | |
168 | /* Create siginfo. */ |
169 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
170 | err |= copy_siginfo_to_user(to: &frame->info, from: &ksig->info); |
171 | |
172 | /* Create the ucontext. */ |
173 | err |= __put_user(0, &frame->uc.uc_flags); |
174 | err |= __put_user(NULL, &frame->uc.uc_link); |
175 | err |= __save_altstack(&frame->uc.uc_stack, regs->sp); |
176 | err |= setup_sigcontext(regs, sc: &frame->uc.uc_mcontext); |
177 | |
178 | err |= __copy_to_user(to: &frame->uc.uc_sigmask, from: set, n: sizeof(*set)); |
179 | |
180 | if (err) |
181 | return -EFAULT; |
182 | |
183 | /* trampoline - the desired return ip is the retcode itself */ |
184 | return_ip = (unsigned long)&frame->retcode; |
185 | /* This is: |
186 | l.ori r11,r0,__NR_sigreturn |
187 | l.sys 1 |
188 | */ |
189 | err |= __put_user(0xa960, (short __user *)(frame->retcode + 0)); |
190 | err |= __put_user(__NR_rt_sigreturn, (short __user *)(frame->retcode + 2)); |
191 | err |= __put_user(0x20000001, (unsigned long __user *)(frame->retcode + 4)); |
192 | err |= __put_user(0x15000000, (unsigned long __user *)(frame->retcode + 8)); |
193 | |
194 | if (err) |
195 | return -EFAULT; |
196 | |
197 | /* Set up registers for signal handler */ |
198 | regs->pc = (unsigned long)ksig->ka.sa.sa_handler; /* what we enter NOW */ |
199 | regs->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */ |
200 | regs->gpr[3] = (unsigned long)ksig->sig; /* arg 1: signo */ |
201 | regs->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */ |
202 | regs->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */ |
203 | |
204 | /* actually move the usp to reflect the stacked frame */ |
205 | regs->sp = (unsigned long)frame; |
206 | |
207 | return 0; |
208 | } |
209 | |
210 | static inline void |
211 | handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
212 | { |
213 | int ret; |
214 | |
215 | ret = setup_rt_frame(ksig, set: sigmask_to_save(), regs); |
216 | |
217 | signal_setup_done(failed: ret, ksig, test_thread_flag(TIF_SINGLESTEP)); |
218 | } |
219 | |
220 | /* |
221 | * Note that 'init' is a special process: it doesn't get signals it doesn't |
222 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
223 | * mistake. |
224 | * |
225 | * Also note that the regs structure given here as an argument, is the latest |
226 | * pushed pt_regs. It may or may not be the same as the first pushed registers |
227 | * when the initial usermode->kernelmode transition took place. Therefore |
228 | * we can use user_mode(regs) to see if we came directly from kernel or user |
229 | * mode below. |
230 | */ |
231 | |
232 | static int do_signal(struct pt_regs *regs, int syscall) |
233 | { |
234 | struct ksignal ksig; |
235 | unsigned long continue_addr = 0; |
236 | unsigned long restart_addr = 0; |
237 | unsigned long retval = 0; |
238 | int restart = 0; |
239 | |
240 | if (syscall) { |
241 | continue_addr = regs->pc; |
242 | restart_addr = continue_addr - 4; |
243 | retval = regs->gpr[11]; |
244 | |
245 | /* |
246 | * Setup syscall restart here so that a debugger will |
247 | * see the already changed PC. |
248 | */ |
249 | switch (retval) { |
250 | case -ERESTART_RESTARTBLOCK: |
251 | restart = -2; |
252 | fallthrough; |
253 | case -ERESTARTNOHAND: |
254 | case -ERESTARTSYS: |
255 | case -ERESTARTNOINTR: |
256 | restart++; |
257 | regs->gpr[11] = regs->orig_gpr11; |
258 | regs->pc = restart_addr; |
259 | break; |
260 | } |
261 | } |
262 | |
263 | /* |
264 | * Get the signal to deliver. During the call to get_signal the |
265 | * debugger may change all our registers so we may need to revert |
266 | * the decision to restart the syscall; specifically, if the PC is |
267 | * changed, don't restart the syscall. |
268 | */ |
269 | if (get_signal(ksig: &ksig)) { |
270 | if (unlikely(restart) && regs->pc == restart_addr) { |
271 | if (retval == -ERESTARTNOHAND || |
272 | retval == -ERESTART_RESTARTBLOCK |
273 | || (retval == -ERESTARTSYS |
274 | && !(ksig.ka.sa.sa_flags & SA_RESTART))) { |
275 | /* No automatic restart */ |
276 | regs->gpr[11] = -EINTR; |
277 | regs->pc = continue_addr; |
278 | } |
279 | } |
280 | handle_signal(ksig: &ksig, regs); |
281 | } else { |
282 | /* no handler */ |
283 | restore_saved_sigmask(); |
284 | /* |
285 | * Restore pt_regs PC as syscall restart will be handled by |
286 | * kernel without return to userspace |
287 | */ |
288 | if (unlikely(restart) && regs->pc == restart_addr) { |
289 | regs->pc = continue_addr; |
290 | return restart; |
291 | } |
292 | } |
293 | |
294 | return 0; |
295 | } |
296 | |
297 | asmlinkage int |
298 | do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) |
299 | { |
300 | do { |
301 | if (likely(thread_flags & _TIF_NEED_RESCHED)) { |
302 | schedule(); |
303 | } else { |
304 | if (unlikely(!user_mode(regs))) |
305 | return 0; |
306 | local_irq_enable(); |
307 | if (thread_flags & (_TIF_SIGPENDING|_TIF_NOTIFY_SIGNAL)) { |
308 | int restart = do_signal(regs, syscall); |
309 | if (unlikely(restart)) { |
310 | /* |
311 | * Restart without handlers. |
312 | * Deal with it without leaving |
313 | * the kernel space. |
314 | */ |
315 | return restart; |
316 | } |
317 | syscall = 0; |
318 | } else { |
319 | resume_user_mode_work(regs); |
320 | } |
321 | } |
322 | local_irq_disable(); |
323 | thread_flags = read_thread_flags(); |
324 | } while (thread_flags & _TIF_WORK_MASK); |
325 | return 0; |
326 | } |
327 | |