)]}'
{
  "commit": "66aebce747eaf9bc456bf1f1b217d8db843031d0",
  "tree": "460c0268105191b2d581f42d5534dc952d565a17",
  "parents": [
    "f3ec434c69ac7f447ff6e6389c19727c9f002087"
  ],
  "author": {
    "name": "Chris Metcalf",
    "email": "cmetcalf@tilera.com",
    "time": "Thu Apr 12 12:49:15 2012 -0700"
  },
  "committer": {
    "name": "Linus Torvalds",
    "email": "torvalds@linux-foundation.org",
    "time": "Thu Apr 12 13:12:12 2012 -0700"
  },
  "message": "hugetlb: fix race condition in hugetlb_fault()\n\nThe race is as follows:\n\nSuppose a multi-threaded task forks a new process (on cpu A), thus\nbumping up the ref count on all the pages.  While the fork is occurring\n(and thus we have marked all the PTEs as read-only), another thread in\nthe original process (on cpu B) tries to write to a huge page, taking an\naccess violation from the write-protect and calling hugetlb_cow().  Now,\nsuppose the fork() fails.  It will undo the COW and decrement the ref\ncount on the pages, so the ref count on the huge page drops back to 1.\nMeanwhile hugetlb_cow() also decrements the ref count by one on the\noriginal page, since the original address space doesn\u0027t need it any\nmore, having copied a new page to replace the original page.  This\nleaves the ref count at zero, and when we call unlock_page(), we panic.\n\n\tfork on CPU A\t\t\t\tfault on CPU B\n\t\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\t\t\t\t\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\t...\n\tdown_write(\u0026parent-\u003emmap_sem);\n\tdown_write_nested(\u0026child-\u003emmap_sem);\n\t...\n\twhile duplicating vmas\n\t\tif error\n\t\t\tbreak;\n\t...\n\tup_write(\u0026child-\u003emmap_sem);\n\tup_write(\u0026parent-\u003emmap_sem);\t\t...\n\t\t\t\t\t\tdown_read(\u0026parent-\u003emmap_sem);\n\t\t\t\t\t\t...\n\t\t\t\t\t\tlock_page(page);\n\t\t\t\t\t\thandle COW\n\t\t\t\t\t\tpage_mapcount(old_page) \u003d\u003d 2\n\t\t\t\t\t\talloc and prepare new_page\n\t...\n\thandle error\n\tpage_remove_rmap(page);\n\tput_page(page);\n\t...\n\t\t\t\t\t\tfold new_page into pte\n\t\t\t\t\t\tpage_remove_rmap(page);\n\t\t\t\t\t\tput_page(page);\n\t\t\t\t\t\t...\n\t\t\t\toops \u003d\u003d\u003e\tunlock_page(page);\n\t\t\t\t\t\tup_read(\u0026parent-\u003emmap_sem);\n\nThe solution is to take an extra reference to the page while we are\nholding the lock on it.\n\nSigned-off-by: Chris Metcalf \u003ccmetcalf@tilera.com\u003e\nCc: Hillf Danton \u003cdhillf@gmail.com\u003e\nCc: Michal Hocko \u003cmhocko@suse.cz\u003e\nCc: KAMEZAWA Hiroyuki \u003ckamezawa.hiroyu@jp.fujitsu.com\u003e\nCc: Hugh Dickins \u003chughd@google.com\u003e\nCc: \u003cstable@vger.kernel.org\u003e\nSigned-off-by: Andrew Morton \u003cakpm@linux-foundation.org\u003e\nSigned-off-by: Linus Torvalds \u003ctorvalds@linux-foundation.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "b8ce6f450956e6e3a9191cbf92afd1d490a32c9d",
      "old_mode": 33188,
      "old_path": "mm/hugetlb.c",
      "new_id": "cd65cb19c941b2bf04cb86777cb8312ecad6c0ae",
      "new_mode": 33188,
      "new_path": "mm/hugetlb.c"
    }
  ]
}
