)]}'
{
  "commit": "788e05a67c343fa22f2ae1d3ca264e7f15c25eaf",
  "tree": "4fa2f7e11cc757160ae5f492fdbe0da72d30cf26",
  "parents": [
    "829841146878e082613a49581ae252c071057c23"
  ],
  "author": {
    "name": "Oleg Nesterov",
    "email": "oleg@tv-sign.ru",
    "time": "Fri Oct 07 17:46:19 2005 +0400"
  },
  "committer": {
    "name": "Linus Torvalds",
    "email": "torvalds@g5.osdl.org",
    "time": "Sat Oct 08 14:53:31 2005 -0700"
  },
  "message": "[PATCH] fix do_coredump() vs SIGSTOP race\n\nLet\u0027s suppose we have 2 threads in thread group:\n\tA - does coredump\n\tB - has pending SIGSTOP\n\nthread A\t\t\t\t\t\tthread B\n\ndo_coredump:\t\t\t\t\t\tget_signal_to_deliver:\n\n  lock(-\u003esighand)\n  -\u003esignal-\u003eflags \u003d SIGNAL_GROUP_EXIT\n  unlock(-\u003esighand)\n\n\t\t\t\t\t\t\tlock(-\u003esighand)\n\t\t\t\t\t\t\tsignr \u003d dequeue_signal()\n\t\t\t\t\t\t\t\t-\u003esignal-\u003eflags |\u003d SIGNAL_STOP_DEQUEUED\n\t\t\t\t\t\t\t\treturn SIGSTOP;\n\n\t\t\t\t\t\t\tdo_signal_stop:\n\t\t\t\t\t\t\t    unlock(-\u003esighand)\n\n  coredump_wait:\n\n      zap_threads:\n          lock(tasklist_lock)\n          send SIGKILL to B\n              // signal_wake_up() does nothing\n          unlock(tasklist_lock)\n\n\t\t\t\t\t\t\t    lock(tasklist_lock)\n\t\t\t\t\t\t\t    lock(-\u003esighand)\n\t\t\t\t\t\t\t    re-check sig-\u003eflags \u0026 SIGNAL_STOP_DEQUEUED, yes\n\t\t\t\t\t\t\t    set_current_state(TASK_STOPPED);\n\t\t\t\t\t\t\t    finish_stop:\n\t\t\t\t\t\t\t        schedule();\n\t\t\t\t\t\t\t            // -\u003estate \u003d\u003d TASK_STOPPED\n\n      wait_for_completion(\u0026startup_done)\n         // waits for complete() from B,\n         // -\u003estate \u003d\u003d TASK_UNINTERRUPTIBLE\n\nWe can\u0027t wake up \u0027B\u0027 in any way:\n\n\tSIGCONT will be ignored because handle_stop_signal() sees\n\t-\u003esignal-\u003eflags \u0026 SIGNAL_GROUP_EXIT.\n\n\tsys_kill(SIGKILL)-\u003e__group_complete_signal() will choose\n\tuninterruptible \u0027A\u0027, so it can\u0027t help.\n\n\tsys_tkill(B, SIGKILL) will be ignored by specific_send_sig_info()\n\tbecause B already has pending SIGKILL.\n\nThis scenario is not possbile if \u0027A\u0027 does do_group_exit(), because\nit sets sig-\u003eflags \u003d SIGNAL_GROUP_EXIT and delivers SIGKILL to\nsubthreads atomically, holding both tasklist_lock and sighand-\u003elock.\nThat means that do_signal_stop() will notice !SIGNAL_STOP_DEQUEUED\nafter re-locking -\u003esighand. And it is not possible to any other\nthread to re-add SIGNAL_STOP_DEQUEUED later, because dequeue_signal()\ncan only return SIGKILL.\n\nI think it is better to change do_coredump() to do sigaddset(SIGKILL)\nand signal_wake_up() under sighand-\u003elock, but this patch is much\nsimpler.\n\nSigned-off-by: Oleg Nesterov \u003coleg@tv-sign.ru\u003e\nSigned-off-by: Linus Torvalds \u003ctorvalds@osdl.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "619b027e92b53ce02706a04f6e4524a6cc1135a8",
      "old_mode": 33188,
      "old_path": "kernel/signal.c",
      "new_id": "c135f5aa2c2d476df8655a67e869e5819b49d901",
      "new_mode": 33188,
      "new_path": "kernel/signal.c"
    }
  ]
}
