diff options
Diffstat (limited to 'arch/x86/kernel/signal_64.c')
-rw-r--r-- | arch/x86/kernel/signal_64.c | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index b45ef8ddd651..87a9c2f28d99 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
@@ -19,9 +19,10 @@ | |||
19 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
20 | #include <linux/personality.h> | 20 | #include <linux/personality.h> |
21 | #include <linux/compiler.h> | 21 | #include <linux/compiler.h> |
22 | #include <linux/uaccess.h> | ||
23 | |||
22 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
23 | #include <asm/ucontext.h> | 25 | #include <asm/ucontext.h> |
24 | #include <asm/uaccess.h> | ||
25 | #include <asm/i387.h> | 26 | #include <asm/i387.h> |
26 | #include <asm/proto.h> | 27 | #include <asm/proto.h> |
27 | #include <asm/ia32_unistd.h> | 28 | #include <asm/ia32_unistd.h> |
@@ -41,11 +42,6 @@ | |||
41 | # define FIX_EFLAGS __FIX_EFLAGS | 42 | # define FIX_EFLAGS __FIX_EFLAGS |
42 | #endif | 43 | #endif |
43 | 44 | ||
44 | int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | ||
45 | sigset_t *set, struct pt_regs * regs); | ||
46 | int ia32_setup_frame(int sig, struct k_sigaction *ka, | ||
47 | sigset_t *set, struct pt_regs * regs); | ||
48 | |||
49 | asmlinkage long | 45 | asmlinkage long |
50 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 46 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
51 | struct pt_regs *regs) | 47 | struct pt_regs *regs) |
@@ -119,7 +115,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
119 | /* Always make any pending restarted system calls return -EINTR */ | 115 | /* Always make any pending restarted system calls return -EINTR */ |
120 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 116 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
121 | 117 | ||
122 | #define COPY(x) err |= __get_user(regs->x, &sc->x) | 118 | #define COPY(x) (err |= __get_user(regs->x, &sc->x)) |
123 | 119 | ||
124 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); | 120 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
125 | COPY(dx); COPY(cx); COPY(ip); | 121 | COPY(dx); COPY(cx); COPY(ip); |
@@ -149,7 +145,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
149 | } | 145 | } |
150 | 146 | ||
151 | { | 147 | { |
152 | struct _fpstate __user * buf; | 148 | struct _fpstate __user *buf; |
153 | err |= __get_user(buf, &sc->fpstate); | 149 | err |= __get_user(buf, &sc->fpstate); |
154 | 150 | ||
155 | if (buf) { | 151 | if (buf) { |
@@ -189,7 +185,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
189 | current->blocked = set; | 185 | current->blocked = set; |
190 | recalc_sigpending(); | 186 | recalc_sigpending(); |
191 | spin_unlock_irq(¤t->sighand->siglock); | 187 | spin_unlock_irq(¤t->sighand->siglock); |
192 | 188 | ||
193 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) | 189 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) |
194 | goto badframe; | 190 | goto badframe; |
195 | 191 | ||
@@ -199,16 +195,17 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
199 | return ax; | 195 | return ax; |
200 | 196 | ||
201 | badframe: | 197 | badframe: |
202 | signal_fault(regs,frame,"sigreturn"); | 198 | signal_fault(regs, frame, "sigreturn"); |
203 | return 0; | 199 | return 0; |
204 | } | 200 | } |
205 | 201 | ||
206 | /* | 202 | /* |
207 | * Set up a signal frame. | 203 | * Set up a signal frame. |
208 | */ | 204 | */ |
209 | 205 | ||
210 | static inline int | 206 | static inline int |
211 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) | 207 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, |
208 | unsigned long mask, struct task_struct *me) | ||
212 | { | 209 | { |
213 | int err = 0; | 210 | int err = 0; |
214 | 211 | ||
@@ -264,35 +261,35 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) | |||
264 | } | 261 | } |
265 | 262 | ||
266 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 263 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
267 | sigset_t *set, struct pt_regs * regs) | 264 | sigset_t *set, struct pt_regs *regs) |
268 | { | 265 | { |
269 | struct rt_sigframe __user *frame; | 266 | struct rt_sigframe __user *frame; |
270 | struct _fpstate __user *fp = NULL; | 267 | struct _fpstate __user *fp = NULL; |
271 | int err = 0; | 268 | int err = 0; |
272 | struct task_struct *me = current; | 269 | struct task_struct *me = current; |
273 | 270 | ||
274 | if (used_math()) { | 271 | if (used_math()) { |
275 | fp = get_stack(ka, regs, sizeof(struct _fpstate)); | 272 | fp = get_stack(ka, regs, sizeof(struct _fpstate)); |
276 | frame = (void __user *)round_down( | 273 | frame = (void __user *)round_down( |
277 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; | 274 | (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; |
278 | 275 | ||
279 | if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) | 276 | if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) |
280 | goto give_sigsegv; | 277 | goto give_sigsegv; |
281 | 278 | ||
282 | if (save_i387(fp) < 0) | 279 | if (save_i387(fp) < 0) |
283 | err |= -1; | 280 | err |= -1; |
284 | } else | 281 | } else |
285 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; | 282 | frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; |
286 | 283 | ||
287 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 284 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
288 | goto give_sigsegv; | 285 | goto give_sigsegv; |
289 | 286 | ||
290 | if (ka->sa.sa_flags & SA_SIGINFO) { | 287 | if (ka->sa.sa_flags & SA_SIGINFO) { |
291 | err |= copy_siginfo_to_user(&frame->info, info); | 288 | err |= copy_siginfo_to_user(&frame->info, info); |
292 | if (err) | 289 | if (err) |
293 | goto give_sigsegv; | 290 | goto give_sigsegv; |
294 | } | 291 | } |
295 | 292 | ||
296 | /* Create the ucontext. */ | 293 | /* Create the ucontext. */ |
297 | err |= __put_user(0, &frame->uc.uc_flags); | 294 | err |= __put_user(0, &frame->uc.uc_flags); |
298 | err |= __put_user(0, &frame->uc.uc_link); | 295 | err |= __put_user(0, &frame->uc.uc_link); |
@@ -302,9 +299,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
302 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | 299 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); |
303 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); | 300 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); |
304 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); | 301 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); |
305 | if (sizeof(*set) == 16) { | 302 | if (sizeof(*set) == 16) { |
306 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | 303 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); |
307 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); | 304 | __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); |
308 | } else | 305 | } else |
309 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 306 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
310 | 307 | ||
@@ -315,7 +312,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
315 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 312 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
316 | } else { | 313 | } else { |
317 | /* could use a vstub here */ | 314 | /* could use a vstub here */ |
318 | goto give_sigsegv; | 315 | goto give_sigsegv; |
319 | } | 316 | } |
320 | 317 | ||
321 | if (err) | 318 | if (err) |
@@ -323,7 +320,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
323 | 320 | ||
324 | /* Set up registers for signal handler */ | 321 | /* Set up registers for signal handler */ |
325 | regs->di = sig; | 322 | regs->di = sig; |
326 | /* In case the signal handler was declared without prototypes */ | 323 | /* In case the signal handler was declared without prototypes */ |
327 | regs->ax = 0; | 324 | regs->ax = 0; |
328 | 325 | ||
329 | /* This also works for non SA_SIGINFO handlers because they expect the | 326 | /* This also works for non SA_SIGINFO handlers because they expect the |
@@ -376,7 +373,7 @@ static long current_syscall_ret(struct pt_regs *regs) | |||
376 | 373 | ||
377 | /* | 374 | /* |
378 | * OK, we're invoking a handler | 375 | * OK, we're invoking a handler |
379 | */ | 376 | */ |
380 | 377 | ||
381 | static int | 378 | static int |
382 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 379 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
@@ -420,7 +417,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
420 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); | 417 | ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs); |
421 | else | 418 | else |
422 | ret = ia32_setup_frame(sig, ka, oldset, regs); | 419 | ret = ia32_setup_frame(sig, ka, oldset, regs); |
423 | } else | 420 | } else |
424 | #endif | 421 | #endif |
425 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 422 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
426 | 423 | ||
@@ -448,9 +445,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
448 | ptrace_notify(SIGTRAP); | 445 | ptrace_notify(SIGTRAP); |
449 | 446 | ||
450 | spin_lock_irq(¤t->sighand->siglock); | 447 | spin_lock_irq(¤t->sighand->siglock); |
451 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 448 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
452 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 449 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
453 | sigaddset(¤t->blocked,sig); | 450 | sigaddset(¤t->blocked, sig); |
454 | recalc_sigpending(); | 451 | recalc_sigpending(); |
455 | spin_unlock_irq(¤t->sighand->siglock); | 452 | spin_unlock_irq(¤t->sighand->siglock); |
456 | } | 453 | } |
@@ -552,14 +549,15 @@ void do_notify_resume(struct pt_regs *regs, void *unused, | |||
552 | } | 549 | } |
553 | 550 | ||
554 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | 551 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) |
555 | { | 552 | { |
556 | struct task_struct *me = current; | 553 | struct task_struct *me = current; |
557 | if (show_unhandled_signals && printk_ratelimit()) { | 554 | if (show_unhandled_signals && printk_ratelimit()) { |
558 | printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", | 555 | printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", |
559 | me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); | 556 | me->comm, me->pid, where, frame, regs->ip, |
557 | regs->sp, regs->orig_ax); | ||
560 | print_vma_addr(" in ", regs->ip); | 558 | print_vma_addr(" in ", regs->ip); |
561 | printk("\n"); | 559 | printk("\n"); |
562 | } | 560 | } |
563 | 561 | ||
564 | force_sig(SIGSEGV, me); | 562 | force_sig(SIGSEGV, me); |
565 | } | 563 | } |