)]}'
{
  "commit": "b4a1b4f5047e4f54e194681125c74c0aa64d637d",
  "tree": "69cbbd8ef1751be1e2015c593090d48f518f53df",
  "parents": [
    "73796d8bf27372e26c2b79881947304c14c2d353"
  ],
  "author": {
    "name": "David Howells",
    "email": "dhowells@redhat.com",
    "time": "Fri Dec 18 01:34:26 2015 +0000"
  },
  "committer": {
    "name": "James Morris",
    "email": "james.l.morris@oracle.com",
    "time": "Sat Dec 19 12:34:43 2015 +1100"
  },
  "message": "KEYS: Fix race between read and revoke\n\nThis fixes CVE-2015-7550.\n\nThere\u0027s a race between keyctl_read() and keyctl_revoke().  If the revoke\nhappens between keyctl_read() checking the validity of a key and the key\u0027s\nsemaphore being taken, then the key type read method will see a revoked key.\n\nThis causes a problem for the user-defined key type because it assumes in\nits read method that there will always be a payload in a non-revoked key\nand doesn\u0027t check for a NULL pointer.\n\nFix this by making keyctl_read() check the validity of a key after taking\nsemaphore instead of before.\n\nI think the bug was introduced with the original keyrings code.\n\nThis was discovered by a multithreaded test program generated by syzkaller\n(http://github.com/google/syzkaller).  Here\u0027s a cleaned up version:\n\n\t#include \u003csys/types.h\u003e\n\t#include \u003ckeyutils.h\u003e\n\t#include \u003cpthread.h\u003e\n\tvoid *thr0(void *arg)\n\t{\n\t\tkey_serial_t key \u003d (unsigned long)arg;\n\t\tkeyctl_revoke(key);\n\t\treturn 0;\n\t}\n\tvoid *thr1(void *arg)\n\t{\n\t\tkey_serial_t key \u003d (unsigned long)arg;\n\t\tchar buffer[16];\n\t\tkeyctl_read(key, buffer, 16);\n\t\treturn 0;\n\t}\n\tint main()\n\t{\n\t\tkey_serial_t key \u003d add_key(\"user\", \"%\", \"foo\", 3, KEY_SPEC_USER_KEYRING);\n\t\tpthread_t th[5];\n\t\tpthread_create(\u0026th[0], 0, thr0, (void *)(unsigned long)key);\n\t\tpthread_create(\u0026th[1], 0, thr1, (void *)(unsigned long)key);\n\t\tpthread_create(\u0026th[2], 0, thr0, (void *)(unsigned long)key);\n\t\tpthread_create(\u0026th[3], 0, thr1, (void *)(unsigned long)key);\n\t\tpthread_join(th[0], 0);\n\t\tpthread_join(th[1], 0);\n\t\tpthread_join(th[2], 0);\n\t\tpthread_join(th[3], 0);\n\t\treturn 0;\n\t}\n\nBuild as:\n\n\tcc -o keyctl-race keyctl-race.c -lkeyutils -lpthread\n\nRun as:\n\n\twhile keyctl-race; do :; done\n\nas it may need several iterations to crash the kernel.  The crash can be\nsummarised as:\n\n\tBUG: unable to handle kernel NULL pointer dereference at 0000000000000010\n\tIP: [\u003cffffffff81279b08\u003e] user_read+0x56/0xa3\n\t...\n\tCall Trace:\n\t [\u003cffffffff81276aa9\u003e] keyctl_read_key+0xb6/0xd7\n\t [\u003cffffffff81277815\u003e] SyS_keyctl+0x83/0xe0\n\t [\u003cffffffff815dbb97\u003e] entry_SYSCALL_64_fastpath+0x12/0x6f\n\nReported-by: Dmitry Vyukov \u003cdvyukov@google.com\u003e\nSigned-off-by: David Howells \u003cdhowells@redhat.com\u003e\nTested-by: Dmitry Vyukov \u003cdvyukov@google.com\u003e\nCc: stable@vger.kernel.org\nSigned-off-by: James Morris \u003cjames.l.morris@oracle.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "fb111eafcb893e4f5146c74a84f8499d4e1553c4",
      "old_mode": 33188,
      "old_path": "security/keys/keyctl.c",
      "new_id": "1c3872aeed14ace421a9d43fc396c43afdd5b93c",
      "new_mode": 33188,
      "new_path": "security/keys/keyctl.c"
    }
  ]
}
