diff options
-rw-r--r-- | arch/x86/kernel/signal_32.c | 64 | ||||
-rw-r--r-- | arch/x86/kernel/signal_64.c | 47 |
2 files changed, 55 insertions, 56 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index a393e3711e08..182269b752da 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -131,14 +131,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax | |||
131 | COPY_SEG(fs); | 131 | COPY_SEG(fs); |
132 | COPY_SEG(es); | 132 | COPY_SEG(es); |
133 | COPY_SEG(ds); | 133 | COPY_SEG(ds); |
134 | COPY(di); | 134 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
135 | COPY(si); | 135 | COPY(dx); COPY(cx); COPY(ip); |
136 | COPY(bp); | ||
137 | COPY(sp); | ||
138 | COPY(bx); | ||
139 | COPY(dx); | ||
140 | COPY(cx); | ||
141 | COPY(ip); | ||
142 | COPY_SEG_STRICT(cs); | 136 | COPY_SEG_STRICT(cs); |
143 | COPY_SEG_STRICT(ss); | 137 | COPY_SEG_STRICT(ss); |
144 | 138 | ||
@@ -412,7 +406,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
412 | ptrace_notify(SIGTRAP); | 406 | ptrace_notify(SIGTRAP); |
413 | 407 | ||
414 | #if DEBUG_SIG | 408 | #if DEBUG_SIG |
415 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", | 409 | printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%p\n", |
416 | current->comm, current->pid, frame, regs->ip, frame->pretcode); | 410 | current->comm, current->pid, frame, regs->ip, frame->pretcode); |
417 | #endif | 411 | #endif |
418 | 412 | ||
@@ -522,7 +516,7 @@ give_sigsegv: | |||
522 | 516 | ||
523 | static int | 517 | static int |
524 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 518 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
525 | sigset_t *oldset, struct pt_regs * regs) | 519 | sigset_t *oldset, struct pt_regs *regs) |
526 | { | 520 | { |
527 | int ret; | 521 | int ret; |
528 | 522 | ||
@@ -530,20 +524,21 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
530 | if ((long)regs->orig_ax >= 0) { | 524 | if ((long)regs->orig_ax >= 0) { |
531 | /* If so, check system call restarting.. */ | 525 | /* If so, check system call restarting.. */ |
532 | switch (regs->ax) { | 526 | switch (regs->ax) { |
533 | case -ERESTART_RESTARTBLOCK: | 527 | case -ERESTART_RESTARTBLOCK: |
534 | case -ERESTARTNOHAND: | 528 | case -ERESTARTNOHAND: |
529 | regs->ax = -EINTR; | ||
530 | break; | ||
531 | |||
532 | case -ERESTARTSYS: | ||
533 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
535 | regs->ax = -EINTR; | 534 | regs->ax = -EINTR; |
536 | break; | 535 | break; |
537 | 536 | } | |
538 | case -ERESTARTSYS: | 537 | /* fallthrough */ |
539 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 538 | case -ERESTARTNOINTR: |
540 | regs->ax = -EINTR; | 539 | regs->ax = regs->orig_ax; |
541 | break; | 540 | regs->ip -= 2; |
542 | } | 541 | break; |
543 | /* fallthrough */ | ||
544 | case -ERESTARTNOINTR: | ||
545 | regs->ax = regs->orig_ax; | ||
546 | regs->ip -= 2; | ||
547 | } | 542 | } |
548 | } | 543 | } |
549 | 544 | ||
@@ -580,18 +575,17 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
580 | */ | 575 | */ |
581 | static void do_signal(struct pt_regs *regs) | 576 | static void do_signal(struct pt_regs *regs) |
582 | { | 577 | { |
578 | struct k_sigaction ka; | ||
583 | siginfo_t info; | 579 | siginfo_t info; |
584 | int signr; | 580 | int signr; |
585 | struct k_sigaction ka; | ||
586 | sigset_t *oldset; | 581 | sigset_t *oldset; |
587 | 582 | ||
588 | /* | 583 | /* |
589 | * We want the common case to go fast, which | 584 | * We want the common case to go fast, which is why we may in certain |
590 | * is why we may in certain cases get here from | 585 | * cases get here from kernel mode. Just return without doing anything |
591 | * kernel mode. Just return without doing anything | 586 | * if so. |
592 | * if so. vm86 regs switched out by assembly code | 587 | * X86_32: vm86 regs switched out by assembly code before reaching |
593 | * before reaching here, so testing against kernel | 588 | * here, so testing against kernel CS suffices. |
594 | * CS suffices. | ||
595 | */ | 589 | */ |
596 | if (!user_mode(regs)) | 590 | if (!user_mode(regs)) |
597 | return; | 591 | return; |
@@ -608,7 +602,7 @@ static void do_signal(struct pt_regs *regs) | |||
608 | * have been cleared if the watchpoint triggered | 602 | * have been cleared if the watchpoint triggered |
609 | * inside the kernel. | 603 | * inside the kernel. |
610 | */ | 604 | */ |
611 | if (unlikely(current->thread.debugreg7)) | 605 | if (current->thread.debugreg7) |
612 | set_debugreg(current->thread.debugreg7, 7); | 606 | set_debugreg(current->thread.debugreg7, 7); |
613 | 607 | ||
614 | /* Whee! Actually deliver the signal. */ | 608 | /* Whee! Actually deliver the signal. */ |
@@ -642,8 +636,10 @@ static void do_signal(struct pt_regs *regs) | |||
642 | } | 636 | } |
643 | } | 637 | } |
644 | 638 | ||
645 | /* if there's no signal to deliver, we just put the saved sigmask | 639 | /* |
646 | * back */ | 640 | * If there's no signal to deliver, we just put the saved sigmask |
641 | * back. | ||
642 | */ | ||
647 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 643 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { |
648 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 644 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
649 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 645 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
@@ -654,12 +650,12 @@ static void do_signal(struct pt_regs *regs) | |||
654 | * notification of userspace execution resumption | 650 | * notification of userspace execution resumption |
655 | * - triggered by the TIF_WORK_MASK flags | 651 | * - triggered by the TIF_WORK_MASK flags |
656 | */ | 652 | */ |
657 | void do_notify_resume(struct pt_regs *regs, void *_unused, | 653 | void do_notify_resume(struct pt_regs *regs, void *unused, |
658 | __u32 thread_info_flags) | 654 | __u32 thread_info_flags) |
659 | { | 655 | { |
660 | /* Pending single-step? */ | 656 | /* Pending single-step? */ |
661 | if (thread_info_flags & _TIF_SINGLESTEP) { | 657 | if (thread_info_flags & _TIF_SINGLESTEP) { |
662 | regs->flags |= TF_MASK; | 658 | regs->flags |= X86_EFLAGS_TF; |
663 | clear_thread_flag(TIF_SINGLESTEP); | 659 | clear_thread_flag(TIF_SINGLESTEP); |
664 | } | 660 | } |
665 | 661 | ||
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 1c83e5124c65..863cebe8e60a 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
@@ -345,7 +345,7 @@ static long current_syscall_ret(struct pt_regs *regs) | |||
345 | 345 | ||
346 | static int | 346 | static int |
347 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 347 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
348 | sigset_t *oldset, struct pt_regs *regs) | 348 | sigset_t *oldset, struct pt_regs *regs) |
349 | { | 349 | { |
350 | int ret; | 350 | int ret; |
351 | 351 | ||
@@ -359,21 +359,21 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
359 | if (current_syscall(regs) >= 0) { | 359 | if (current_syscall(regs) >= 0) { |
360 | /* If so, check system call restarting.. */ | 360 | /* If so, check system call restarting.. */ |
361 | switch (current_syscall_ret(regs)) { | 361 | switch (current_syscall_ret(regs)) { |
362 | case -ERESTART_RESTARTBLOCK: | 362 | case -ERESTART_RESTARTBLOCK: |
363 | case -ERESTARTNOHAND: | 363 | case -ERESTARTNOHAND: |
364 | regs->ax = -EINTR; | 364 | regs->ax = -EINTR; |
365 | break; | 365 | break; |
366 | 366 | ||
367 | case -ERESTARTSYS: | 367 | case -ERESTARTSYS: |
368 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 368 | if (!(ka->sa.sa_flags & SA_RESTART)) { |
369 | regs->ax = -EINTR; | 369 | regs->ax = -EINTR; |
370 | break; | ||
371 | } | ||
372 | /* fallthrough */ | ||
373 | case -ERESTARTNOINTR: | ||
374 | regs->ax = regs->orig_ax; | ||
375 | regs->ip -= 2; | ||
376 | break; | 370 | break; |
371 | } | ||
372 | /* fallthrough */ | ||
373 | case -ERESTARTNOINTR: | ||
374 | regs->ax = regs->orig_ax; | ||
375 | regs->ip -= 2; | ||
376 | break; | ||
377 | } | 377 | } |
378 | } | 378 | } |
379 | 379 | ||
@@ -420,10 +420,11 @@ static void do_signal(struct pt_regs *regs) | |||
420 | sigset_t *oldset; | 420 | sigset_t *oldset; |
421 | 421 | ||
422 | /* | 422 | /* |
423 | * We want the common case to go fast, which | 423 | * We want the common case to go fast, which is why we may in certain |
424 | * is why we may in certain cases get here from | 424 | * cases get here from kernel mode. Just return without doing anything |
425 | * kernel mode. Just return without doing anything | ||
426 | * if so. | 425 | * if so. |
426 | * X86_32: vm86 regs switched out by assembly code before reaching | ||
427 | * here, so testing against kernel CS suffices. | ||
427 | */ | 428 | */ |
428 | if (!user_mode(regs)) | 429 | if (!user_mode(regs)) |
429 | return; | 430 | return; |
@@ -473,16 +474,18 @@ static void do_signal(struct pt_regs *regs) | |||
473 | } | 474 | } |
474 | } | 475 | } |
475 | 476 | ||
476 | /* if there's no signal to deliver, we just put the saved sigmask | 477 | /* |
477 | back. */ | 478 | * If there's no signal to deliver, we just put the saved sigmask |
479 | * back. | ||
480 | */ | ||
478 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 481 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { |
479 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 482 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
480 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 483 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
481 | } | 484 | } |
482 | } | 485 | } |
483 | 486 | ||
484 | void | 487 | void do_notify_resume(struct pt_regs *regs, void *unused, |
485 | do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | 488 | __u32 thread_info_flags) |
486 | { | 489 | { |
487 | #ifdef DEBUG_SIG | 490 | #ifdef DEBUG_SIG |
488 | printk("do_notify_resume flags:%x ip:%lx sp:%lx caller:%p pending:%x\n", | 491 | printk("do_notify_resume flags:%x ip:%lx sp:%lx caller:%p pending:%x\n", |
@@ -502,7 +505,7 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | |||
502 | #endif /* CONFIG_X86_MCE */ | 505 | #endif /* CONFIG_X86_MCE */ |
503 | 506 | ||
504 | /* deal with pending signal delivery */ | 507 | /* deal with pending signal delivery */ |
505 | if (thread_info_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK)) | 508 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) |
506 | do_signal(regs); | 509 | do_signal(regs); |
507 | 510 | ||
508 | if (thread_info_flags & _TIF_HRTICK_RESCHED) | 511 | if (thread_info_flags & _TIF_HRTICK_RESCHED) |