#define PTRACE_SEIZE           0x4206
 #define PTRACE_INTERRUPT       0x4207
+#define PTRACE_LISTEN          0x4208
 
 /* flags in @data for PTRACE_SEIZE */
 #define PTRACE_SEIZE_DEVEL     0x80000000 /* temp flag for development */
 
 #define JOBCTL_TRAP_STOP_BIT   19      /* trap for STOP */
 #define JOBCTL_TRAP_NOTIFY_BIT 20      /* trap for NOTIFY */
 #define JOBCTL_TRAPPING_BIT    21      /* switching to TRACED */
+#define JOBCTL_LISTENING_BIT   22      /* ptracer is listening for events */
 
 #define JOBCTL_STOP_DEQUEUED   (1 << JOBCTL_STOP_DEQUEUED_BIT)
 #define JOBCTL_STOP_PENDING    (1 << JOBCTL_STOP_PENDING_BIT)
 #define JOBCTL_TRAP_STOP       (1 << JOBCTL_TRAP_STOP_BIT)
 #define JOBCTL_TRAP_NOTIFY     (1 << JOBCTL_TRAP_NOTIFY_BIT)
 #define JOBCTL_TRAPPING                (1 << JOBCTL_TRAPPING_BIT)
+#define JOBCTL_LISTENING       (1 << JOBCTL_LISTENING_BIT)
 
 #define JOBCTL_TRAP_MASK       (JOBCTL_TRAP_STOP | JOBCTL_TRAP_NOTIFY)
 #define JOBCTL_PENDING_MASK    (JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK)
 
 static int *task_stopped_code(struct task_struct *p, bool ptrace)
 {
        if (ptrace) {
-               if (task_is_stopped_or_traced(p))
+               if (task_is_stopped_or_traced(p) &&
+                   !(p->jobctl & JOBCTL_LISTENING))
                        return &p->exit_code;
        } else {
                if (p->signal->flags & SIGNAL_STOP_STOPPED)
 
                 */
                spin_lock_irq(&child->sighand->siglock);
                WARN_ON_ONCE(task_is_stopped(child));
-               if (task_is_traced(child) || ignore_state)
+               if (ignore_state || (task_is_traced(child) &&
+                                    !(child->jobctl & JOBCTL_LISTENING)))
                        ret = 0;
                spin_unlock_irq(&child->sighand->siglock);
        }
 {
        bool seized = child->ptrace & PT_SEIZED;
        int ret = -EIO;
-       siginfo_t siginfo;
+       siginfo_t siginfo, *si;
        void __user *datavp = (void __user *) data;
        unsigned long __user *datalp = datavp;
        unsigned long flags;
                if (unlikely(!seized || !lock_task_sighand(child, &flags)))
                        break;
 
+               /*
+                * INTERRUPT doesn't disturb existing trap sans one
+                * exception.  If ptracer issued LISTEN for the current
+                * STOP, this INTERRUPT should clear LISTEN and re-trap
+                * tracee into STOP.
+                */
                if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP)))
-                       signal_wake_up(child, 0);
+                       signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
+
+               unlock_task_sighand(child, &flags);
+               ret = 0;
+               break;
+
+       case PTRACE_LISTEN:
+               /*
+                * Listen for events.  Tracee must be in STOP.  It's not
+                * resumed per-se but is not considered to be in TRACED by
+                * wait(2) or ptrace(2).  If an async event (e.g. group
+                * stop state change) happens, tracee will enter STOP trap
+                * again.  Alternatively, ptracer can issue INTERRUPT to
+                * finish listening and re-trap tracee into STOP.
+                */
+               if (unlikely(!seized || !lock_task_sighand(child, &flags)))
+                       break;
+
+               si = child->last_siginfo;
+               if (unlikely(!si || si->si_code >> 8 != PTRACE_EVENT_STOP))
+                       break;
+
+               child->jobctl |= JOBCTL_LISTENING;
+
+               /*
+                * If NOTIFY is set, it means event happened between start
+                * of this trap and now.  Trigger re-trap immediately.
+                */
+               if (child->jobctl & JOBCTL_TRAP_NOTIFY)
+                       signal_wake_up(child, true);
 
                unlock_task_sighand(child, &flags);
                ret = 0;
 
  * TRAP_STOP to notify ptracer of an event.  @t must have been seized by
  * ptracer.
  *
- * If @t is running, STOP trap will be taken.  If already trapped, STOP
- * trap will be eventually taken without returning to userland after the
- * existing traps are finished by PTRACE_CONT.
+ * If @t is running, STOP trap will be taken.  If trapped for STOP and
+ * ptracer is listening for events, tracee is woken up so that it can
+ * re-trap for the new event.  If trapped otherwise, STOP trap will be
+ * eventually taken without returning to userland after the existing traps
+ * are finished by PTRACE_CONT.
  *
  * CONTEXT:
  * Must be called with @task->sighand->siglock held.
        assert_spin_locked(&t->sighand->siglock);
 
        task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY);
-       signal_wake_up(t, 0);
+       signal_wake_up(t, t->jobctl & JOBCTL_LISTENING);
 }
 
 /*
        spin_lock_irq(¤t->sighand->siglock);
        current->last_siginfo = NULL;
 
+       /* LISTENING can be set only during STOP traps, clear it */
+       current->jobctl &= ~JOBCTL_LISTENING;
+
        /*
         * Queued signals ignored us while we were stopped for tracing.
         * So check for any that we should take before resuming user mode.