Blame view
arch/mips/kernel/signal32.c
21.2 KB
1da177e4c 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 [MIPS] Make do_si... |
7 |
* Copyright (C) 1994 - 2000, 2006 Ralf Baechle |
1da177e4c Linux-2.6.12-rc2 |
8 9 |
* Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ |
02416dcf5 Redo RM9000 worka... |
10 |
#include <linux/cache.h> |
431dc8040 [MIPS] Fix sigset... |
11 |
#include <linux/compat.h> |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 |
#include <linux/sched.h> #include <linux/mm.h> #include <linux/smp.h> |
1da177e4c 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 Linux-2.6.12-rc2 |
21 22 |
#include <linux/suspend.h> #include <linux/compiler.h> |
faea62346 [MIPS] Retry {sav... |
23 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
24 |
|
e50c0a8fa Support the MIPS3... |
25 |
#include <asm/abi.h> |
1da177e4c Linux-2.6.12-rc2 |
26 |
#include <asm/asm.h> |
431dc8040 [MIPS] Fix sigset... |
27 |
#include <asm/compat-signal.h> |
1da177e4c Linux-2.6.12-rc2 |
28 29 30 |
#include <linux/bitops.h> #include <asm/cacheflush.h> #include <asm/sim.h> |
1da177e4c Linux-2.6.12-rc2 |
31 32 33 |
#include <asm/ucontext.h> #include <asm/system.h> #include <asm/fpu.h> |
02416dcf5 Redo RM9000 worka... |
34 |
#include <asm/war.h> |
d814c28ce MIPS: Move signal... |
35 |
#include <asm/vdso.h> |
1da177e4c Linux-2.6.12-rc2 |
36 |
|
36a1f2c24 [MIPS] signal32: ... |
37 |
#include "signal-common.h" |
137f6f3e2 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 Linux-2.6.12-rc2 |
46 47 48 |
/* * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... */ |
151fd6acd [MIPS] signals: S... |
49 |
#define __NR_O32_restart_syscall 4253 |
1da177e4c Linux-2.6.12-rc2 |
50 |
|
1da177e4c Linux-2.6.12-rc2 |
51 |
/* 32-bit compatibility types */ |
1da177e4c 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 [MIPS] sigset_32 ... |
73 |
compat_sigset_t uc_sigmask; /* mask last for extensibility */ |
1da177e4c Linux-2.6.12-rc2 |
74 |
}; |
dd02f06aa [MIPS] signal: Fi... |
75 76 |
struct sigframe32 { u32 sf_ass[4]; /* argument save space for o32 */ |
d814c28ce MIPS: Move signal... |
77 |
u32 sf_pad[2]; /* Was: signal trampoline */ |
dd02f06aa [MIPS] signal: Fi... |
78 |
struct sigcontext32 sf_sc; |
755f21bb8 [MIPS] Fix sigset... |
79 |
compat_sigset_t sf_mask; |
dd02f06aa [MIPS] signal: Fi... |
80 |
}; |
c0b9bae9d [MIPS] signal: cl... |
81 82 |
struct rt_sigframe32 { u32 rs_ass[4]; /* argument save space for o32 */ |
d814c28ce MIPS: Move signal... |
83 |
u32 rs_pad[2]; /* Was: signal trampoline */ |
c0b9bae9d [MIPS] signal: cl... |
84 85 86 |
compat_siginfo_t rs_info; struct ucontext32 rs_uc; }; |
9432a9ba9 [MIPS] signal32: ... |
87 88 89 |
/* * sigcontext handlers */ |
faea62346 [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 MIPS: Fix GCC-4.6... |
112 |
int err, tmp __maybe_unused; |
faea62346 [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 [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 [MIPS] FPU owners... |
134 |
u32 used_math; |
9432a9ba9 [MIPS] signal32: ... |
135 136 |
err |= __put_user(regs->cp0_epc, &sc->sc_pc); |
9432a9ba9 [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 [MIPS] FPU owners... |
153 154 |
used_math = !!used_math(); err |= __put_user(used_math, &sc->sc_used_math); |
9432a9ba9 [MIPS] signal32: ... |
155 |
|
53dc80287 [MIPS] FPU owners... |
156 |
if (used_math) { |
9432a9ba9 [MIPS] signal32: ... |
157 158 159 160 |
/* * Save FPU state to signal context. Signal handler * will "inherit" current FPU state. */ |
faea62346 [MIPS] Retry {sav... |
161 |
err |= protected_save_fp_context32(sc); |
9432a9ba9 [MIPS] signal32: ... |
162 163 164 |
} return err; } |
c6a2f4679 [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 [MIPS] Retry {sav... |
173 |
err |= protected_restore_fp_context32(sc); |
c6a2f4679 [MIPS] Check FCSR... |
174 175 |
return err ?: sig; } |
9432a9ba9 [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 [MIPS] FPU owners... |
205 |
if (used_math) { |
9432a9ba9 [MIPS] signal32: ... |
206 |
/* restore fpu context if we have used it before */ |
c6a2f4679 [MIPS] Check FCSR... |
207 208 |
if (!err) err = check_and_restore_fp_context32(sc); |
9432a9ba9 [MIPS] signal32: ... |
209 210 |
} else { /* signal handler may have used FPU. Give it up. */ |
53dc80287 [MIPS] FPU owners... |
211 |
lose_fpu(0); |
9432a9ba9 [MIPS] signal32: ... |
212 |
} |
9432a9ba9 [MIPS] signal32: ... |
213 214 215 216 217 218 |
return err; } /* * */ |
1da177e4c Linux-2.6.12-rc2 |
219 220 |
extern void __put_sigset_unknown_nsig(void); extern void __get_sigset_unknown_nsig(void); |
9bbf28a36 [MIPS] Sparse: Ad... |
221 |
static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf) |
1da177e4c 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 [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 Linux-2.6.12-rc2 |
234 |
case 1: |
49a89efbb [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 Linux-2.6.12-rc2 |
237 238 239 240 |
} return err; } |
9c6031cc9 [MIPS] Signal cle... |
241 |
static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf) |
1da177e4c 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 [MIPS] Fix "no sp... |
253 254 |
err |= __get_user(sig[3], &ubuf->sig[3]); err |= __get_user(sig[2], &ubuf->sig[2]); |
1da177e4c Linux-2.6.12-rc2 |
255 256 |
kbuf->sig[1] = sig[2] | (sig[3] << 32); case 1: |
49a89efbb [MIPS] Fix "no sp... |
257 258 |
err |= __get_user(sig[1], &ubuf->sig[1]); err |= __get_user(sig[0], &ubuf->sig[0]); |
1da177e4c 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 [MIPS] signal: do... |
268 |
asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) |
1da177e4c Linux-2.6.12-rc2 |
269 |
{ |
9c6031cc9 [MIPS] Signal cle... |
270 |
compat_sigset_t __user *uset; |
68fa383f3 [MIPS] Add suppor... |
271 |
sigset_t newset; |
1da177e4c Linux-2.6.12-rc2 |
272 |
|
9c6031cc9 [MIPS] Signal cle... |
273 |
uset = (compat_sigset_t __user *) regs.regs[4]; |
1da177e4c Linux-2.6.12-rc2 |
274 275 276 277 278 |
if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); |
68fa383f3 [MIPS] Add suppor... |
279 |
current->saved_sigmask = current->blocked; |
1da177e4c Linux-2.6.12-rc2 |
280 281 282 |
current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); |
68fa383f3 [MIPS] Add suppor... |
283 284 285 286 |
current->state = TASK_INTERRUPTIBLE; schedule(); set_thread_flag(TIF_RESTORE_SIGMASK); return -ERESTARTNOHAND; |
1da177e4c Linux-2.6.12-rc2 |
287 |
} |
f90080a05 [MIPS] signal: do... |
288 |
asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) |
1da177e4c Linux-2.6.12-rc2 |
289 |
{ |
9c6031cc9 [MIPS] Signal cle... |
290 |
compat_sigset_t __user *uset; |
68fa383f3 [MIPS] Add suppor... |
291 |
sigset_t newset; |
304416da8 [MIPS] Reformat _... |
292 |
size_t sigsetsize; |
1da177e4c 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 [MIPS] Signal cle... |
298 |
uset = (compat_sigset_t __user *) regs.regs[4]; |
1da177e4c Linux-2.6.12-rc2 |
299 300 301 302 303 |
if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); |
68fa383f3 [MIPS] Add suppor... |
304 |
current->saved_sigmask = current->blocked; |
1da177e4c Linux-2.6.12-rc2 |
305 |
current->blocked = newset; |
6254944fa [MIPS] Reformat a... |
306 |
recalc_sigpending(); |
1da177e4c Linux-2.6.12-rc2 |
307 |
spin_unlock_irq(¤t->sighand->siglock); |
68fa383f3 [MIPS] Add suppor... |
308 309 310 311 |
current->state = TASK_INTERRUPTIBLE; schedule(); set_thread_flag(TIF_RESTORE_SIGMASK); return -ERESTARTNOHAND; |
1da177e4c Linux-2.6.12-rc2 |
312 |
} |
dbda6ac08 MIPS: CVE-2009-00... |
313 314 |
SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act, struct sigaction32 __user *, oact) |
1da177e4c 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 Gcc 4.0 fixes. |
322 |
s32 handler; |
1da177e4c Linux-2.6.12-rc2 |
323 324 325 |
if (!access_ok(VERIFY_READ, act, sizeof(*act))) return -EFAULT; |
77c728c22 Gcc 4.0 fixes. |
326 |
err |= __get_user(handler, &act->sa_handler); |
9bbf28a36 [MIPS] Sparse: Ad... |
327 |
new_ka.sa.sa_handler = (void __user *)(s64)handler; |
1da177e4c 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 [MIPS] Reformat a... |
340 |
return -EFAULT; |
1da177e4c 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 [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 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 [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 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 [MIPS] Signal cle... |
369 |
kss.ss_sp = (void __user *) (long) sp; |
1da177e4c 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 [MIPS] Fix "no sp... |
375 |
set_fs(KERNEL_DS); |
9bbf28a36 [MIPS] Sparse: Ad... |
376 377 |
ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL, uoss ? (stack_t __user *)&koss : NULL, usp); |
49a89efbb [MIPS] Fix "no sp... |
378 |
set_fs(old_fs); |
1da177e4c Linux-2.6.12-rc2 |
379 380 381 382 |
if (!ret && uoss) { if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) return -EFAULT; |
9c6031cc9 [MIPS] Signal cle... |
383 |
sp = (int) (unsigned long) koss.ss_sp; |
1da177e4c 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 [MIPS] Sparse: Ad... |
392 |
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) |
1da177e4c 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 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 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 [MIPS] Fix minor ... |
427 |
err |= __put_user((unsigned long)from->si_addr, &to->si_addr); |
1da177e4c 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 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 [MIPS] signal: do... |
454 |
asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) |
1da177e4c Linux-2.6.12-rc2 |
455 |
{ |
dd02f06aa [MIPS] signal: Fi... |
456 |
struct sigframe32 __user *frame; |
1da177e4c Linux-2.6.12-rc2 |
457 |
sigset_t blocked; |
c6a2f4679 [MIPS] Check FCSR... |
458 |
int sig; |
1da177e4c Linux-2.6.12-rc2 |
459 |
|
dd02f06aa [MIPS] signal: Fi... |
460 |
frame = (struct sigframe32 __user *) regs.regs[29]; |
1da177e4c Linux-2.6.12-rc2 |
461 462 |
if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; |
431dc8040 [MIPS] Fix sigset... |
463 |
if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask)) |
1da177e4c Linux-2.6.12-rc2 |
464 465 466 467 468 469 470 |
goto badframe; sigdelsetmask(&blocked, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = blocked; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); |
c6a2f4679 [MIPS] Check FCSR... |
471 472 |
sig = restore_sigcontext32(®s, &frame->sf_sc); if (sig < 0) |
1da177e4c Linux-2.6.12-rc2 |
473 |
goto badframe; |
c6a2f4679 [MIPS] Check FCSR... |
474 475 |
else if (sig) force_sig(sig, current); |
1da177e4c Linux-2.6.12-rc2 |
476 477 478 479 |
/* * Don't let your children do this ... */ |
1da177e4c 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" (®s)); /* Unreached */ badframe: force_sig(SIGSEGV, current); } |
f90080a05 [MIPS] signal: do... |
491 |
asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) |
1da177e4c Linux-2.6.12-rc2 |
492 |
{ |
9bbf28a36 [MIPS] Sparse: Ad... |
493 |
struct rt_sigframe32 __user *frame; |
1fcf1cc74 We pass a kernel ... |
494 |
mm_segment_t old_fs; |
1da177e4c Linux-2.6.12-rc2 |
495 496 497 |
sigset_t set; stack_t st; s32 sp; |
c6a2f4679 [MIPS] Check FCSR... |
498 |
int sig; |
1da177e4c Linux-2.6.12-rc2 |
499 |
|
9bbf28a36 [MIPS] Sparse: Ad... |
500 |
frame = (struct rt_sigframe32 __user *) regs.regs[29]; |
1da177e4c Linux-2.6.12-rc2 |
501 502 |
if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; |
431dc8040 [MIPS] Fix sigset... |
503 |
if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) |
1da177e4c Linux-2.6.12-rc2 |
504 505 506 507 508 509 510 |
goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); |
c6a2f4679 [MIPS] Check FCSR... |
511 512 |
sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); if (sig < 0) |
1da177e4c Linux-2.6.12-rc2 |
513 |
goto badframe; |
c6a2f4679 [MIPS] Check FCSR... |
514 515 |
else if (sig) force_sig(sig, current); |
1da177e4c 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 [MIPS] Signal cle... |
520 |
st.ss_sp = (void __user *)(long) sp; |
1da177e4c 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 We pass a kernel ... |
528 |
old_fs = get_fs(); |
49a89efbb [MIPS] Fix "no sp... |
529 |
set_fs(KERNEL_DS); |
9bbf28a36 [MIPS] Sparse: Ad... |
530 |
do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); |
49a89efbb [MIPS] Fix "no sp... |
531 |
set_fs(old_fs); |
1da177e4c 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" (®s)); /* Unreached */ badframe: force_sig(SIGSEGV, current); } |
d814c28ce 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 Linux-2.6.12-rc2 |
549 |
{ |
dd02f06aa [MIPS] signal: Fi... |
550 |
struct sigframe32 __user *frame; |
1da177e4c 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 Linux-2.6.12-rc2 |
556 |
err |= setup_sigcontext32(regs, &frame->sf_sc); |
431dc8040 [MIPS] Fix sigset... |
557 |
err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); |
1da177e4c 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 MIPS: Move signal... |
575 |
regs->regs[31] = (unsigned long) sig_return; |
1da177e4c Linux-2.6.12-rc2 |
576 |
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; |
722bb63de [MIPS] signal: fa... |
577 578 |
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx ", |
1da177e4c Linux-2.6.12-rc2 |
579 |
current->comm, current->pid, |
722bb63de [MIPS] signal: fa... |
580 |
frame, regs->cp0_epc, regs->regs[31]); |
7b3e2fc84 [MIPS] Add suppor... |
581 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
582 583 584 |
give_sigsegv: force_sigsegv(signr, current); |
7b3e2fc84 [MIPS] Add suppor... |
585 |
return -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
586 |
} |
d814c28ce 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 Linux-2.6.12-rc2 |
590 |
{ |
9bbf28a36 [MIPS] Sparse: Ad... |
591 |
struct rt_sigframe32 __user *frame; |
1da177e4c 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 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 [MIPS] Fix sigset... |
612 |
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); |
1da177e4c 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 MIPS: Move signal... |
631 |
regs->regs[31] = (unsigned long) sig_return; |
1da177e4c Linux-2.6.12-rc2 |
632 |
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; |
722bb63de [MIPS] signal: fa... |
633 634 |
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx ", |
1da177e4c Linux-2.6.12-rc2 |
635 |
current->comm, current->pid, |
722bb63de [MIPS] signal: fa... |
636 |
frame, regs->cp0_epc, regs->regs[31]); |
7b3e2fc84 [MIPS] Add suppor... |
637 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
638 639 640 |
give_sigsegv: force_sigsegv(signr, current); |
7b3e2fc84 [MIPS] Add suppor... |
641 |
return -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
642 |
} |
151fd6acd [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 MIPS: Move signal... |
648 649 |
.signal_return_offset = offsetof(struct mips_vdso, o32_signal_trampoline), |
151fd6acd [MIPS] signals: S... |
650 |
.setup_rt_frame = setup_rt_frame_32, |
d814c28ce MIPS: Move signal... |
651 652 |
.rt_signal_return_offset = offsetof(struct mips_vdso, o32_rt_signal_trampoline), |
151fd6acd [MIPS] signals: S... |
653 654 |
.restart = __NR_O32_restart_syscall }; |
1da177e4c Linux-2.6.12-rc2 |
655 |
|
dbda6ac08 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 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 Gcc 4.0 fixes. |
668 |
s32 handler; |
1da177e4c Linux-2.6.12-rc2 |
669 670 671 672 |
int err = 0; if (!access_ok(VERIFY_READ, act, sizeof(*act))) return -EFAULT; |
77c728c22 Gcc 4.0 fixes. |
673 |
err |= __get_user(handler, &act->sa_handler); |
9bbf28a36 [MIPS] Sparse: Ad... |
674 |
new_sa.sa.sa_handler = (void __user *)(s64)handler; |
1da177e4c 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 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 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 [MIPS] Fix "no sp... |
708 |
set_fs(KERNEL_DS); |
9bbf28a36 [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 [MIPS] Fix "no sp... |
712 |
set_fs(old_fs); |
1da177e4c Linux-2.6.12-rc2 |
713 714 715 716 717 718 |
if (!ret && oset && put_sigset(&old_set, oset)) return -EFAULT; return ret; } |
dbda6ac08 MIPS: CVE-2009-00... |
719 720 |
SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset, unsigned int, sigsetsize) |
1da177e4c Linux-2.6.12-rc2 |
721 722 723 724 |
{ int ret; sigset_t set; mm_segment_t old_fs = get_fs(); |
49a89efbb [MIPS] Fix "no sp... |
725 |
set_fs(KERNEL_DS); |
9bbf28a36 [MIPS] Sparse: Ad... |
726 |
ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize); |
49a89efbb [MIPS] Fix "no sp... |
727 |
set_fs(old_fs); |
1da177e4c Linux-2.6.12-rc2 |
728 729 730 731 732 733 |
if (!ret && put_sigset(&set, uset)) return -EFAULT; return ret; } |
dbda6ac08 MIPS: CVE-2009-00... |
734 735 |
SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig, compat_siginfo_t __user *, uinfo) |
1da177e4c Linux-2.6.12-rc2 |
736 737 738 739 |
{ siginfo_t info; int ret; mm_segment_t old_fs = get_fs(); |
49a89efbb [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 Linux-2.6.12-rc2 |
742 |
return -EFAULT; |
49a89efbb [MIPS] Fix "no sp... |
743 |
set_fs(KERNEL_DS); |
9bbf28a36 [MIPS] Sparse: Ad... |
744 |
ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info); |
49a89efbb [MIPS] Fix "no sp... |
745 |
set_fs(old_fs); |
1da177e4c Linux-2.6.12-rc2 |
746 747 |
return ret; } |
54f2da755 Implement 32-bit ... |
748 |
|
dbda6ac08 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 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 [MIPS] Fix "no sp... |
759 |
set_fs(KERNEL_DS); |
54f2da755 Implement 32-bit ... |
760 761 |
ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options, uru ? (struct rusage __user *) &ru : NULL); |
49a89efbb [MIPS] Fix "no sp... |
762 |
set_fs(old_fs); |
54f2da755 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 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); |