{
  "affected": [
    {
      "ranges": [
        {
          "events": [
            {
              "introduced": "20d72b00ca814d748f5663484e5c53bb2bf37a3a"
            },
            {
              "fixed": "8df142e93098b4531fadb5dfcf93087649f570b3"
            },
            {
              "fixed": "4d428dca252c858bfac691c31fa95d26cd008706"
            }
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "type": "GIT"
        },
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "1a8360c2eed3b292ed654c2ac61b09de4a80e298"
            }
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "type": "GIT"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Linux",
        "name": "Kernel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.16.0"
            },
            {
              "fixed": "6.16.10"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "database_specific": {
    "cna_assigner": "Linux",
    "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/40xxx/CVE-2025-40007.json"
  },
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\nnetfs: fix reference leak\n\nCommit 20d72b00ca81 (\"netfs: Fix the request's work item to not\nrequire a ref\") modified netfs_alloc_request() to initialize the\nreference counter to 2 instead of 1.  The rationale was that the\nrequet's \"work\" would release the second reference after completion\n(via netfs_{read,write}_collection_worker()).  That works most of the\ntime if all goes well.\n\nHowever, it leaks this additional reference if the request is released\nbefore the I/O operation has been submitted: the error code path only\ndecrements the reference counter once and the work item will never be\nqueued because there will never be a completion.\n\nThis has caused outages of our whole server cluster today because\ntasks were blocked in netfs_wait_for_outstanding_io(), leading to\ndeadlocks in Ceph (another bug that I will address soon in another\npatch).  This was caused by a netfs_pgpriv2_begin_copy_to_cache() call\nwhich failed in fscache_begin_write_operation().  The leaked\nnetfs_io_request was never completed, leaving `netfs_inode.io_count`\nwith a positive value forever.\n\nAll of this is super-fragile code.  Finding out which code paths will\nlead to an eventual completion and which do not is hard to see:\n\n- Some functions like netfs_create_write_req() allocate a request, but\n  will never submit any I/O.\n\n- netfs_unbuffered_read_iter_locked() calls netfs_unbuffered_read()\n  and then netfs_put_request(); however, netfs_unbuffered_read() can\n  also fail early before submitting the I/O request, therefore another\n  netfs_put_request() call must be added there.\n\nA rule of thumb is that functions that return a `netfs_io_request` do\nnot submit I/O, and all of their callers must be checked.\n\nFor my taste, the whole netfs code needs an overhaul to make reference\ncounting easier to understand and less fragile \u0026 obscure.  But to fix\nthis bug here and now and produce a patch that is adequate for a\nstable backport, I tried a minimal approach that quickly frees the\nrequest object upon early failure.\n\nI decided against adding a second netfs_put_request() each time\nbecause that would cause code duplication which obscures the code\nfurther.  Instead, I added the function netfs_put_failed_request()\nwhich frees such a failed request synchronously under the assumption\nthat the reference count is exactly 2 (as initially set by\nnetfs_alloc_request() and never touched), verified by a\nWARN_ON_ONCE().  It then deinitializes the request object (without\ngoing through the \"cleanup_work\" indirection) and frees the allocation\n(with RCU protection to protect against concurrent access by\nnetfs_requests_seq_start()).\n\nAll code paths that fail early have been changed to call\nnetfs_put_failed_request() instead of netfs_put_request().\nAdditionally, I have added a netfs_put_request() call to\nnetfs_unbuffered_read() as explained above because the\nnetfs_put_failed_request() approach does not work there.",
  "id": "CVE-2025-40007",
  "modified": "2026-04-01T23:10:04.619748015Z",
  "published": "2025-10-20T15:26:53.880Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/4d428dca252c858bfac691c31fa95d26cd008706"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/8df142e93098b4531fadb5dfcf93087649f570b3"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/40xxx/CVE-2025-40007.json"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-40007"
    },
    {
      "type": "PACKAGE",
      "url": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
    }
  ],
  "schema_version": "1.7.3",
  "summary": "netfs: fix reference leak"
}