{
  "schema_version": "1.6.1",
  "id": "RPI-CVE-2024-26640",
  "modified": "2026-10-09T11:39:44Z",
  "upstream": [
    "CVE-2024-26640"
  ],
  "published": "2024-03-18T10:22:07Z",
  "summary": "tcp: add sanity checks to rx zerocopy",
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\ntcp: add sanity checks to rx zerocopy\n\nTCP rx zerocopy intent is to map pages initially allocated\nfrom NIC drivers, not pages owned by a fs.\n\nThis patch adds to can_map_frag() these additional checks:\n\n- Page must not be a compound one.\n- page->mapping must be NULL.\n\nThis fixes the panic reported by ZhangPeng.\n\nsyzbot was able to loopback packets built with sendfile(),\nmapping pages owned by an ext4 file to TCP rx zerocopy.\n\nr3 = socket$inet_tcp(0x2, 0x1, 0x0)\nmmap(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x0, 0x12, r3, 0x0)\nr4 = socket$inet_tcp(0x2, 0x1, 0x0)\nbind$inet(r4, &(0x7f0000000000)={0x2, 0x4e24, @multicast1}, 0x10)\nconnect$inet(r4, &(0x7f00000006c0)={0x2, 0x4e24, @empty}, 0x10)\nr5 = openat$dir(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\\x00',\n    0x181e42, 0x0)\nfallocate(r5, 0x0, 0x0, 0x85b8)\nsendfile(r4, r5, 0x0, 0x8ba0)\ngetsockopt$inet_tcp_TCP_ZEROCOPY_RECEIVE(r4, 0x6, 0x23,\n    &(0x7f00000001c0)={&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x0, 0x0,\n    0x0, 0x0, 0x0, 0x0}, &(0x7f0000000440)=0x40)\nr6 = openat$dir(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\\x00',\n    0x181e42, 0x0)",
  "severity": [
    {
      "type": "CVSS_V3",
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"
    }
  ],
  "affected": [
    {
      "package": {
        "ecosystem": "Raspberry Pi OS:12",
        "name": "linux"
      },
      "versions": [
        "1:6.1.21-1+rpt1",
        "1:6.1.47-1+rpt2",
        "1:6.1.47-1+rpt4",
        "1:6.1.54-1+rpt2",
        "1:6.1.58-1+rpt2",
        "1:6.1.63-1+rpt1",
        "1:6.1.73-1+rpt1"
      ],
      "ecosystem_specific": {
        "binaries": [
          {
            "binary_name": "linux-image-6.1.0-rpi1-rpi-v6",
            "binary_version": "1:6.1.21-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi1-rpi-v7",
            "binary_version": "1:6.1.21-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi1-rpi-v7l",
            "binary_version": "1:6.1.21-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi1-rpi-v8",
            "binary_version": "1:6.1.21-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi2-rpi-v6",
            "binary_version": "1:6.1.47-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi2-rpi-v7",
            "binary_version": "1:6.1.47-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi2-rpi-v7l",
            "binary_version": "1:6.1.47-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi2-rpi-v8",
            "binary_version": "1:6.1.47-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-2712",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-v6",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-v7",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-v7l",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi3-rpi-v8",
            "binary_version": "1:6.1.47-1+rpt4"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi4-rpi-2712",
            "binary_version": "1:6.1.54-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi4-rpi-v6",
            "binary_version": "1:6.1.54-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi4-rpi-v7",
            "binary_version": "1:6.1.54-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi4-rpi-v7l",
            "binary_version": "1:6.1.54-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi4-rpi-v8",
            "binary_version": "1:6.1.54-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi6-rpi-2712",
            "binary_version": "1:6.1.58-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi6-rpi-v6",
            "binary_version": "1:6.1.58-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi6-rpi-v7",
            "binary_version": "1:6.1.58-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi6-rpi-v7l",
            "binary_version": "1:6.1.58-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi6-rpi-v8",
            "binary_version": "1:6.1.58-1+rpt2"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi7-rpi-2712",
            "binary_version": "1:6.1.63-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi7-rpi-v6",
            "binary_version": "1:6.1.63-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi7-rpi-v7",
            "binary_version": "1:6.1.63-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi7-rpi-v7l",
            "binary_version": "1:6.1.63-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi7-rpi-v8",
            "binary_version": "1:6.1.63-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi8-rpi-2712",
            "binary_version": "1:6.1.73-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi8-rpi-v6",
            "binary_version": "1:6.1.73-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi8-rpi-v7",
            "binary_version": "1:6.1.73-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi8-rpi-v7l",
            "binary_version": "1:6.1.73-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.1.0-rpi8-rpi-v8",
            "binary_version": "1:6.1.73-1+rpt1"
          }
        ]
      },
      "database_specific": {
        "per_version": {
          "1:6.1.21-1+rpt1": {
            "linux_commit": "0afb5e98488aed7017b9bf321b575d0177feb7ed",
            "upstream_version": "6.1.21",
            "assessment": "commit ancestry (strak rule)",
            "upstream_fixed": "6.1.77"
          },
          "1:6.1.47-1+rpt2": {
            "linux_commit": "655fc658a15ae7a6f37103754adb39ba52a9a14e",
            "upstream_version": "6.1.47",
            "assessment": "commit ancestry (strak rule)",
            "upstream_fixed": "6.1.77"
          },
          "1:6.1.47-1+rpt4": {
            "linux_commit": "655fc658a15ae7a6f37103754adb39ba52a9a14e",
            "upstream_version": "6.1.47",
            "assessment": "commit ancestry (strak rule)",
            "upstream_fixed": "6.1.77",
            "compiled_filter": false
          },
          "1:6.1.54-1+rpt2": {
            "linux_commit": "2906f7abdc03d4a92b6b0e2e0c87ea2a9dffe8f7",
            "upstream_version": "6.1.54",
            "assessment": "commit ancestry (strak rule)",
            "upstream_fixed": "6.1.77"
          },
          "1:6.1.58-1+rpt2": {
            "linux_commit": "ccf1586ad0663fa91238ac56abf6340d6d740d18",
            "upstream_version": "6.1.58",
            "assessment": "commit ancestry (strak rule)",
            "upstream_fixed": "6.1.77"
          },
          "1:6.1.63-1+rpt1": {
            "linux_commit": null,
            "upstream_version": "6.1.63",
            "assessment": "upstream version (no usable Linux commit)",
            "upstream_fixed": "6.1.77"
          },
          "1:6.1.73-1+rpt1": {
            "linux_commit": null,
            "upstream_version": "6.1.73",
            "assessment": "upstream version (no usable Linux commit)",
            "upstream_fixed": "6.1.77"
          }
        }
      }
    }
  ],
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://www.cve.org/CVERecord?id=CVE-2024-26640"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/f48bf9a83b1666d934247cb58a9887d7b3127b6f"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/718f446e60316bf606946f7f42367d691d21541e"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/b383d4ea272fe5795877506dcce5aad1f6330e5e"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/d15cc0f66884ef2bed28c7ccbb11c102aa3a0760"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/1b8adcc0e2c584fec778add7777fe28e20781e60"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/577e4432f3ac810049cb7e6b71f4d96ec7c6e894"
    }
  ],
  "database_specific": {
    "source": "https://git.kernel.org/pub/scm/linux/security/vulns.git",
    "upstream_modified": "2026-08-05T11:52:36Z",
    "severity": {
      "source": "kernel CNA",
      "cvss_v3_score": 7.8,
      "cvss_v3_severity": "High",
      "scenario": "AV:L - Triggering requires local syscalls on the attacker's own process \u2014 mmap() of a TCP socket, sendfile() of a page-cache-backed file over loopback, and getsockopt(TCP_ZEROCOPY_RECEIVE). A purely remote peer cannot supply page-cache or compound pages into the receive frags, since those come from the local NIC/page_pool allocator.\nAC:L - The syzbot reproducer is fully deterministic with no race window and no dependence on memory layout: sendfile() guarantees PAGE_SIZE frags at offset 0 pointing at ext4 page-cache pages, and loopback delivers them unchanged to the same socket's receive queue. Follow-on inode eviction is likewise triggered on demand by the attacker via O_TRUNC/unlink+close.\nPR:L - Every step is available to an ordinary unprivileged user \u2014 tcp_mmap() performs no capability check, TCP_ZEROCOPY_RECEIVE is unconditionally compiled in under CONFIG_MMU, and sendfile() on a file the user owns needs no privilege. No CAP_NET_ADMIN or namespace trickery is required at all.\nUI:N - A single unprivileged process performs the entire sequence against itself via a loopback self-connect; no victim process must be running, and no administrator or user action is needed.\nS:U - The corruption is confined to the kernel's own page-cache/rmap accounting and the attacking process's address space, managed by the same security authority. There is no crossing of a VM, IOMMU, or sandbox boundary.\nC:H - Because the page is mapped outside the inode's i_mmap tree, filemap_unaccount_folio()'s recovery path resets mapcount and subtracts the PTE's reference, letting the page be freed and reallocated while the attacker retains a valid read-only PTE to it \u2014 an arbitrary-read window into whatever kernel data (slab objects, page tables, other processes' pages) subsequently occupies that physical page.\nI:H - The dropped reference plus the later munmap-time page_remove_rmap()/put_page() drives _mapcount and the page refcount negative, producing a double-free of a buddy-allocator page that can be handed out twice and used as a write primitive into kernel-owned memory. The mismatched rmap/_nr_pages_mapped accounting for compound folios corrupts kernel state directly.\nA:H - This is exactly the reported crash \u2014 truncating the file makes filemap_unaccount_folio() hit VM_BUG_ON_FOLIO(folio_mapped(folio)) and panic the kernel; on non-DEBUG_VM builds it produces \"BUG: Bad page cache\"/bad-page-state taints and freelist corruption that destabilizes the whole system."
    }
  }
}
