{
  "schema_version": "1.6.1",
  "id": "RPI-CVE-2025-21954",
  "modified": "2026-10-09T11:39:44Z",
  "upstream": [
    "CVE-2025-21954"
  ],
  "published": "2025-04-01T15:46:27Z",
  "summary": "netmem: prevent TX of unreadable skbs",
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\nnetmem: prevent TX of unreadable skbs\n\nCurrently on stable trees we have support for netmem/devmem RX but not\nTX. It is not safe to forward/redirect an RX unreadable netmem packet\ninto the device's TX path, as the device may call dma-mapping APIs on\ndma addrs that should not be passed to it.\n\nFix this by preventing the xmit of unreadable skbs.\n\nTested by configuring tc redirect:\n\nsudo tc qdisc add dev eth1 ingress\nsudo tc filter add dev eth1 ingress protocol ip prio 1 flower ip_proto \\\n\ttcp src_ip 192.168.1.12 action mirred egress redirect dev eth1\n\nBefore, I see unreadable skbs in the driver's TX path passed to dma\nmapping APIs.\n\nAfter, I don't see unreadable skbs in the driver's TX path passed to dma\nmapping APIs.",
  "severity": [
    {
      "type": "CVSS_V3",
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
    }
  ],
  "affected": [
    {
      "package": {
        "ecosystem": "Raspberry Pi OS:13",
        "name": "linux"
      },
      "versions": [
        "1:6.12.19-1+rpt1~bpo12+1",
        "1:6.12.19-1+rpt1"
      ],
      "ecosystem_specific": {
        "binaries": [
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-2712",
            "binary_version": "1:6.12.19-1+rpt1~bpo12+1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-v6",
            "binary_version": "1:6.12.19-1+rpt1~bpo12+1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-v7",
            "binary_version": "1:6.12.19-1+rpt1~bpo12+1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-v7l",
            "binary_version": "1:6.12.19-1+rpt1~bpo12+1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-v8",
            "binary_version": "1:6.12.19-1+rpt1~bpo12+1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-2712",
            "binary_version": "1:6.12.19-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-v6",
            "binary_version": "1:6.12.19-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-v7",
            "binary_version": "1:6.12.19-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-v7l",
            "binary_version": "1:6.12.19-1+rpt1"
          },
          {
            "binary_name": "linux-image-6.12.19+rpt-rpi-v8",
            "binary_version": "1:6.12.19-1+rpt1"
          }
        ]
      },
      "database_specific": {
        "per_version": {
          "1:6.12.19-1+rpt1~bpo12+1": {
            "linux_commit": "121c2c384b9c2f4790ffb31b2cd25c7d75c8fda0",
            "upstream_version": "6.12.19",
            "assessment": "commit ancestry (strak rule)",
            "upstream_fixed": "6.12.20"
          },
          "1:6.12.19-1+rpt1": {
            "linux_commit": "121c2c384b9c2f4790ffb31b2cd25c7d75c8fda0",
            "upstream_version": "6.12.19",
            "assessment": "commit ancestry (strak rule)",
            "upstream_fixed": "6.12.20"
          }
        }
      }
    }
  ],
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://www.cve.org/CVERecord?id=CVE-2025-21954"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/454825019d2f0c59e5174ece9e713f45ad80beff"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/1c17c8ced25c5fbe424c7ad7ea11d33014a986b1"
    },
    {
      "type": "FIX",
      "url": "https://git.kernel.org/stable/c/f3600c867c99a2cc8038680ecf211089c50e7971"
    }
  ],
  "database_specific": {
    "source": "https://git.kernel.org/pub/scm/linux/security/vulns.git",
    "upstream_modified": "2026-08-05T12:19:11Z",
    "severity": {
      "source": "kernel CNA",
      "cvss_v3_score": 9.8,
      "cvss_v3_severity": "Critical",
      "scenario": "AV:N - The unreadable skb is created by the RX path from a packet sent by a remote peer into a dmabuf-bound RX queue, and the bug fires when that received packet is forwarded/bridged/redirected to egress (`ip_forward`/`br_forward`/`act_mirred` \u2192 `dev_queue_xmit` \u2192 `validate_xmit_skb`). The attacker's only action is transmitting network traffic to the host.\nAC:L - On a host in the affected configuration the trigger is fully deterministic \u2014 every forwarded devmem skb reaches `skb_frag_dma_map()` with a NULL page; there is no race window, timing dependency, or memory-layout requirement the attacker must win. `CONFIG_NET_DEVMEM` is `def_bool y`, and per CVSS the vulnerable runtime configuration is assumed rather than charged to complexity.\nPR:N - The remote sender needs no account, credential, or privilege on the target; ordinary unauthenticated packets landing on the devmem-bound queue and being forwarded are sufficient. The CAP_NET_ADMIN-gated `NETDEV_CMD_BIND_RX` is pre-existing admin setup, not something the attacker must perform.\nUI:N - No victim action is required \u2014 packet reception and kernel forwarding happen autonomously in softirq context. The devmem binding and forwarding/redirect rules are pre-existing system state, not an interaction solicited from a user.\nS:U - The bogus DMA mapping is programmed by the kernel itself and all consequences (crash, DMA fault, unintended memory access) land within the same host kernel's security authority. No guest/host, IOMMU-enforcement, or sandbox boundary is escaped by the vulnerability itself.\nC:H - The NIC is handed a DMA address derived from a NULL `struct page` that bears no relation to the intended buffer, so on the TX (device-read) path host memory outside any granted buffer can be fetched by the device and transmitted on the wire to the remote peer; the swiotlb path additionally `memcpy`s from `phys_to_virt()` of that garbage address into a bounce buffer that is then sent out.\nI:H - This is a DMA memory-safety violation: the kernel installs a mapping (and on IOMMU systems an active IOVA translation) for a physical range it never owned, and the subsequent `dma_sync`/`dma_unmap` and cache-maintenance operations act on that arbitrary physical range, so memory outside the intended buffer can be modified. Such device-DMA corruption is leveragable well beyond a simple crash.\nA:H - Outcomes include a kernel NULL dereference (`is_pci_p2pdma_page(NULL)`/`swiotlb_bounce()` on confidential-VM and bounce-buffer configurations), DMAR/AER fault storms and TX-ring wedging when the device aborts on the invalid address, and device reset or panic on platforms that escalate the PCIe error \u2014 all repeatable at will by continuing to send traffic."
    }
  }
}
