ptrace: PTRACE_LISTEN forgets to unlock ->siglock

If PTRACE_LISTEN fails after lock_task_sighand() it doesn't drop ->siglock.

Reported-by: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Oleg Nesterov and committed by Linus Torvalds f9d81f61 b172e38e

Changed files
+10 -13
kernel
+10 -13
kernel/ptrace.c
··· 744 744 break; 745 745 746 746 si = child->last_siginfo; 747 - if (unlikely(!si || si->si_code >> 8 != PTRACE_EVENT_STOP)) 748 - break; 749 - 750 - child->jobctl |= JOBCTL_LISTENING; 751 - 752 - /* 753 - * If NOTIFY is set, it means event happened between start 754 - * of this trap and now. Trigger re-trap immediately. 755 - */ 756 - if (child->jobctl & JOBCTL_TRAP_NOTIFY) 757 - signal_wake_up(child, true); 758 - 747 + if (likely(si && (si->si_code >> 8) == PTRACE_EVENT_STOP)) { 748 + child->jobctl |= JOBCTL_LISTENING; 749 + /* 750 + * If NOTIFY is set, it means event happened between 751 + * start of this trap and now. Trigger re-trap. 752 + */ 753 + if (child->jobctl & JOBCTL_TRAP_NOTIFY) 754 + signal_wake_up(child, true); 755 + ret = 0; 756 + } 759 757 unlock_task_sighand(child, &flags); 760 - ret = 0; 761 758 break; 762 759 763 760 case PTRACE_DETACH: /* detach a process that was attached. */