Blame view

arch/mips/kernel/signal32.c 21.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file "COPYING" in the main directory of this archive
   * for more details.
   *
   * Copyright (C) 1991, 1992  Linus Torvalds
dda73d0bb   Martin Michlmayr   [MIPS] Make do_si...
7
   * Copyright (C) 1994 - 2000, 2006  Ralf Baechle
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
   * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   */
02416dcf5   Ralf Baechle   Redo RM9000 worka...
10
  #include <linux/cache.h>
431dc8040   Ralf Baechle   [MIPS] Fix sigset...
11
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
  #include <linux/sched.h>
  #include <linux/mm.h>
  #include <linux/smp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
20
  #include <linux/kernel.h>
  #include <linux/signal.h>
  #include <linux/syscalls.h>
  #include <linux/errno.h>
  #include <linux/wait.h>
  #include <linux/ptrace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
  #include <linux/suspend.h>
  #include <linux/compiler.h>
faea62346   Atsushi Nemoto   [MIPS] Retry {sav...
23
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

e50c0a8fa   Ralf Baechle   Support the MIPS3...
25
  #include <asm/abi.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <asm/asm.h>
431dc8040   Ralf Baechle   [MIPS] Fix sigset...
27
  #include <asm/compat-signal.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
  #include <linux/bitops.h>
  #include <asm/cacheflush.h>
  #include <asm/sim.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
  #include <asm/ucontext.h>
  #include <asm/system.h>
  #include <asm/fpu.h>
02416dcf5   Ralf Baechle   Redo RM9000 worka...
34
  #include <asm/war.h>
d814c28ce   David Daney   MIPS: Move signal...
35
  #include <asm/vdso.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36

36a1f2c24   Franck Bui-Huu   [MIPS] signal32: ...
37
  #include "signal-common.h"
137f6f3e2   Ralf Baechle   MIPS: Cleanup sig...
38
39
40
41
42
43
44
45
  static int (*save_fp_context32)(struct sigcontext32 __user *sc);
  static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
  
  extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
  extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
  
  extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
  extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
  /*
   * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
   */
151fd6acd   Ralf Baechle   [MIPS] signals: S...
49
  #define __NR_O32_restart_syscall        4253
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  /* 32-bit compatibility types */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  typedef unsigned int __sighandler32_t;
  typedef void (*vfptr_t)(void);
  
  struct sigaction32 {
  	unsigned int		sa_flags;
  	__sighandler32_t	sa_handler;
  	compat_sigset_t		sa_mask;
  };
  
  /* IRIX compatible stack_t  */
  typedef struct sigaltstack32 {
  	s32 ss_sp;
  	compat_size_t ss_size;
  	int ss_flags;
  } stack32_t;
  
  struct ucontext32 {
  	u32                 uc_flags;
  	s32                 uc_link;
  	stack32_t           uc_stack;
  	struct sigcontext32 uc_mcontext;
01ee60370   Ralf Baechle   [MIPS] sigset_32 ...
73
  	compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  };
dd02f06aa   Ralf Baechle   [MIPS] signal: Fi...
75
76
  struct sigframe32 {
  	u32 sf_ass[4];		/* argument save space for o32 */
d814c28ce   David Daney   MIPS: Move signal...
77
  	u32 sf_pad[2];		/* Was: signal trampoline */
dd02f06aa   Ralf Baechle   [MIPS] signal: Fi...
78
  	struct sigcontext32 sf_sc;
755f21bb8   Atsushi Nemoto   [MIPS] Fix sigset...
79
  	compat_sigset_t sf_mask;
dd02f06aa   Ralf Baechle   [MIPS] signal: Fi...
80
  };
c0b9bae9d   Franck Bui-Huu   [MIPS] signal: cl...
81
82
  struct rt_sigframe32 {
  	u32 rs_ass[4];			/* argument save space for o32 */
d814c28ce   David Daney   MIPS: Move signal...
83
  	u32 rs_pad[2];			/* Was: signal trampoline */
c0b9bae9d   Franck Bui-Huu   [MIPS] signal: cl...
84
85
86
  	compat_siginfo_t rs_info;
  	struct ucontext32 rs_uc;
  };
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
87
88
89
  /*
   * sigcontext handlers
   */
faea62346   Atsushi Nemoto   [MIPS] Retry {sav...
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  static int protected_save_fp_context32(struct sigcontext32 __user *sc)
  {
  	int err;
  	while (1) {
  		lock_fpu_owner();
  		own_fpu_inatomic(1);
  		err = save_fp_context32(sc); /* this might fail */
  		unlock_fpu_owner();
  		if (likely(!err))
  			break;
  		/* touch the sigcontext and try again */
  		err = __put_user(0, &sc->sc_fpregs[0]) |
  			__put_user(0, &sc->sc_fpregs[31]) |
  			__put_user(0, &sc->sc_fpc_csr);
  		if (err)
  			break;	/* really bad sigcontext */
  	}
  	return err;
  }
  
  static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
  {
c726b8221   David Daney   MIPS: Fix GCC-4.6...
112
  	int err, tmp __maybe_unused;
faea62346   Atsushi Nemoto   [MIPS] Retry {sav...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  	while (1) {
  		lock_fpu_owner();
  		own_fpu_inatomic(0);
  		err = restore_fp_context32(sc); /* this might fail */
  		unlock_fpu_owner();
  		if (likely(!err))
  			break;
  		/* touch the sigcontext and try again */
  		err = __get_user(tmp, &sc->sc_fpregs[0]) |
  			__get_user(tmp, &sc->sc_fpregs[31]) |
  			__get_user(tmp, &sc->sc_fpc_csr);
  		if (err)
  			break;	/* really bad sigcontext */
  	}
  	return err;
  }
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
129
130
131
132
133
  static int setup_sigcontext32(struct pt_regs *regs,
  			      struct sigcontext32 __user *sc)
  {
  	int err = 0;
  	int i;
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
134
  	u32 used_math;
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
135
136
  
  	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  
  	err |= __put_user(0, &sc->sc_regs[0]);
  	for (i = 1; i < 32; i++)
  		err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
  
  	err |= __put_user(regs->hi, &sc->sc_mdhi);
  	err |= __put_user(regs->lo, &sc->sc_mdlo);
  	if (cpu_has_dsp) {
  		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
  		err |= __put_user(mfhi1(), &sc->sc_hi1);
  		err |= __put_user(mflo1(), &sc->sc_lo1);
  		err |= __put_user(mfhi2(), &sc->sc_hi2);
  		err |= __put_user(mflo2(), &sc->sc_lo2);
  		err |= __put_user(mfhi3(), &sc->sc_hi3);
  		err |= __put_user(mflo3(), &sc->sc_lo3);
  	}
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
153
154
  	used_math = !!used_math();
  	err |= __put_user(used_math, &sc->sc_used_math);
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
155

53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
156
  	if (used_math) {
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
157
158
159
160
  		/*
  		 * Save FPU state to signal context.  Signal handler
  		 * will "inherit" current FPU state.
  		 */
faea62346   Atsushi Nemoto   [MIPS] Retry {sav...
161
  		err |= protected_save_fp_context32(sc);
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
162
163
164
  	}
  	return err;
  }
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
165
166
167
168
169
170
171
172
  static int
  check_and_restore_fp_context32(struct sigcontext32 __user *sc)
  {
  	int err, sig;
  
  	err = sig = fpcsr_pending(&sc->sc_fpc_csr);
  	if (err > 0)
  		err = 0;
faea62346   Atsushi Nemoto   [MIPS] Retry {sav...
173
  	err |= protected_restore_fp_context32(sc);
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
174
175
  	return err ?: sig;
  }
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  static int restore_sigcontext32(struct pt_regs *regs,
  				struct sigcontext32 __user *sc)
  {
  	u32 used_math;
  	int err = 0;
  	s32 treg;
  	int i;
  
  	/* Always make any pending restarted system calls return -EINTR */
  	current_thread_info()->restart_block.fn = do_no_restart_syscall;
  
  	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
  	err |= __get_user(regs->hi, &sc->sc_mdhi);
  	err |= __get_user(regs->lo, &sc->sc_mdlo);
  	if (cpu_has_dsp) {
  		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
  		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
  		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
  		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
  		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
  		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
  		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
  	}
  
  	for (i = 1; i < 32; i++)
  		err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
  
  	err |= __get_user(used_math, &sc->sc_used_math);
  	conditional_used_math(used_math);
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
205
  	if (used_math) {
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
206
  		/* restore fpu context if we have used it before */
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
207
208
  		if (!err)
  			err = check_and_restore_fp_context32(sc);
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
209
210
  	} else {
  		/* signal handler may have used FPU.  Give it up. */
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
211
  		lose_fpu(0);
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
212
  	}
9432a9ba9   Franck Bui-Huu   [MIPS] signal32: ...
213
214
215
216
217
218
  	return err;
  }
  
  /*
   *
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
  extern void __put_sigset_unknown_nsig(void);
  extern void __get_sigset_unknown_nsig(void);
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
221
  static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
226
227
228
229
230
231
  {
  	int err = 0;
  
  	if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
  		return -EFAULT;
  
  	switch (_NSIG_WORDS) {
  	default:
  		__put_sigset_unknown_nsig();
  	case 2:
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
232
233
  		err |= __put_user(kbuf->sig[1] >> 32, &ubuf->sig[3]);
  		err |= __put_user(kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
  	case 1:
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
235
236
  		err |= __put_user(kbuf->sig[0] >> 32, &ubuf->sig[1]);
  		err |= __put_user(kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
  	}
  
  	return err;
  }
9c6031cc9   Atsushi Nemoto   [MIPS] Signal cle...
241
  static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
246
247
248
249
250
251
252
  {
  	int err = 0;
  	unsigned long sig[4];
  
  	if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
  		return -EFAULT;
  
  	switch (_NSIG_WORDS) {
  	default:
  		__get_sigset_unknown_nsig();
  	case 2:
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
253
254
  		err |= __get_user(sig[3], &ubuf->sig[3]);
  		err |= __get_user(sig[2], &ubuf->sig[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
  		kbuf->sig[1] = sig[2] | (sig[3] << 32);
  	case 1:
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
257
258
  		err |= __get_user(sig[1], &ubuf->sig[1]);
  		err |= __get_user(sig[0], &ubuf->sig[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
262
263
264
265
266
267
  		kbuf->sig[0] = sig[0] | (sig[1] << 32);
  	}
  
  	return err;
  }
  
  /*
   * Atomically swap in the new signal mask, and wait for a signal.
   */
f90080a05   Franck Bui-Huu   [MIPS] signal: do...
268
  asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  {
9c6031cc9   Atsushi Nemoto   [MIPS] Signal cle...
270
  	compat_sigset_t __user *uset;
68fa383f3   Martin Michlmayr   [MIPS] Add suppor...
271
  	sigset_t newset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272

9c6031cc9   Atsushi Nemoto   [MIPS] Signal cle...
273
  	uset = (compat_sigset_t __user *) regs.regs[4];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
276
277
278
  	if (get_sigset(&newset, uset))
  		return -EFAULT;
  	sigdelsetmask(&newset, ~_BLOCKABLE);
  
  	spin_lock_irq(&current->sighand->siglock);
68fa383f3   Martin Michlmayr   [MIPS] Add suppor...
279
  	current->saved_sigmask = current->blocked;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
  	current->blocked = newset;
  	recalc_sigpending();
  	spin_unlock_irq(&current->sighand->siglock);
68fa383f3   Martin Michlmayr   [MIPS] Add suppor...
283
284
285
286
  	current->state = TASK_INTERRUPTIBLE;
  	schedule();
  	set_thread_flag(TIF_RESTORE_SIGMASK);
  	return -ERESTARTNOHAND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  }
f90080a05   Franck Bui-Huu   [MIPS] signal: do...
288
  asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
  {
9c6031cc9   Atsushi Nemoto   [MIPS] Signal cle...
290
  	compat_sigset_t __user *uset;
68fa383f3   Martin Michlmayr   [MIPS] Add suppor...
291
  	sigset_t newset;
304416da8   Ralf Baechle   [MIPS] Reformat _...
292
  	size_t sigsetsize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
297
  
  	/* XXX Don't preclude handling different sized sigset_t's.  */
  	sigsetsize = regs.regs[5];
  	if (sigsetsize != sizeof(compat_sigset_t))
  		return -EINVAL;
9c6031cc9   Atsushi Nemoto   [MIPS] Signal cle...
298
  	uset = (compat_sigset_t __user *) regs.regs[4];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
303
  	if (get_sigset(&newset, uset))
  		return -EFAULT;
  	sigdelsetmask(&newset, ~_BLOCKABLE);
  
  	spin_lock_irq(&current->sighand->siglock);
68fa383f3   Martin Michlmayr   [MIPS] Add suppor...
304
  	current->saved_sigmask = current->blocked;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  	current->blocked = newset;
6254944fa   Martin Michlmayr   [MIPS] Reformat a...
306
  	recalc_sigpending();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
  	spin_unlock_irq(&current->sighand->siglock);
68fa383f3   Martin Michlmayr   [MIPS] Add suppor...
308
309
310
311
  	current->state = TASK_INTERRUPTIBLE;
  	schedule();
  	set_thread_flag(TIF_RESTORE_SIGMASK);
  	return -ERESTARTNOHAND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  }
dbda6ac08   Ralf Baechle   MIPS: CVE-2009-00...
313
314
  SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
  	struct sigaction32 __user *, oact)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
320
321
  {
  	struct k_sigaction new_ka, old_ka;
  	int ret;
  	int err = 0;
  
  	if (act) {
  		old_sigset_t mask;
77c728c22   Ralf Baechle   Gcc 4.0 fixes.
322
  		s32 handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
  
  		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
  			return -EFAULT;
77c728c22   Ralf Baechle   Gcc 4.0 fixes.
326
  		err |= __get_user(handler, &act->sa_handler);
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
327
  		new_ka.sa.sa_handler = (void __user *)(s64)handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
331
332
333
334
335
336
337
338
339
  		err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
  		err |= __get_user(mask, &act->sa_mask.sig[0]);
  		if (err)
  			return -EFAULT;
  
  		siginitset(&new_ka.sa.sa_mask, mask);
  	}
  
  	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
  
  	if (!ret && oact) {
  		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
6254944fa   Martin Michlmayr   [MIPS] Reformat a...
340
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
  		err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
  		err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
  		                  &oact->sa_handler);
  		err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
6254944fa   Martin Michlmayr   [MIPS] Reformat a...
345
346
347
348
  		err |= __put_user(0, &oact->sa_mask.sig[1]);
  		err |= __put_user(0, &oact->sa_mask.sig[2]);
  		err |= __put_user(0, &oact->sa_mask.sig[3]);
  		if (err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
352
353
354
355
356
  			return -EFAULT;
  	}
  
  	return ret;
  }
  
  asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
  {
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
357
358
  	const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
  	stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
361
362
363
364
365
366
367
368
  	unsigned long usp = regs.regs[29];
  	stack_t kss, koss;
  	int ret, err = 0;
  	mm_segment_t old_fs = get_fs();
  	s32 sp;
  
  	if (uss) {
  		if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
  			return -EFAULT;
  		err |= __get_user(sp, &uss->ss_sp);
9c6031cc9   Atsushi Nemoto   [MIPS] Signal cle...
369
  		kss.ss_sp = (void __user *) (long) sp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
374
  		err |= __get_user(kss.ss_size, &uss->ss_size);
  		err |= __get_user(kss.ss_flags, &uss->ss_flags);
  		if (err)
  			return -EFAULT;
  	}
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
375
  	set_fs(KERNEL_DS);
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
376
377
  	ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
  			     uoss ? (stack_t __user *)&koss : NULL, usp);
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
378
  	set_fs(old_fs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
  
  	if (!ret && uoss) {
  		if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
  			return -EFAULT;
9c6031cc9   Atsushi Nemoto   [MIPS] Signal cle...
383
  		sp = (int) (unsigned long) koss.ss_sp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
387
388
389
390
391
  		err |= __put_user(sp, &uoss->ss_sp);
  		err |= __put_user(koss.ss_size, &uoss->ss_size);
  		err |= __put_user(koss.ss_flags, &uoss->ss_flags);
  		if (err)
  			return -EFAULT;
  	}
  	return ret;
  }
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
392
  int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  {
  	int err;
  
  	if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
  		return -EFAULT;
  
  	/* If you change siginfo_t structure, please be sure
  	   this code is fixed accordingly.
  	   It should never copy any pad contained in the structure
  	   to avoid security leaks, but must copy the generic
  	   3 ints plus the relevant union member.
  	   This routine must convert siginfo from 64bit to 32bit as well
  	   at the same time.  */
  	err = __put_user(from->si_signo, &to->si_signo);
  	err |= __put_user(from->si_errno, &to->si_errno);
  	err |= __put_user((short)from->si_code, &to->si_code);
  	if (from->si_code < 0)
  		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
  	else {
  		switch (from->si_code >> 16) {
a982099ca   Ralf Baechle   Update to match t...
413
414
415
416
417
  		case __SI_TIMER >> 16:
  			err |= __put_user(from->si_tid, &to->si_tid);
  			err |= __put_user(from->si_overrun, &to->si_overrun);
  			err |= __put_user(from->si_int, &to->si_int);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
420
421
422
423
424
425
426
  		case __SI_CHLD >> 16:
  			err |= __put_user(from->si_utime, &to->si_utime);
  			err |= __put_user(from->si_stime, &to->si_stime);
  			err |= __put_user(from->si_status, &to->si_status);
  		default:
  			err |= __put_user(from->si_pid, &to->si_pid);
  			err |= __put_user(from->si_uid, &to->si_uid);
  			break;
  		case __SI_FAULT >> 16:
5665a0ac5   Atsushi Nemoto   [MIPS] Fix minor ...
427
  			err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
  			break;
  		case __SI_POLL >> 16:
  			err |= __put_user(from->si_band, &to->si_band);
  			err |= __put_user(from->si_fd, &to->si_fd);
  			break;
  		case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
  		case __SI_MESGQ >> 16:
  			err |= __put_user(from->si_pid, &to->si_pid);
  			err |= __put_user(from->si_uid, &to->si_uid);
  			err |= __put_user(from->si_int, &to->si_int);
  			break;
  		}
  	}
  	return err;
  }
5d9a76cd0   Thomas Bogendoerfer   MIPS: Use compat_...
443
444
445
446
447
448
449
450
451
452
453
  int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
  {
  	memset(to, 0, sizeof *to);
  
  	if (copy_from_user(to, from, 3*sizeof(int)) ||
  	    copy_from_user(to->_sifields._pad,
  			   from->_sifields._pad, SI_PAD_SIZE32))
  		return -EFAULT;
  
  	return 0;
  }
f90080a05   Franck Bui-Huu   [MIPS] signal: do...
454
  asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
  {
dd02f06aa   Ralf Baechle   [MIPS] signal: Fi...
456
  	struct sigframe32 __user *frame;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  	sigset_t blocked;
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
458
  	int sig;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459

dd02f06aa   Ralf Baechle   [MIPS] signal: Fi...
460
  	frame = (struct sigframe32 __user *) regs.regs[29];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
  		goto badframe;
431dc8040   Ralf Baechle   [MIPS] Fix sigset...
463
  	if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
468
469
470
  		goto badframe;
  
  	sigdelsetmask(&blocked, ~_BLOCKABLE);
  	spin_lock_irq(&current->sighand->siglock);
  	current->blocked = blocked;
  	recalc_sigpending();
  	spin_unlock_irq(&current->sighand->siglock);
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
471
472
  	sig = restore_sigcontext32(&regs, &frame->sf_sc);
  	if (sig < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  		goto badframe;
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
474
475
  	else if (sig)
  		force_sig(sig, current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
479
  
  	/*
  	 * Don't let your children do this ...
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
483
484
485
486
487
488
489
490
  	__asm__ __volatile__(
  		"move\t$29, %0
  \t"
  		"j\tsyscall_exit"
  		:/* no outputs */
  		:"r" (&regs));
  	/* Unreached */
  
  badframe:
  	force_sig(SIGSEGV, current);
  }
f90080a05   Franck Bui-Huu   [MIPS] signal: do...
491
  asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  {
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
493
  	struct rt_sigframe32 __user *frame;
1fcf1cc74   Ralf Baechle   We pass a kernel ...
494
  	mm_segment_t old_fs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
  	sigset_t set;
  	stack_t st;
  	s32 sp;
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
498
  	int sig;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499

9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
500
  	frame = (struct rt_sigframe32 __user *) regs.regs[29];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
502
  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
  		goto badframe;
431dc8040   Ralf Baechle   [MIPS] Fix sigset...
503
  	if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
508
509
510
  		goto badframe;
  
  	sigdelsetmask(&set, ~_BLOCKABLE);
  	spin_lock_irq(&current->sighand->siglock);
  	current->blocked = set;
  	recalc_sigpending();
  	spin_unlock_irq(&current->sighand->siglock);
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
511
512
  	sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
  	if (sig < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  		goto badframe;
c6a2f4679   Atsushi Nemoto   [MIPS] Check FCSR...
514
515
  	else if (sig)
  		force_sig(sig, current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
  
  	/* The ucontext contains a stack32_t, so we must convert!  */
  	if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
  		goto badframe;
9c6031cc9   Atsushi Nemoto   [MIPS] Signal cle...
520
  	st.ss_sp = (void __user *)(long) sp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
526
527
  	if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
  		goto badframe;
  	if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
  		goto badframe;
  
  	/* It is more difficult to avoid calling this function than to
  	   call it and ignore errors.  */
1fcf1cc74   Ralf Baechle   We pass a kernel ...
528
  	old_fs = get_fs();
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
529
  	set_fs(KERNEL_DS);
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
530
  	do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
531
  	set_fs(old_fs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
  
  	/*
  	 * Don't let your children do this ...
  	 */
  	__asm__ __volatile__(
  		"move\t$29, %0
  \t"
  		"j\tsyscall_exit"
  		:/* no outputs */
  		:"r" (&regs));
  	/* Unreached */
  
  badframe:
  	force_sig(SIGSEGV, current);
  }
d814c28ce   David Daney   MIPS: Move signal...
547
548
  static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
  			  struct pt_regs *regs, int signr, sigset_t *set)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
  {
dd02f06aa   Ralf Baechle   [MIPS] signal: Fi...
550
  	struct sigframe32 __user *frame;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
555
  	int err = 0;
  
  	frame = get_sigframe(ka, regs, sizeof(*frame));
  	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
  		goto give_sigsegv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
  	err |= setup_sigcontext32(regs, &frame->sf_sc);
431dc8040   Ralf Baechle   [MIPS] Fix sigset...
557
  	err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  	if (err)
  		goto give_sigsegv;
  
  	/*
  	 * Arguments to signal handler:
  	 *
  	 *   a0 = signal number
  	 *   a1 = 0 (should be cause)
  	 *   a2 = pointer to struct sigcontext
  	 *
  	 * $25 and c0_epc point to the signal handler, $29 points to the
  	 * struct sigframe.
  	 */
  	regs->regs[ 4] = signr;
  	regs->regs[ 5] = 0;
  	regs->regs[ 6] = (unsigned long) &frame->sf_sc;
  	regs->regs[29] = (unsigned long) frame;
d814c28ce   David Daney   MIPS: Move signal...
575
  	regs->regs[31] = (unsigned long) sig_return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
722bb63de   Franck Bui-Huu   [MIPS] signal: fa...
577
578
  	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
  	       current->comm, current->pid,
722bb63de   Franck Bui-Huu   [MIPS] signal: fa...
580
  	       frame, regs->cp0_epc, regs->regs[31]);
7b3e2fc84   Ralf Baechle   [MIPS] Add suppor...
581
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
  
  give_sigsegv:
  	force_sigsegv(signr, current);
7b3e2fc84   Ralf Baechle   [MIPS] Add suppor...
585
  	return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  }
d814c28ce   David Daney   MIPS: Move signal...
587
588
589
  static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
  			     struct pt_regs *regs, int signr, sigset_t *set,
  			     siginfo_t *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
  {
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
591
  	struct rt_sigframe32 __user *frame;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
594
595
596
597
  	int err = 0;
  	s32 sp;
  
  	frame = get_sigframe(ka, regs, sizeof(*frame));
  	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
  		goto give_sigsegv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
600
601
602
603
604
605
606
607
608
609
610
611
  	/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
  	err |= copy_siginfo_to_user32(&frame->rs_info, info);
  
  	/* Create the ucontext.  */
  	err |= __put_user(0, &frame->rs_uc.uc_flags);
  	err |= __put_user(0, &frame->rs_uc.uc_link);
  	sp = (int) (long) current->sas_ss_sp;
  	err |= __put_user(sp,
  	                  &frame->rs_uc.uc_stack.ss_sp);
  	err |= __put_user(sas_ss_flags(regs->regs[29]),
  	                  &frame->rs_uc.uc_stack.ss_flags);
  	err |= __put_user(current->sas_ss_size,
  	                  &frame->rs_uc.uc_stack.ss_size);
  	err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
431dc8040   Ralf Baechle   [MIPS] Fix sigset...
612
  	err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  
  	if (err)
  		goto give_sigsegv;
  
  	/*
  	 * Arguments to signal handler:
  	 *
  	 *   a0 = signal number
  	 *   a1 = 0 (should be cause)
  	 *   a2 = pointer to ucontext
  	 *
  	 * $25 and c0_epc point to the signal handler, $29 points to
  	 * the struct rt_sigframe32.
  	 */
  	regs->regs[ 4] = signr;
  	regs->regs[ 5] = (unsigned long) &frame->rs_info;
  	regs->regs[ 6] = (unsigned long) &frame->rs_uc;
  	regs->regs[29] = (unsigned long) frame;
d814c28ce   David Daney   MIPS: Move signal...
631
  	regs->regs[31] = (unsigned long) sig_return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
722bb63de   Franck Bui-Huu   [MIPS] signal: fa...
633
634
  	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  	       current->comm, current->pid,
722bb63de   Franck Bui-Huu   [MIPS] signal: fa...
636
  	       frame, regs->cp0_epc, regs->regs[31]);
7b3e2fc84   Ralf Baechle   [MIPS] Add suppor...
637
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
  
  give_sigsegv:
  	force_sigsegv(signr, current);
7b3e2fc84   Ralf Baechle   [MIPS] Add suppor...
641
  	return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
  }
151fd6acd   Ralf Baechle   [MIPS] signals: S...
643
644
645
646
647
  /*
   * o32 compatibility on 64-bit kernels, without DSP ASE
   */
  struct mips_abi mips_abi_32 = {
  	.setup_frame	= setup_frame_32,
d814c28ce   David Daney   MIPS: Move signal...
648
649
  	.signal_return_offset =
  		offsetof(struct mips_vdso, o32_signal_trampoline),
151fd6acd   Ralf Baechle   [MIPS] signals: S...
650
  	.setup_rt_frame	= setup_rt_frame_32,
d814c28ce   David Daney   MIPS: Move signal...
651
652
  	.rt_signal_return_offset =
  		offsetof(struct mips_vdso, o32_rt_signal_trampoline),
151fd6acd   Ralf Baechle   [MIPS] signals: S...
653
654
  	.restart	= __NR_O32_restart_syscall
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655

dbda6ac08   Ralf Baechle   MIPS: CVE-2009-00...
656
657
658
  SYSCALL_DEFINE4(32_rt_sigaction, int, sig,
  	const struct sigaction32 __user *, act,
  	struct sigaction32 __user *, oact, unsigned int, sigsetsize)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
663
664
665
666
667
  {
  	struct k_sigaction new_sa, old_sa;
  	int ret = -EINVAL;
  
  	/* XXX: Don't preclude handling different sized sigset_t's.  */
  	if (sigsetsize != sizeof(sigset_t))
  		goto out;
  
  	if (act) {
77c728c22   Ralf Baechle   Gcc 4.0 fixes.
668
  		s32 handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
671
672
  		int err = 0;
  
  		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
  			return -EFAULT;
77c728c22   Ralf Baechle   Gcc 4.0 fixes.
673
  		err |= __get_user(handler, &act->sa_handler);
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
674
  		new_sa.sa.sa_handler = (void __user *)(s64)handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
  		err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
  		err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
  		if (err)
  			return -EFAULT;
  	}
  
  	ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
  
  	if (!ret && oact) {
  		int err = 0;
  
  		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
  			return -EFAULT;
  
  		err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
  		                   &oact->sa_handler);
  		err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
  		err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
  		if (err)
  			return -EFAULT;
  	}
  out:
  	return ret;
  }
dbda6ac08   Ralf Baechle   MIPS: CVE-2009-00...
699
700
  SYSCALL_DEFINE4(32_rt_sigprocmask, int, how, compat_sigset_t __user *, set,
  	compat_sigset_t __user *, oset, unsigned int, sigsetsize)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
703
704
705
706
707
  {
  	sigset_t old_set, new_set;
  	int ret;
  	mm_segment_t old_fs = get_fs();
  
  	if (set && get_sigset(&new_set, set))
  		return -EFAULT;
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
708
  	set_fs(KERNEL_DS);
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
709
710
711
  	ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
  				 oset ? (sigset_t __user *)&old_set : NULL,
  				 sigsetsize);
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
712
  	set_fs(old_fs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
713
714
715
716
717
718
  
  	if (!ret && oset && put_sigset(&old_set, oset))
  		return -EFAULT;
  
  	return ret;
  }
dbda6ac08   Ralf Baechle   MIPS: CVE-2009-00...
719
720
  SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset,
  	unsigned int, sigsetsize)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
722
723
724
  {
  	int ret;
  	sigset_t set;
  	mm_segment_t old_fs = get_fs();
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
725
  	set_fs(KERNEL_DS);
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
726
  	ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
727
  	set_fs(old_fs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
730
731
732
733
  
  	if (!ret && put_sigset(&set, uset))
  		return -EFAULT;
  
  	return ret;
  }
dbda6ac08   Ralf Baechle   MIPS: CVE-2009-00...
734
735
  SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig,
  	compat_siginfo_t __user *, uinfo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
738
739
  {
  	siginfo_t info;
  	int ret;
  	mm_segment_t old_fs = get_fs();
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
740
741
  	if (copy_from_user(&info, uinfo, 3*sizeof(int)) ||
  	    copy_from_user(info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  		return -EFAULT;
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
743
  	set_fs(KERNEL_DS);
9bbf28a36   Atsushi Nemoto   [MIPS] Sparse: Ad...
744
  	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
745
  	set_fs(old_fs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
  	return ret;
  }
54f2da755   Ralf Baechle   Implement 32-bit ...
748

dbda6ac08   Ralf Baechle   MIPS: CVE-2009-00...
749
750
751
  SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
  	     compat_siginfo_t __user *, uinfo, int, options,
  	     struct compat_rusage __user *, uru)
54f2da755   Ralf Baechle   Implement 32-bit ...
752
753
754
755
756
757
758
  {
  	siginfo_t info;
  	struct rusage ru;
  	long ret;
  	mm_segment_t old_fs = get_fs();
  
  	info.si_signo = 0;
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
759
  	set_fs(KERNEL_DS);
54f2da755   Ralf Baechle   Implement 32-bit ...
760
761
  	ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
  			 uru ? (struct rusage __user *) &ru : NULL);
49a89efbb   Ralf Baechle   [MIPS] Fix "no sp...
762
  	set_fs(old_fs);
54f2da755   Ralf Baechle   Implement 32-bit ...
763
764
765
766
767
768
769
770
771
772
773
  
  	if (ret < 0 || info.si_signo == 0)
  		return ret;
  
  	if (uru && (ret = put_compat_rusage(&ru, uru)))
  		return ret;
  
  	BUG_ON(info.si_code & __SI_MASK);
  	info.si_code |= __SI_CHLD;
  	return copy_siginfo_to_user32(uinfo, &info);
  }
137f6f3e2   Ralf Baechle   MIPS: Cleanup sig...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
  
  static int signal32_init(void)
  {
  	if (cpu_has_fpu) {
  		save_fp_context32 = _save_fp_context32;
  		restore_fp_context32 = _restore_fp_context32;
  	} else {
  		save_fp_context32 = fpu_emulator_save_context32;
  		restore_fp_context32 = fpu_emulator_restore_context32;
  	}
  
  	return 0;
  }
  
  arch_initcall(signal32_init);