blob: 879f8d86bc21c06c0d07ac32eee26c36f365f207 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
David S. Miller5526b7e2008-04-27 02:26:36 -07002/* arch/sparc64/kernel/signal32.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
7 * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
8 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
9 */
10
11#include <linux/sched.h>
12#include <linux/kernel.h>
13#include <linux/signal.h>
14#include <linux/errno.h>
15#include <linux/wait.h>
16#include <linux/ptrace.h>
17#include <linux/unistd.h>
18#include <linux/mm.h>
19#include <linux/tty.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/binfmts.h>
21#include <linux/compat.h>
22#include <linux/bitops.h>
Roland McGrath95698462008-07-27 01:08:02 -070023#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080025#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/ptrace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <asm/pgtable.h>
28#include <asm/psrcompat.h>
29#include <asm/fpumacro.h>
30#include <asm/visasm.h>
David S. Miller14cc6ab2006-10-02 14:17:57 -070031#include <asm/compat_signal.h>
David Howellsd550bbd2012-03-28 18:30:03 +010032#include <asm/switch_to.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
David S. Miller55984732011-08-20 17:14:54 -070034#include "sigutil.h"
Sam Ravnborgabaff452014-05-16 23:26:00 +020035#include "kernel.h"
David S. Miller55984732011-08-20 17:14:54 -070036
Linus Torvalds1da177e2005-04-16 15:20:36 -070037/* This magic should be in g_upper[0] for all upper parts
38 * to be valid.
39 */
40#define SIGINFO_EXTRA_V8PLUS_MAGIC 0x130e269
41typedef struct {
42 unsigned int g_upper[8];
43 unsigned int o_upper[8];
44 unsigned int asi;
45} siginfo_extra_v8plus_t;
46
David S. Miller5526b7e2008-04-27 02:26:36 -070047struct signal_frame32 {
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 struct sparc_stackf32 ss;
49 __siginfo32_t info;
David S. Miller55984732011-08-20 17:14:54 -070050 /* __siginfo_fpu_t * */ u32 fpu_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 unsigned int insns[2];
52 unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
53 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
54 /* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
55 siginfo_extra_v8plus_t v8plus;
David S. Miller55984732011-08-20 17:14:54 -070056 /* __siginfo_rwin_t * */u32 rwin_save;
57} __attribute__((aligned(8)));
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Linus Torvalds1da177e2005-04-16 15:20:36 -070059struct rt_signal_frame32 {
60 struct sparc_stackf32 ss;
61 compat_siginfo_t info;
62 struct pt_regs32 regs;
63 compat_sigset_t mask;
David S. Miller55984732011-08-20 17:14:54 -070064 /* __siginfo_fpu_t * */ u32 fpu_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 unsigned int insns[2];
Al Viro99b06fe2012-12-23 03:41:17 -050066 compat_stack_t stack;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 unsigned int extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */
68 /* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
69 siginfo_extra_v8plus_t v8plus;
David S. Miller55984732011-08-20 17:14:54 -070070 /* __siginfo_rwin_t * */u32 rwin_save;
71} __attribute__((aligned(8)));
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
Al Viroce395962013-10-13 17:23:53 -040073int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
75 int err;
76
77 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
78 return -EFAULT;
79
80 /* If you change siginfo_t structure, please be sure
81 this code is fixed accordingly.
82 It should never copy any pad contained in the structure
83 to avoid security leaks, but must copy the generic
84 3 ints plus the relevant union member.
85 This routine must convert siginfo from 64bit to 32bit as well
86 at the same time. */
87 err = __put_user(from->si_signo, &to->si_signo);
88 err |= __put_user(from->si_errno, &to->si_errno);
Eric W. Biedermancc731522017-07-16 22:36:59 -050089 err |= __put_user(from->si_code, &to->si_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 if (from->si_code < 0)
91 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
92 else {
Eric W. Biedermancc731522017-07-16 22:36:59 -050093 switch (siginfo_layout(from->si_signo, from->si_code)) {
94 case SIL_TIMER:
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 err |= __put_user(from->si_tid, &to->si_tid);
96 err |= __put_user(from->si_overrun, &to->si_overrun);
97 err |= __put_user(from->si_int, &to->si_int);
98 break;
Eric W. Biedermancc731522017-07-16 22:36:59 -050099 case SIL_CHLD:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100 err |= __put_user(from->si_utime, &to->si_utime);
101 err |= __put_user(from->si_stime, &to->si_stime);
102 err |= __put_user(from->si_status, &to->si_status);
103 default:
Eric W. Biedermancc731522017-07-16 22:36:59 -0500104 case SIL_KILL:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 err |= __put_user(from->si_pid, &to->si_pid);
106 err |= __put_user(from->si_uid, &to->si_uid);
107 break;
Eric W. Biedermancc731522017-07-16 22:36:59 -0500108 case SIL_FAULT:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 err |= __put_user(from->si_trapno, &to->si_trapno);
110 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
111 break;
Eric W. Biedermancc731522017-07-16 22:36:59 -0500112 case SIL_POLL:
Jurij Smakov9c7d3b32005-04-17 18:03:12 -0700113 err |= __put_user(from->si_band, &to->si_band);
114 err |= __put_user(from->si_fd, &to->si_fd);
115 break;
Eric W. Biedermancc731522017-07-16 22:36:59 -0500116 case SIL_RT:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 err |= __put_user(from->si_pid, &to->si_pid);
118 err |= __put_user(from->si_uid, &to->si_uid);
119 err |= __put_user(from->si_int, &to->si_int);
120 break;
121 }
122 }
123 return err;
124}
125
126/* CAUTION: This is just a very minimalist implementation for the
127 * sake of compat_sys_rt_sigqueueinfo()
128 */
129int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
130{
131 if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t)))
132 return -EFAULT;
133
134 if (copy_from_user(to, from, 3*sizeof(int)) ||
135 copy_from_user(to->_sifields._pad, from->_sifields._pad,
136 SI_PAD_SIZE))
137 return -EFAULT;
138
139 return 0;
140}
141
David S. Millerd11c2a02016-05-28 21:21:31 -0700142/* Checks if the fp is valid. We always build signal frames which are
143 * 16-byte aligned, therefore we can always enforce that the restore
144 * frame has that property as well.
145 */
146static bool invalid_frame_pointer(void __user *fp, int fplen)
147{
148 if ((((unsigned long) fp) & 15) ||
149 ((unsigned long)fp) > 0x100000000ULL - fplen)
150 return true;
151 return false;
152}
153
David S. Miller5526b7e2008-04-27 02:26:36 -0700154void do_sigreturn32(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155{
David S. Miller5526b7e2008-04-27 02:26:36 -0700156 struct signal_frame32 __user *sf;
David S. Miller55984732011-08-20 17:14:54 -0700157 compat_uptr_t fpu_save;
158 compat_uptr_t rwin_save;
David S. Millerd11c2a02016-05-28 21:21:31 -0700159 unsigned int psr, ufp;
Joe Perches9ef595d2016-03-10 15:21:43 -0800160 unsigned int pc, npc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 sigset_t set;
Sam Ravnborgc19ac322014-05-16 23:26:01 +0200162 compat_sigset_t seta;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 int err, i;
164
David S. Miller5526b7e2008-04-27 02:26:36 -0700165 /* Always make any pending restarted system calls return -EINTR */
Andy Lutomirskif56141e2015-02-12 15:01:14 -0800166 current->restart_block.fn = do_no_restart_syscall;
David S. Miller5526b7e2008-04-27 02:26:36 -0700167
168 synchronize_user_stack();
169
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
David S. Miller5526b7e2008-04-27 02:26:36 -0700171 sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173 /* 1. Make sure we are not getting garbage from the user */
David S. Millerd11c2a02016-05-28 21:21:31 -0700174 if (invalid_frame_pointer(sf, sizeof(*sf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 goto segv;
176
David S. Millerd11c2a02016-05-28 21:21:31 -0700177 if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
178 goto segv;
179
180 if (ufp & 0x7)
181 goto segv;
182
183 if (__get_user(pc, &sf->info.si_regs.pc) ||
Al Viro187cd442012-04-22 16:51:36 -0400184 __get_user(npc, &sf->info.si_regs.npc))
185 goto segv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
187 if ((pc | npc) & 3)
188 goto segv;
189
190 if (test_thread_flag(TIF_32BIT)) {
191 pc &= 0xffffffff;
192 npc &= 0xffffffff;
193 }
194 regs->tpc = pc;
195 regs->tnpc = npc;
196
197 /* 2. Restore the state */
198 err = __get_user(regs->y, &sf->info.si_regs.y);
199 err |= __get_user(psr, &sf->info.si_regs.psr);
200
201 for (i = UREG_G1; i <= UREG_I7; i++)
202 err |= __get_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
203 if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
204 err |= __get_user(i, &sf->v8plus.g_upper[0]);
205 if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
206 unsigned long asi;
207
208 for (i = UREG_G1; i <= UREG_I7; i++)
209 err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
210 err |= __get_user(asi, &sf->v8plus.asi);
211 regs->tstate &= ~TSTATE_ASI;
212 regs->tstate |= ((asi & 0xffUL) << 24UL);
213 }
214 }
215
216 /* User can only change condition codes in %tstate. */
217 regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
218 regs->tstate |= psr_to_tstate_icc(psr);
219
David S. Miller2678fef2008-05-01 03:30:22 -0700220 /* Prevent syscall restart. */
David S. Miller28e61032008-05-11 02:07:19 -0700221 pt_regs_clear_syscall(regs);
David S. Miller2678fef2008-05-01 03:30:22 -0700222
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 err |= __get_user(fpu_save, &sf->fpu_save);
David S. Miller55984732011-08-20 17:14:54 -0700224 if (!err && fpu_save)
225 err |= restore_fpu_state(regs, compat_ptr(fpu_save));
226 err |= __get_user(rwin_save, &sf->rwin_save);
227 if (!err && rwin_save) {
228 if (restore_rwin_state(compat_ptr(rwin_save)))
229 goto segv;
230 }
Sam Ravnborgc19ac322014-05-16 23:26:01 +0200231 err |= __get_user(seta.sig[0], &sf->info.si_mask);
232 err |= copy_from_user(&seta.sig[1], &sf->extramask,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
234 if (err)
235 goto segv;
Sam Ravnborgc19ac322014-05-16 23:26:01 +0200236
237 set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
Matt Flemingfaddf592011-08-11 14:57:02 +0100238 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 return;
240
241segv:
242 force_sig(SIGSEGV, current);
243}
244
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
246{
247 struct rt_signal_frame32 __user *sf;
David S. Millerd11c2a02016-05-28 21:21:31 -0700248 unsigned int psr, pc, npc, ufp;
David S. Miller55984732011-08-20 17:14:54 -0700249 compat_uptr_t fpu_save;
250 compat_uptr_t rwin_save;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 sigset_t set;
252 compat_sigset_t seta;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 int err, i;
254
255 /* Always make any pending restarted system calls return -EINTR */
Andy Lutomirskif56141e2015-02-12 15:01:14 -0800256 current->restart_block.fn = do_no_restart_syscall;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258 synchronize_user_stack();
259 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
260 sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
261
262 /* 1. Make sure we are not getting garbage from the user */
David S. Millerd11c2a02016-05-28 21:21:31 -0700263 if (invalid_frame_pointer(sf, sizeof(*sf)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 goto segv;
265
David S. Millerd11c2a02016-05-28 21:21:31 -0700266 if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
267 goto segv;
268
269 if (ufp & 0x7)
270 goto segv;
271
272 if (__get_user(pc, &sf->regs.pc) ||
Al Viro187cd442012-04-22 16:51:36 -0400273 __get_user(npc, &sf->regs.npc))
274 goto segv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
276 if ((pc | npc) & 3)
277 goto segv;
278
279 if (test_thread_flag(TIF_32BIT)) {
280 pc &= 0xffffffff;
281 npc &= 0xffffffff;
282 }
283 regs->tpc = pc;
284 regs->tnpc = npc;
285
286 /* 2. Restore the state */
287 err = __get_user(regs->y, &sf->regs.y);
288 err |= __get_user(psr, &sf->regs.psr);
289
290 for (i = UREG_G1; i <= UREG_I7; i++)
291 err |= __get_user(regs->u_regs[i], &sf->regs.u_regs[i]);
292 if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
293 err |= __get_user(i, &sf->v8plus.g_upper[0]);
294 if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
295 unsigned long asi;
296
297 for (i = UREG_G1; i <= UREG_I7; i++)
298 err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
299 err |= __get_user(asi, &sf->v8plus.asi);
300 regs->tstate &= ~TSTATE_ASI;
301 regs->tstate |= ((asi & 0xffUL) << 24UL);
302 }
303 }
304
305 /* User can only change condition codes in %tstate. */
306 regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
307 regs->tstate |= psr_to_tstate_icc(psr);
308
David S. Miller2678fef2008-05-01 03:30:22 -0700309 /* Prevent syscall restart. */
David S. Miller28e61032008-05-11 02:07:19 -0700310 pt_regs_clear_syscall(regs);
David S. Miller2678fef2008-05-01 03:30:22 -0700311
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 err |= __get_user(fpu_save, &sf->fpu_save);
David S. Miller55984732011-08-20 17:14:54 -0700313 if (!err && fpu_save)
314 err |= restore_fpu_state(regs, compat_ptr(fpu_save));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t));
Al Viro99b06fe2012-12-23 03:41:17 -0500316 err |= compat_restore_altstack(&sf->stack);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 if (err)
318 goto segv;
319
David S. Miller55984732011-08-20 17:14:54 -0700320 err |= __get_user(rwin_save, &sf->rwin_save);
321 if (!err && rwin_save) {
322 if (restore_rwin_state(compat_ptr(rwin_save)))
323 goto segv;
324 }
325
Sam Ravnborgc19ac322014-05-16 23:26:01 +0200326 set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
Matt Flemingfaddf592011-08-11 14:57:02 +0100327 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 return;
329segv:
330 force_sig(SIGSEGV, current);
331}
332
Al Viro08f73952012-11-07 23:48:13 -0500333static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{
335 unsigned long sp;
336
337 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
338 sp = regs->u_regs[UREG_FP];
339
David S. Millerdc5dc7e2008-05-07 18:54:05 -0700340 /*
341 * If we are on the alternate signal stack and would overflow it, don't.
342 * Return an always-bogus address instead so we will die with SIGSEGV.
343 */
344 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
345 return (void __user *) -1L;
346
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 /* This is the X/Open sanctioned signal stack switching. */
Al Viro08f73952012-11-07 23:48:13 -0500348 sp = sigsp(sp, ksig) - framesize;
David S. Millerf036d9f2010-02-09 16:18:40 -0800349
David S. Millerdc5dc7e2008-05-07 18:54:05 -0700350 /* Always align the stack frame. This handles two cases. First,
351 * sigaltstack need not be mindful of platform specific stack
352 * alignment. Second, if we took this signal because the stack
353 * is not aligned properly, we'd like to take the signal cleanly
354 * and report that.
355 */
David S. Millerf036d9f2010-02-09 16:18:40 -0800356 sp &= ~15UL;
David S. Millerdc5dc7e2008-05-07 18:54:05 -0700357
David S. Millerf036d9f2010-02-09 16:18:40 -0800358 return (void __user *) sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
David S. Miller05c5e762010-09-20 23:24:52 -0700361/* The I-cache flush instruction only works in the primary ASI, which
362 * right now is the nucleus, aka. kernel space.
363 *
364 * Therefore we have to kick the instructions out using the kernel
365 * side linear mapping of the physical address backing the user
366 * instructions.
367 */
368static void flush_signal_insns(unsigned long address)
369{
370 unsigned long pstate, paddr;
371 pte_t *ptep, pte;
372 pgd_t *pgdp;
373 pud_t *pudp;
374 pmd_t *pmdp;
375
376 /* Commit all stores of the instructions we are about to flush. */
377 wmb();
378
379 /* Disable cross-call reception. In this way even a very wide
380 * munmap() on another cpu can't tear down the page table
381 * hierarchy from underneath us, since that can't complete
382 * until the IPI tlb flush returns.
383 */
384
385 __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
386 __asm__ __volatile__("wrpr %0, %1, %%pstate"
387 : : "r" (pstate), "i" (PSTATE_IE));
388
389 pgdp = pgd_offset(current->mm, address);
390 if (pgd_none(*pgdp))
391 goto out_irqs_on;
392 pudp = pud_offset(pgdp, address);
393 if (pud_none(*pudp))
394 goto out_irqs_on;
395 pmdp = pmd_offset(pudp, address);
396 if (pmd_none(*pmdp))
397 goto out_irqs_on;
398
399 ptep = pte_offset_map(pmdp, address);
400 pte = *ptep;
401 if (!pte_present(pte))
402 goto out_unmap;
403
404 paddr = (unsigned long) page_address(pte_page(pte));
405
406 __asm__ __volatile__("flush %0 + %1"
407 : /* no outputs */
408 : "r" (paddr),
409 "r" (address & (PAGE_SIZE - 1))
410 : "memory");
411
412out_unmap:
413 pte_unmap(ptep);
414out_irqs_on:
415 __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
416
417}
418
Al Viro08f73952012-11-07 23:48:13 -0500419static int setup_frame32(struct ksignal *ksig, struct pt_regs *regs,
420 sigset_t *oldset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421{
David S. Miller5526b7e2008-04-27 02:26:36 -0700422 struct signal_frame32 __user *sf;
David S. Miller55984732011-08-20 17:14:54 -0700423 int i, err, wsaved;
424 void __user *tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 int sigframe_size;
426 u32 psr;
Sam Ravnborgc19ac322014-05-16 23:26:01 +0200427 compat_sigset_t seta;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 /* 1. Make sure everything is clean */
430 synchronize_user_stack();
431 save_and_clear_fpu();
432
David S. Miller55984732011-08-20 17:14:54 -0700433 wsaved = get_thread_wsaved();
434
435 sigframe_size = sizeof(*sf);
436 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
437 sigframe_size += sizeof(__siginfo_fpu_t);
438 if (wsaved)
439 sigframe_size += sizeof(__siginfo_rwin_t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
David S. Miller5526b7e2008-04-27 02:26:36 -0700441 sf = (struct signal_frame32 __user *)
Al Viro08f73952012-11-07 23:48:13 -0500442 get_sigframe(ksig, regs, sigframe_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
Al Viro08f73952012-11-07 23:48:13 -0500444 if (invalid_frame_pointer(sf, sigframe_size)) {
David Miller61a92172018-10-25 20:36:46 -0700445 if (show_unhandled_signals)
446 pr_info("%s[%d] bad frame in setup_frame32: %08lx TPC %08lx O7 %08lx\n",
447 current->comm, current->pid, (unsigned long)sf,
448 regs->tpc, regs->u_regs[UREG_I7]);
449 force_sigsegv(ksig->sig, current);
Al Viro08f73952012-11-07 23:48:13 -0500450 return -EINVAL;
451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
David S. Miller55984732011-08-20 17:14:54 -0700453 tail = (sf + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
455 /* 2. Save the current process state */
456 if (test_thread_flag(TIF_32BIT)) {
457 regs->tpc &= 0xffffffff;
458 regs->tnpc &= 0xffffffff;
459 }
460 err = put_user(regs->tpc, &sf->info.si_regs.pc);
461 err |= __put_user(regs->tnpc, &sf->info.si_regs.npc);
462 err |= __put_user(regs->y, &sf->info.si_regs.y);
463 psr = tstate_to_psr(regs->tstate);
464 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
465 psr |= PSR_EF;
466 err |= __put_user(psr, &sf->info.si_regs.psr);
467 for (i = 0; i < 16; i++)
468 err |= __put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
469 err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
470 err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
471 for (i = 1; i < 16; i++)
472 err |= __put_user(((u32 *)regs->u_regs)[2*i],
473 &sf->v8plus.g_upper[i]);
474 err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
475 &sf->v8plus.asi);
476
477 if (psr & PSR_EF) {
David S. Miller55984732011-08-20 17:14:54 -0700478 __siginfo_fpu_t __user *fp = tail;
479 tail += sizeof(*fp);
480 err |= save_fpu_state(regs, fp);
481 err |= __put_user((u64)fp, &sf->fpu_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 } else {
483 err |= __put_user(0, &sf->fpu_save);
484 }
David S. Miller55984732011-08-20 17:14:54 -0700485 if (wsaved) {
486 __siginfo_rwin_t __user *rwp = tail;
487 tail += sizeof(*rwp);
488 err |= save_rwin_state(wsaved, rwp);
489 err |= __put_user((u64)rwp, &sf->rwin_save);
490 set_thread_wsaved(0);
491 } else {
492 err |= __put_user(0, &sf->rwin_save);
493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
Sam Ravnborgc19ac322014-05-16 23:26:01 +0200495 /* If these change we need to know - assignments to seta relies on these sizes */
496 BUILD_BUG_ON(_NSIG_WORDS != 1);
497 BUILD_BUG_ON(_COMPAT_NSIG_WORDS != 2);
498 seta.sig[1] = (oldset->sig[0] >> 32);
499 seta.sig[0] = oldset->sig[0];
500
501 err |= __put_user(seta.sig[0], &sf->info.si_mask);
502 err |= __copy_to_user(sf->extramask, &seta.sig[1],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
504
David S. Miller55984732011-08-20 17:14:54 -0700505 if (!wsaved) {
506 err |= copy_in_user((u32 __user *)sf,
507 (u32 __user *)(regs->u_regs[UREG_FP]),
508 sizeof(struct reg_window32));
509 } else {
510 struct reg_window *rp;
511
512 rp = &current_thread_info()->reg_window[wsaved - 1];
513 for (i = 0; i < 8; i++)
514 err |= __put_user(rp->locals[i], &sf->ss.locals[i]);
515 for (i = 0; i < 6; i++)
516 err |= __put_user(rp->ins[i], &sf->ss.ins[i]);
517 err |= __put_user(rp->ins[6], &sf->ss.fp);
518 err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 if (err)
Al Viro08f73952012-11-07 23:48:13 -0500521 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
523 /* 3. signal handler back-trampoline and parameters */
524 regs->u_regs[UREG_FP] = (unsigned long) sf;
Al Viro08f73952012-11-07 23:48:13 -0500525 regs->u_regs[UREG_I0] = ksig->sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
527 regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
528
529 /* 4. signal handler */
Al Viro08f73952012-11-07 23:48:13 -0500530 regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 regs->tnpc = (regs->tpc + 4);
532 if (test_thread_flag(TIF_32BIT)) {
533 regs->tpc &= 0xffffffff;
534 regs->tnpc &= 0xffffffff;
535 }
536
537 /* 5. return to kernel instructions */
Al Viro08f73952012-11-07 23:48:13 -0500538 if (ksig->ka.ka_restorer) {
539 regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 unsigned long address = ((unsigned long)&(sf->insns[0]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543 regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
544
545 err = __put_user(0x821020d8, &sf->insns[0]); /*mov __NR_sigreturn, %g1*/
546 err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
547 if (err)
Al Viro08f73952012-11-07 23:48:13 -0500548 return err;
David S. Miller05c5e762010-09-20 23:24:52 -0700549 flush_signal_insns(address);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 }
David S. Millerc2785252010-09-21 22:30:13 -0700551 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552}
553
Al Viro08f73952012-11-07 23:48:13 -0500554static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs,
555 sigset_t *oldset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556{
557 struct rt_signal_frame32 __user *sf;
David S. Miller55984732011-08-20 17:14:54 -0700558 int i, err, wsaved;
559 void __user *tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 int sigframe_size;
561 u32 psr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 compat_sigset_t seta;
563
564 /* 1. Make sure everything is clean */
565 synchronize_user_stack();
566 save_and_clear_fpu();
567
David S. Miller55984732011-08-20 17:14:54 -0700568 wsaved = get_thread_wsaved();
569
570 sigframe_size = sizeof(*sf);
571 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
572 sigframe_size += sizeof(__siginfo_fpu_t);
573 if (wsaved)
574 sigframe_size += sizeof(__siginfo_rwin_t);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
576 sf = (struct rt_signal_frame32 __user *)
Al Viro08f73952012-11-07 23:48:13 -0500577 get_sigframe(ksig, regs, sigframe_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Al Viro08f73952012-11-07 23:48:13 -0500579 if (invalid_frame_pointer(sf, sigframe_size)) {
David Miller61a92172018-10-25 20:36:46 -0700580 if (show_unhandled_signals)
581 pr_info("%s[%d] bad frame in setup_rt_frame32: %08lx TPC %08lx O7 %08lx\n",
582 current->comm, current->pid, (unsigned long)sf,
583 regs->tpc, regs->u_regs[UREG_I7]);
584 force_sigsegv(ksig->sig, current);
Al Viro08f73952012-11-07 23:48:13 -0500585 return -EINVAL;
586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
David S. Miller55984732011-08-20 17:14:54 -0700588 tail = (sf + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590 /* 2. Save the current process state */
591 if (test_thread_flag(TIF_32BIT)) {
592 regs->tpc &= 0xffffffff;
593 regs->tnpc &= 0xffffffff;
594 }
595 err = put_user(regs->tpc, &sf->regs.pc);
596 err |= __put_user(regs->tnpc, &sf->regs.npc);
597 err |= __put_user(regs->y, &sf->regs.y);
598 psr = tstate_to_psr(regs->tstate);
599 if (current_thread_info()->fpsaved[0] & FPRS_FEF)
600 psr |= PSR_EF;
601 err |= __put_user(psr, &sf->regs.psr);
602 for (i = 0; i < 16; i++)
603 err |= __put_user(regs->u_regs[i], &sf->regs.u_regs[i]);
604 err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
605 err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
606 for (i = 1; i < 16; i++)
607 err |= __put_user(((u32 *)regs->u_regs)[2*i],
608 &sf->v8plus.g_upper[i]);
609 err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
610 &sf->v8plus.asi);
611
612 if (psr & PSR_EF) {
David S. Miller55984732011-08-20 17:14:54 -0700613 __siginfo_fpu_t __user *fp = tail;
614 tail += sizeof(*fp);
615 err |= save_fpu_state(regs, fp);
616 err |= __put_user((u64)fp, &sf->fpu_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 } else {
618 err |= __put_user(0, &sf->fpu_save);
619 }
David S. Miller55984732011-08-20 17:14:54 -0700620 if (wsaved) {
621 __siginfo_rwin_t __user *rwp = tail;
622 tail += sizeof(*rwp);
623 err |= save_rwin_state(wsaved, rwp);
624 err |= __put_user((u64)rwp, &sf->rwin_save);
625 set_thread_wsaved(0);
626 } else {
627 err |= __put_user(0, &sf->rwin_save);
628 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630 /* Update the siginfo structure. */
Al Viro08f73952012-11-07 23:48:13 -0500631 err |= copy_siginfo_to_user32(&sf->info, &ksig->info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633 /* Setup sigaltstack */
Al Viro99b06fe2012-12-23 03:41:17 -0500634 err |= __compat_save_altstack(&sf->stack, regs->u_regs[UREG_FP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Sam Ravnborgc19ac322014-05-16 23:26:01 +0200636 seta.sig[1] = (oldset->sig[0] >> 32);
637 seta.sig[0] = oldset->sig[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t));
639
David S. Miller55984732011-08-20 17:14:54 -0700640 if (!wsaved) {
641 err |= copy_in_user((u32 __user *)sf,
642 (u32 __user *)(regs->u_regs[UREG_FP]),
643 sizeof(struct reg_window32));
644 } else {
645 struct reg_window *rp;
646
647 rp = &current_thread_info()->reg_window[wsaved - 1];
648 for (i = 0; i < 8; i++)
649 err |= __put_user(rp->locals[i], &sf->ss.locals[i]);
650 for (i = 0; i < 6; i++)
651 err |= __put_user(rp->ins[i], &sf->ss.ins[i]);
652 err |= __put_user(rp->ins[6], &sf->ss.fp);
653 err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
654 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 if (err)
Al Viro08f73952012-11-07 23:48:13 -0500656 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658 /* 3. signal handler back-trampoline and parameters */
659 regs->u_regs[UREG_FP] = (unsigned long) sf;
Al Viro08f73952012-11-07 23:48:13 -0500660 regs->u_regs[UREG_I0] = ksig->sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
662 regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
663
664 /* 4. signal handler */
Al Viro08f73952012-11-07 23:48:13 -0500665 regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 regs->tnpc = (regs->tpc + 4);
667 if (test_thread_flag(TIF_32BIT)) {
668 regs->tpc &= 0xffffffff;
669 regs->tnpc &= 0xffffffff;
670 }
671
672 /* 5. return to kernel instructions */
Al Viro08f73952012-11-07 23:48:13 -0500673 if (ksig->ka.ka_restorer)
674 regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 unsigned long address = ((unsigned long)&(sf->insns[0]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
679
680 /* mov __NR_rt_sigreturn, %g1 */
681 err |= __put_user(0x82102065, &sf->insns[0]);
682
683 /* t 0x10 */
684 err |= __put_user(0x91d02010, &sf->insns[1]);
685 if (err)
Al Viro08f73952012-11-07 23:48:13 -0500686 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
David S. Miller05c5e762010-09-20 23:24:52 -0700688 flush_signal_insns(address);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 }
David S. Miller392c2182010-09-21 21:41:12 -0700690 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691}
692
Al Viro08f73952012-11-07 23:48:13 -0500693static inline void handle_signal32(struct ksignal *ksig,
694 struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695{
Al Viro08f73952012-11-07 23:48:13 -0500696 sigset_t *oldset = sigmask_to_save();
David S. Miller392c2182010-09-21 21:41:12 -0700697 int err;
698
Al Viro08f73952012-11-07 23:48:13 -0500699 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
700 err = setup_rt_frame32(ksig, regs, oldset);
David S. Millerec98c6b2008-04-20 02:14:23 -0700701 else
Al Viro08f73952012-11-07 23:48:13 -0500702 err = setup_frame32(ksig, regs, oldset);
David S. Miller392c2182010-09-21 21:41:12 -0700703
Al Viro08f73952012-11-07 23:48:13 -0500704 signal_setup_done(err, ksig, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705}
706
707static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
708 struct sigaction *sa)
709{
710 switch (regs->u_regs[UREG_I0]) {
711 case ERESTART_RESTARTBLOCK:
712 case ERESTARTNOHAND:
713 no_system_call_restart:
714 regs->u_regs[UREG_I0] = EINTR;
715 regs->tstate |= TSTATE_ICARRY;
716 break;
717 case ERESTARTSYS:
718 if (!(sa->sa_flags & SA_RESTART))
719 goto no_system_call_restart;
720 /* fallthrough */
721 case ERESTARTNOINTR:
722 regs->u_regs[UREG_I0] = orig_i0;
723 regs->tpc -= 4;
724 regs->tnpc -= 4;
725 }
726}
727
728/* Note that 'init' is a special process: it doesn't get signals it doesn't
729 * want to handle. Thus you cannot kill init even with a SIGKILL even by
730 * mistake.
731 */
Al Virodfbb83d2013-03-02 02:55:16 -0500732void do_signal32(struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733{
Al Viro08f73952012-11-07 23:48:13 -0500734 struct ksignal ksig;
735 unsigned long orig_i0 = 0;
736 int restart_syscall = 0;
737 bool has_handler = get_signal(&ksig);
David S. Miller28e61032008-05-11 02:07:19 -0700738
David S. Miller1d299bc2011-11-14 20:32:16 -0800739 if (pt_regs_is_syscall(regs) &&
740 (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
741 restart_syscall = 1;
David S. Millere88d2462011-11-15 12:57:00 -0800742 orig_i0 = regs->u_regs[UREG_G6];
David S. Miller1d299bc2011-11-14 20:32:16 -0800743 }
David S. Miller28e61032008-05-11 02:07:19 -0700744
Al Viro08f73952012-11-07 23:48:13 -0500745 if (has_handler) {
David S. Miller28e61032008-05-11 02:07:19 -0700746 if (restart_syscall)
Al Viro08f73952012-11-07 23:48:13 -0500747 syscall_restart32(orig_i0, regs, &ksig.ka.sa);
748 handle_signal32(&ksig, regs);
749 } else {
750 if (restart_syscall) {
751 switch (regs->u_regs[UREG_I0]) {
752 case ERESTARTNOHAND:
753 case ERESTARTSYS:
754 case ERESTARTNOINTR:
755 /* replay the system call when we are done */
756 regs->u_regs[UREG_I0] = orig_i0;
757 regs->tpc -= 4;
758 regs->tnpc -= 4;
759 pt_regs_clear_syscall(regs);
760 case ERESTART_RESTARTBLOCK:
761 regs->u_regs[UREG_G1] = __NR_restart_syscall;
762 regs->tpc -= 4;
763 regs->tnpc -= 4;
764 pt_regs_clear_syscall(regs);
765 }
766 }
767 restore_saved_sigmask();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769}
770
771struct sigstack32 {
772 u32 the_stack;
773 int cur_status;
774};
775
776asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp)
777{
778 struct sigstack32 __user *ssptr =
779 (struct sigstack32 __user *)((unsigned long)(u_ssptr));
780 struct sigstack32 __user *ossptr =
781 (struct sigstack32 __user *)((unsigned long)(u_ossptr));
782 int ret = -EFAULT;
783
784 /* First see if old state is wanted. */
785 if (ossptr) {
786 if (put_user(current->sas_ss_sp + current->sas_ss_size,
787 &ossptr->the_stack) ||
788 __put_user(on_sig_stack(sp), &ossptr->cur_status))
789 goto out;
790 }
791
792 /* Now see if we want to update the new state. */
793 if (ssptr) {
794 u32 ss_sp;
795
796 if (get_user(ss_sp, &ssptr->the_stack))
797 goto out;
798
799 /* If the current stack was set with sigaltstack, don't
800 * swap stacks while we are on it.
801 */
802 ret = -EPERM;
803 if (current->sas_ss_sp && on_sig_stack(sp))
804 goto out;
805
806 /* Since we don't know the extent of the stack, and we don't
807 * track onstack-ness, but rather calculate it, we must
808 * presume a size. Ho hum this interface is lossy.
809 */
810 current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ;
811 current->sas_ss_size = SIGSTKSZ;
812 }
813
814 ret = 0;
815out:
816 return ret;
817}