)]}'
{
  "commit": "53ab88e0b1fbc160209e0e54c15e968942ee6087",
  "tree": "4bec6ded8f90e3c0c5d03703d2e62be4b5627fb0",
  "parents": [
    "ccc0e8d808b489320a88f4898dd66aad6ef4914d"
  ],
  "author": {
    "name": "Al Viro",
    "email": "viro@zeniv.linux.org.uk",
    "time": "Fri Nov 14 02:18:22 2025 -0500"
  },
  "committer": {
    "name": "Al Viro",
    "email": "viro@zeniv.linux.org.uk",
    "time": "Mon Nov 17 17:07:28 2025 -0500"
  },
  "message": "functionfs: fix the open/removal races\n\nffs_epfile_open() can race with removal, ending up with file-\u003eprivate_data\npointing to freed object.\n\nThere is a total count of opened files on functionfs (both ep0 and\ndynamic ones) and when it hits zero, dynamic files get removed.\nUnfortunately, that removal can happen while another thread is\nin ffs_epfile_open(), but has not incremented the count yet.\nIn that case open will succeed, leaving us with UAF on any subsequent\nread() or write().\n\nThe root cause is that ffs-\u003eopened is misused; atomic_dec_and_test() vs.\natomic_add_return() is not a good idea, when object remains visible all\nalong.\n\nTo untangle that\n\t* serialize openers on ffs-\u003emutex (both for ep0 and for dynamic files)\n\t* have dynamic ones use atomic_inc_not_zero() and fail if we had\nzero -\u003eopened; in that case the file we are opening is doomed.\n\t* have the inodes of dynamic files marked on removal (from the\ncallback of simple_recursive_removal()) - clear -\u003ei_private there.\n\t* have open of dynamic ones verify they hadn\u0027t been already removed,\nalong with checking that state is FFS_ACTIVE.\n\nSigned-off-by: Al Viro \u003cviro@zeniv.linux.org.uk\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "27860fc0fd7d1e0825533debfbf89bc2e5c8914d",
      "old_mode": 33188,
      "old_path": "drivers/usb/gadget/function/f_fs.c",
      "new_id": "c7cb23a15fd08c29d3e77235ed9f2e03ebe0451d",
      "new_mode": 33188,
      "new_path": "drivers/usb/gadget/function/f_fs.c"
    }
  ]
}
