CVE-2025-39948 (GCVE-0-2025-39948)

Vulnerability from cvelistv5 – Published: 2025-10-04 07:31 – Updated: 2026-10-21 12:37
VLAI
Title
ice: fix Rx page leak on multi-buffer frames
Summary
In the Linux kernel, the following vulnerability has been resolved: ice: fix Rx page leak on multi-buffer frames The ice_put_rx_mbuf() function handles calling ice_put_rx_buf() for each buffer in the current frame. This function was introduced as part of handling multi-buffer XDP support in the ice driver. It works by iterating over the buffers from first_desc up to 1 plus the total number of fragments in the frame, cached from before the XDP program was executed. If the hardware posts a descriptor with a size of 0, the logic used in ice_put_rx_mbuf() breaks. Such descriptors get skipped and don't get added as fragments in ice_add_xdp_frag. Since the buffer isn't counted as a fragment, we do not iterate over it in ice_put_rx_mbuf(), and thus we don't call ice_put_rx_buf(). Because we don't call ice_put_rx_buf(), we don't attempt to re-use the page or free it. This leaves a stale page in the ring, as we don't increment next_to_alloc. The ice_reuse_rx_page() assumes that the next_to_alloc has been incremented properly, and that it always points to a buffer with a NULL page. Since this function doesn't check, it will happily recycle a page over the top of the next_to_alloc buffer, losing track of the old page. Note that this leak only occurs for multi-buffer frames. The ice_put_rx_mbuf() function always handles at least one buffer, so a single-buffer frame will always get handled correctly. It is not clear precisely why the hardware hands us descriptors with a size of 0 sometimes, but it happens somewhat regularly with "jumbo frames" used by 9K MTU. To fix ice_put_rx_mbuf(), we need to make sure to call ice_put_rx_buf() on all buffers between first_desc and next_to_clean. Borrow the logic of a similar function in i40e used for this same purpose. Use the same logic also in ice_get_pgcnts(). Instead of iterating over just the number of fragments, use a loop which iterates until the current index reaches to the next_to_clean element just past the current frame. Unlike i40e, the ice_put_rx_mbuf() function does call ice_put_rx_buf() on the last buffer of the frame indicating the end of packet. For non-linear (multi-buffer) frames, we need to take care when adjusting the pagecnt_bias. An XDP program might release fragments from the tail of the frame, in which case that fragment page is already released. Only update the pagecnt_bias for the first descriptor and fragments still remaining post-XDP program. Take care to only access the shared info for fragmented buffers, as this avoids a significant cache miss. The xdp_xmit value only needs to be updated if an XDP program is run, and only once per packet. Drop the xdp_xmit pointer argument from ice_put_rx_mbuf(). Instead, set xdp_xmit in the ice_clean_rx_irq() function directly. This avoids needing to pass the argument and avoids an extra bit-wise OR for each buffer in the frame. Move the increment of the ntc local variable to ensure its updated *before* all calls to ice_get_pgcnts() or ice_put_rx_mbuf(), as the loop logic requires the index of the element just after the current frame. Now that we use an index pointer in the ring to identify the packet, we no longer need to track or cache the number of fragments in the rx_ring.
Assigner
Linux CNA under the mitre root
CNA scorecard D 53/100 over 6843 records in the last 180 days details
Impacted products
Vendor Product Version CPE status
Linux Linux Affected: ac1728cf370bec2e74fe6a2adf05b4629980d2b3 , < 8729dc4eeb502145418db5f2ca2192fd26f3efda (git)
Affected: 311813ed013c016d4b0b0985a9ee41f778489077 , < 80555adb5c892f0e21d243ae96ed997ee520aea9 (git)
Affected: 743bbd93cf29f653fae0e1416a31f03231689911 , < fcb5718ebfe7fd64144e3399280440cce361a3ae (git)
Affected: 743bbd93cf29f653fae0e1416a31f03231689911 , < 84bf1ac85af84d354c7a2fdbdc0d4efc8aaec34b (git)
Affected: d445b59d30415bb56f4803f622d566bca06e0abc (git)
Affected: 6.6.78 , < 6.6.160 (semver)
Affected: 6.12.14 , < 6.12.49 (semver)
Affected: 6.13.3 , < 6.14 (semver)
guessed Create a notification for this product.
Linux Linux Affected: 6.14
Unaffected: 0 , < 6.14 (semver)
Unaffected: 6.6.160 , ≤ 6.6.* (semver)
Unaffected: 6.12.49 , ≤ 6.12.* (semver)
Unaffected: 6.16.9 , ≤ 6.16.* (semver)
Unaffected: 6.17 , ≤ * (original_commit_for_fix)
guessed Create a notification for this product.
Show details on NVD website

{
  "containers": {
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "product": "Linux",
          "programFiles": [
            "drivers/net/ethernet/intel/ice/ice_txrx.c",
            "drivers/net/ethernet/intel/ice/ice_txrx.h"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "lessThan": "8729dc4eeb502145418db5f2ca2192fd26f3efda",
              "status": "affected",
              "version": "ac1728cf370bec2e74fe6a2adf05b4629980d2b3",
              "versionType": "git"
            },
            {
              "lessThan": "80555adb5c892f0e21d243ae96ed997ee520aea9",
              "status": "affected",
              "version": "311813ed013c016d4b0b0985a9ee41f778489077",
              "versionType": "git"
            },
            {
              "lessThan": "fcb5718ebfe7fd64144e3399280440cce361a3ae",
              "status": "affected",
              "version": "743bbd93cf29f653fae0e1416a31f03231689911",
              "versionType": "git"
            },
            {
              "lessThan": "84bf1ac85af84d354c7a2fdbdc0d4efc8aaec34b",
              "status": "affected",
              "version": "743bbd93cf29f653fae0e1416a31f03231689911",
              "versionType": "git"
            },
            {
              "status": "affected",
              "version": "d445b59d30415bb56f4803f622d566bca06e0abc",
              "versionType": "git"
            },
            {
              "lessThan": "6.6.160",
              "status": "affected",
              "version": "6.6.78",
              "versionType": "semver"
            },
            {
              "lessThan": "6.12.49",
              "status": "affected",
              "version": "6.12.14",
              "versionType": "semver"
            },
            {
              "lessThan": "6.14",
              "status": "affected",
              "version": "6.13.3",
              "versionType": "semver"
            }
          ]
        },
        {
          "defaultStatus": "affected",
          "product": "Linux",
          "programFiles": [
            "drivers/net/ethernet/intel/ice/ice_txrx.c",
            "drivers/net/ethernet/intel/ice/ice_txrx.h"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "6.14"
            },
            {
              "lessThan": "6.14",
              "status": "unaffected",
              "version": "0",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.6.*",
              "status": "unaffected",
              "version": "6.6.160",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.12.*",
              "status": "unaffected",
              "version": "6.12.49",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "6.16.*",
              "status": "unaffected",
              "version": "6.16.9",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "*",
              "status": "unaffected",
              "version": "6.17",
              "versionType": "original_commit_for_fix"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.6.160",
                  "versionStartIncluding": "6.6.78",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.12.49",
                  "versionStartIncluding": "6.12.14",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.16.9",
                  "versionStartIncluding": "6.14",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "6.17",
                  "versionStartIncluding": "6.14",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionStartIncluding": "6.13.3",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nice: fix Rx page leak on multi-buffer frames\n\nThe ice_put_rx_mbuf() function handles calling ice_put_rx_buf() for each\nbuffer in the current frame. This function was introduced as part of\nhandling multi-buffer XDP support in the ice driver.\n\nIt works by iterating over the buffers from first_desc up to 1 plus the\ntotal number of fragments in the frame, cached from before the XDP program\nwas executed.\n\nIf the hardware posts a descriptor with a size of 0, the logic used in\nice_put_rx_mbuf() breaks. Such descriptors get skipped and don\u0027t get added\nas fragments in ice_add_xdp_frag. Since the buffer isn\u0027t counted as a\nfragment, we do not iterate over it in ice_put_rx_mbuf(), and thus we don\u0027t\ncall ice_put_rx_buf().\n\nBecause we don\u0027t call ice_put_rx_buf(), we don\u0027t attempt to re-use the\npage or free it. This leaves a stale page in the ring, as we don\u0027t\nincrement next_to_alloc.\n\nThe ice_reuse_rx_page() assumes that the next_to_alloc has been incremented\nproperly, and that it always points to a buffer with a NULL page. Since\nthis function doesn\u0027t check, it will happily recycle a page over the top\nof the next_to_alloc buffer, losing track of the old page.\n\nNote that this leak only occurs for multi-buffer frames. The\nice_put_rx_mbuf() function always handles at least one buffer, so a\nsingle-buffer frame will always get handled correctly. It is not clear\nprecisely why the hardware hands us descriptors with a size of 0 sometimes,\nbut it happens somewhat regularly with \"jumbo frames\" used by 9K MTU.\n\nTo fix ice_put_rx_mbuf(), we need to make sure to call ice_put_rx_buf() on\nall buffers between first_desc and next_to_clean. Borrow the logic of a\nsimilar function in i40e used for this same purpose. Use the same logic\nalso in ice_get_pgcnts().\n\nInstead of iterating over just the number of fragments, use a loop which\niterates until the current index reaches to the next_to_clean element just\npast the current frame. Unlike i40e, the ice_put_rx_mbuf() function does\ncall ice_put_rx_buf() on the last buffer of the frame indicating the end of\npacket.\n\nFor non-linear (multi-buffer) frames, we need to take care when adjusting\nthe pagecnt_bias. An XDP program might release fragments from the tail of\nthe frame, in which case that fragment page is already released. Only\nupdate the pagecnt_bias for the first descriptor and fragments still\nremaining post-XDP program. Take care to only access the shared info for\nfragmented buffers, as this avoids a significant cache miss.\n\nThe xdp_xmit value only needs to be updated if an XDP program is run, and\nonly once per packet. Drop the xdp_xmit pointer argument from\nice_put_rx_mbuf(). Instead, set xdp_xmit in the ice_clean_rx_irq() function\ndirectly. This avoids needing to pass the argument and avoids an extra\nbit-wise OR for each buffer in the frame.\n\nMove the increment of the ntc local variable to ensure its updated *before*\nall calls to ice_get_pgcnts() or ice_put_rx_mbuf(), as the loop logic\nrequires the index of the element just after the current frame.\n\nNow that we use an index pointer in the ring to identify the packet, we no\nlonger need to track or cache the number of fragments in the rx_ring."
        }
      ],
      "metrics": [
        {
          "cvssV3_1": {
            "baseScore": 9.8,
            "baseSeverity": "CRITICAL",
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
            "version": "3.1"
          },
          "scenarios": [
            {
              "lang": "en",
              "value": "AV:N - The vulnerable code is the ice NIC\u0027s Rx completion path (`ice_clean_rx_irq`), reached by every inbound Ethernet frame before any protocol demux, socket lookup or firewall filtering, so the attacker only needs to send multi-buffer (\u003e3072 byte) frames at the host. Jumbo MTU is the default on cloud VPC networking (AWS 9001, GCP 8896) and datacenter storage fabrics where such frames are routed across L3, so the trigger is remote, not merely link-local.\nAC:L - The attacker simply floods large frames; Intel documents the zero-size-descriptor condition as occurring \"somewhat regularly\" with 9K MTU, so at volume the leak and the mis-recycled buffer are hit reliably, with no race to win and no memory-layout dependency the attacker cannot influence. Jumbo MTU is a mainstream deployment configuration rather than a rare kernel build option.\nPR:N - Descriptor processing happens in NAPI context before any credential, socket, or netfilter check, so packets to closed ports or packets that would be dropped by the firewall still traverse the buggy code. No account, capability, or session on the target is required.\nUI:N - The bug triggers purely on packet reception by the driver; no local user or administrator has to open, mount, or interact with anything. The victim only needs the interface to be up.\nS:U - The leaked pages, the mis-posted Rx buffers, and the corrupted page refcounts all live in kernel memory managed by the same kernel security authority. No VM, IOMMU, or sandbox boundary is crossed.\nC:H - The unreleased buffer keeps its `page_offset` on the half of the page still owned by an in-flight skb and is re-posted to hardware by `ice_alloc_rx_bufs()`, so a stack-owned buffer \u2014 potentially one mapped into userspace by TCP receive zerocopy \u2014 is simultaneously used as a DMA target for later packets, aliasing data across unrelated flows and tenants. The `pagecnt_bias` over-increment can additionally free a page still referenced by an skb, giving a use-after-free that exposes freed-page contents.\nI:H - Hardware DMAs attacker-controlled packet data directly over payload of skbs already queued in the network stack, silently corrupting data delivered to applications, and the same buffer is handed to the stack twice. The refcount underflow path frees a live page, yielding a page-level use-after-free that is a classic write primitive via heap reuse.\nA:H - Every occurrence permanently leaks a page together with its DMA/IOVA mapping, and the leak is unbounded and driven purely by remote traffic volume \u2014 the reporter observed production hosts steadily losing memory until OOM. The associated buffer aliasing and page refcount underflow also produce corruption and crashes rather than mere degradation."
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-10-21T12:37:38.940Z",
        "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "shortName": "Linux"
      },
      "references": [
        {
          "url": "https://git.kernel.org/stable/c/8729dc4eeb502145418db5f2ca2192fd26f3efda"
        },
        {
          "url": "https://git.kernel.org/stable/c/80555adb5c892f0e21d243ae96ed997ee520aea9"
        },
        {
          "url": "https://git.kernel.org/stable/c/fcb5718ebfe7fd64144e3399280440cce361a3ae"
        },
        {
          "url": "https://git.kernel.org/stable/c/84bf1ac85af84d354c7a2fdbdc0d4efc8aaec34b"
        }
      ],
      "title": "ice: fix Rx page leak on multi-buffer frames",
      "x_generator": {
        "engine": "bippy-1.2.0"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
    "assignerShortName": "Linux",
    "cveId": "CVE-2025-39948",
    "datePublished": "2025-10-04T07:31:09.403Z",
    "dateReserved": "2025-04-16T07:20:57.148Z",
    "dateUpdated": "2026-10-21T12:37:38.940Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2",
  "vulnerability-lookup:meta": {
    "epss": {
      "cve": "CVE-2025-39948",
      "date": "2026-10-22",
      "epss": "0.00301",
      "percentile": "0.21626"
    },
    "nvd": {
      "cve": {
        "affected": [
          {
            "affectedData": [
              {
                "defaultStatus": "unaffected",
                "product": "Linux",
                "programFiles": [
                  "drivers/net/ethernet/intel/ice/ice_txrx.c",
                  "drivers/net/ethernet/intel/ice/ice_txrx.h"
                ],
                "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
                "vendor": "Linux",
                "versions": [
                  {
                    "lessThan": "8729dc4eeb502145418db5f2ca2192fd26f3efda",
                    "status": "affected",
                    "version": "ac1728cf370bec2e74fe6a2adf05b4629980d2b3",
                    "versionType": "git"
                  },
                  {
                    "lessThan": "80555adb5c892f0e21d243ae96ed997ee520aea9",
                    "status": "affected",
                    "version": "311813ed013c016d4b0b0985a9ee41f778489077",
                    "versionType": "git"
                  },
                  {
                    "lessThan": "fcb5718ebfe7fd64144e3399280440cce361a3ae",
                    "status": "affected",
                    "version": "743bbd93cf29f653fae0e1416a31f03231689911",
                    "versionType": "git"
                  },
                  {
                    "lessThan": "84bf1ac85af84d354c7a2fdbdc0d4efc8aaec34b",
                    "status": "affected",
                    "version": "743bbd93cf29f653fae0e1416a31f03231689911",
                    "versionType": "git"
                  },
                  {
                    "status": "affected",
                    "version": "d445b59d30415bb56f4803f622d566bca06e0abc",
                    "versionType": "git"
                  },
                  {
                    "lessThan": "6.6.160",
                    "status": "affected",
                    "version": "6.6.78",
                    "versionType": "semver"
                  },
                  {
                    "lessThan": "6.12.49",
                    "status": "affected",
                    "version": "6.12.14",
                    "versionType": "semver"
                  },
                  {
                    "lessThan": "6.14",
                    "status": "affected",
                    "version": "6.13.3",
                    "versionType": "semver"
                  }
                ]
              },
              {
                "defaultStatus": "affected",
                "product": "Linux",
                "programFiles": [
                  "drivers/net/ethernet/intel/ice/ice_txrx.c",
                  "drivers/net/ethernet/intel/ice/ice_txrx.h"
                ],
                "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
                "vendor": "Linux",
                "versions": [
                  {
                    "status": "affected",
                    "version": "6.14"
                  },
                  {
                    "lessThan": "6.14",
                    "status": "unaffected",
                    "version": "0",
                    "versionType": "semver"
                  },
                  {
                    "lessThanOrEqual": "6.6.*",
                    "status": "unaffected",
                    "version": "6.6.160",
                    "versionType": "semver"
                  },
                  {
                    "lessThanOrEqual": "6.12.*",
                    "status": "unaffected",
                    "version": "6.12.49",
                    "versionType": "semver"
                  },
                  {
                    "lessThanOrEqual": "6.16.*",
                    "status": "unaffected",
                    "version": "6.16.9",
                    "versionType": "semver"
                  },
                  {
                    "lessThanOrEqual": "*",
                    "status": "unaffected",
                    "version": "6.17",
                    "versionType": "original_commit_for_fix"
                  }
                ]
              }
            ],
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
          }
        ],
        "configurations": [
          {
            "nodes": [
              {
                "cpeMatch": [
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                    "matchCriteriaId": "798E4358-338A-4036-B5D8-1838AB8BCCD4",
                    "versionEndExcluding": "6.7",
                    "versionStartIncluding": "6.6.78",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                    "matchCriteriaId": "D923DEB0-924B-4809-8FDE-2A7C2793235A",
                    "versionEndExcluding": "6.12.49",
                    "versionStartIncluding": "6.12.14",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                    "matchCriteriaId": "B8E3FDCA-E284-40B8-A6D6-540447031B88",
                    "versionEndExcluding": "6.14",
                    "versionStartIncluding": "6.13.3",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                    "matchCriteriaId": "6AB98D54-D180-4A88-8A84-DDCE0D947A94",
                    "versionEndExcluding": "6.16.9",
                    "versionStartIncluding": "6.14.1",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.14:-:*:*:*:*:*:*",
                    "matchCriteriaId": "7DE421BA-0600-4401-A175-73CAB6A6FB4E",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc2:*:*:*:*:*:*",
                    "matchCriteriaId": "0D3E781C-403A-498F-9DA9-ECEE50F41E75",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc3:*:*:*:*:*:*",
                    "matchCriteriaId": "66619FB8-0AAF-4166-B2CF-67B24143261D",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc4:*:*:*:*:*:*",
                    "matchCriteriaId": "D3D6550E-6679-4560-902D-AF52DCFE905B",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc5:*:*:*:*:*:*",
                    "matchCriteriaId": "45B90F6B-BEC7-4D4E-883A-9DBADE021750",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc6:*:*:*:*:*:*",
                    "matchCriteriaId": "1759FFB7-531C-41B1-9AE1-FD3D80E0D920",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc7:*:*:*:*:*:*",
                    "matchCriteriaId": "AD948719-8628-4421-A340-1066314BBD4A",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc1:*:*:*:*:*:*",
                    "matchCriteriaId": "327D22EF-390B-454C-BD31-2ED23C998A1C",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc2:*:*:*:*:*:*",
                    "matchCriteriaId": "C730CD9A-D969-4A8E-9522-162AAF7C0EE9",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc3:*:*:*:*:*:*",
                    "matchCriteriaId": "39982C4B-716E-4B2F-8196-FA301F47807D",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc4:*:*:*:*:*:*",
                    "matchCriteriaId": "340BEEA9-D70D-4290-B502-FBB1032353B1",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc5:*:*:*:*:*:*",
                    "matchCriteriaId": "47E4C5C0-079F-4838-971B-8C503D48FCC2",
                    "vulnerable": true
                  },
                  {
                    "criteria": "cpe:2.3:o:linux:linux_kernel:6.17:rc6:*:*:*:*:*:*",
                    "matchCriteriaId": "5A4516A6-C12E-42A4-8C0E-68AEF3264504",
                    "vulnerable": true
                  }
                ],
                "negate": false,
                "operator": "OR"
              }
            ]
          }
        ],
        "cveTags": [],
        "descriptions": [
          {
            "lang": "en",
            "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nice: fix Rx page leak on multi-buffer frames\n\nThe ice_put_rx_mbuf() function handles calling ice_put_rx_buf() for each\nbuffer in the current frame. This function was introduced as part of\nhandling multi-buffer XDP support in the ice driver.\n\nIt works by iterating over the buffers from first_desc up to 1 plus the\ntotal number of fragments in the frame, cached from before the XDP program\nwas executed.\n\nIf the hardware posts a descriptor with a size of 0, the logic used in\nice_put_rx_mbuf() breaks. Such descriptors get skipped and don\u0027t get added\nas fragments in ice_add_xdp_frag. Since the buffer isn\u0027t counted as a\nfragment, we do not iterate over it in ice_put_rx_mbuf(), and thus we don\u0027t\ncall ice_put_rx_buf().\n\nBecause we don\u0027t call ice_put_rx_buf(), we don\u0027t attempt to re-use the\npage or free it. This leaves a stale page in the ring, as we don\u0027t\nincrement next_to_alloc.\n\nThe ice_reuse_rx_page() assumes that the next_to_alloc has been incremented\nproperly, and that it always points to a buffer with a NULL page. Since\nthis function doesn\u0027t check, it will happily recycle a page over the top\nof the next_to_alloc buffer, losing track of the old page.\n\nNote that this leak only occurs for multi-buffer frames. The\nice_put_rx_mbuf() function always handles at least one buffer, so a\nsingle-buffer frame will always get handled correctly. It is not clear\nprecisely why the hardware hands us descriptors with a size of 0 sometimes,\nbut it happens somewhat regularly with \"jumbo frames\" used by 9K MTU.\n\nTo fix ice_put_rx_mbuf(), we need to make sure to call ice_put_rx_buf() on\nall buffers between first_desc and next_to_clean. Borrow the logic of a\nsimilar function in i40e used for this same purpose. Use the same logic\nalso in ice_get_pgcnts().\n\nInstead of iterating over just the number of fragments, use a loop which\niterates until the current index reaches to the next_to_clean element just\npast the current frame. Unlike i40e, the ice_put_rx_mbuf() function does\ncall ice_put_rx_buf() on the last buffer of the frame indicating the end of\npacket.\n\nFor non-linear (multi-buffer) frames, we need to take care when adjusting\nthe pagecnt_bias. An XDP program might release fragments from the tail of\nthe frame, in which case that fragment page is already released. Only\nupdate the pagecnt_bias for the first descriptor and fragments still\nremaining post-XDP program. Take care to only access the shared info for\nfragmented buffers, as this avoids a significant cache miss.\n\nThe xdp_xmit value only needs to be updated if an XDP program is run, and\nonly once per packet. Drop the xdp_xmit pointer argument from\nice_put_rx_mbuf(). Instead, set xdp_xmit in the ice_clean_rx_irq() function\ndirectly. This avoids needing to pass the argument and avoids an extra\nbit-wise OR for each buffer in the frame.\n\nMove the increment of the ntc local variable to ensure its updated *before*\nall calls to ice_get_pgcnts() or ice_put_rx_mbuf(), as the loop logic\nrequires the index of the element just after the current frame.\n\nNow that we use an index pointer in the ring to identify the packet, we no\nlonger need to track or cache the number of fragments in the rx_ring."
          },
          {
            "lang": "es",
            "value": "En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta:\n\nice: corrige la fuga de p\u00e1gina Rx en tramas de m\u00faltiples b\u00faferes\n\nLa funci\u00f3n ice_put_rx_mbuf() se encarga de llamar a ice_put_rx_buf() para cada b\u00fafer en la trama actual. Esta funci\u00f3n fue introducida como parte del manejo del soporte XDP de m\u00faltiples b\u00faferes en el controlador ice.\n\nFunciona iterando sobre los b\u00faferes desde first_desc hasta 1 m\u00e1s el n\u00famero total de fragmentos en la trama, almacenados en cach\u00e9 desde antes de que se ejecutara el programa XDP.\n\nSi el hardware publica un descriptor con un tama\u00f1o de 0, la l\u00f3gica utilizada en ice_put_rx_mbuf() falla. Dichos descriptores se omiten y no se a\u00f1aden como fragmentos en ice_add_xdp_frag. Dado que el b\u00fafer no se cuenta como un fragmento, no iteramos sobre \u00e9l en ice_put_rx_mbuf(), y, por lo tanto, no llamamos a ice_put_rx_buf().\n\nDebido a que no llamamos a ice_put_rx_buf(), no intentamos reutilizar la p\u00e1gina ni liberarla. Esto deja una p\u00e1gina obsoleta en el anillo, ya que no incrementamos next_to_alloc.\n\nLa funci\u00f3n ice_reuse_rx_page() asume que next_to_alloc se ha incrementado correctamente y que siempre apunta a un b\u00fafer con una p\u00e1gina NULL. Dado que esta funci\u00f3n no verifica, reciclar\u00e1 felizmente una p\u00e1gina sobre el b\u00fafer next_to_alloc, perdiendo el rastro de la p\u00e1gina antigua.\n\nTenga en cuenta que esta fuga solo ocurre para tramas de m\u00faltiples b\u00faferes. La funci\u00f3n ice_put_rx_mbuf() siempre maneja al menos un b\u00fafer, por lo que una trama de un solo b\u00fafer siempre se manejar\u00e1 correctamente. No est\u00e1 claro con precisi\u00f3n por qu\u00e9 el hardware nos entrega descriptores con un tama\u00f1o de 0 a veces, pero ocurre con cierta regularidad con \u0027tramas jumbo\u0027 utilizadas por MTU de 9K.\n\nPara corregir ice_put_rx_mbuf(), necesitamos asegurarnos de llamar a ice_put_rx_buf() en todos los b\u00faferes entre first_desc y next_to_clean. Tomar prestada la l\u00f3gica de una funci\u00f3n similar en i40e utilizada para este mismo prop\u00f3sito. Usar la misma l\u00f3gica tambi\u00e9n en ice_get_pgcnts().\n\nEn lugar de iterar solo sobre el n\u00famero de fragmentos, usar un bucle que itere hasta que el \u00edndice actual alcance el elemento next_to_clean justo despu\u00e9s de la trama actual. A diferencia de i40e, la funci\u00f3n ice_put_rx_mbuf() s\u00ed llama a ice_put_rx_buf() en el \u00faltimo b\u00fafer de la trama indicando el final del paquete.\n\nPara tramas no lineales (de m\u00faltiples b\u00faferes), debemos tener cuidado al ajustar el pagecnt_bias. Un programa XDP podr\u00eda liberar fragmentos de la cola de la trama, en cuyo caso esa p\u00e1gina de fragmento ya est\u00e1 liberada. Solo actualizar el pagecnt_bias para el primer descriptor y los fragmentos que a\u00fan quedan despu\u00e9s del programa XDP. Tenga cuidado de acceder solo a la informaci\u00f3n compartida para b\u00faferes fragmentados, ya que esto evita una falla de cach\u00e9 significativa.\n\nEl valor xdp_xmit solo necesita ser actualizado si se ejecuta un programa XDP, y solo una vez por paquete. Eliminar el argumento de puntero xdp_xmit de ice_put_rx_mbuf(). En su lugar, establecer xdp_xmit directamente en la funci\u00f3n ice_clean_rx_irq(). Esto evita la necesidad de pasar el argumento y evita un OR bit a bit adicional para cada b\u00fafer en la trama.\n\nMover el incremento de la variable local ntc para asegurar que se actualice *antes* de todas las llamadas a ice_get_pgcnts() o ice_put_rx_mbuf(), ya que la l\u00f3gica del bucle requiere el \u00edndice del elemento justo despu\u00e9s de la trama actual.\n\nAhora que usamos un puntero de \u00edndice en el anillo para identificar el paquete, ya no necesitamos rastrear o almacenar en cach\u00e9 el n\u00famero de fragmentos en el rx_ring."
          }
        ],
        "id": "CVE-2025-39948",
        "lastModified": "2026-10-21T13:18:17.630",
        "metrics": {
          "cvssMetricV31": [
            {
              "cvssData": {
                "attackComplexity": "LOW",
                "attackVector": "NETWORK",
                "availabilityImpact": "HIGH",
                "baseScore": 9.8,
                "baseSeverity": "CRITICAL",
                "confidentialityImpact": "HIGH",
                "integrityImpact": "HIGH",
                "privilegesRequired": "NONE",
                "scope": "UNCHANGED",
                "userInteraction": "NONE",
                "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
                "version": "3.1"
              },
              "exploitabilityScore": 3.9,
              "impactScore": 5.9,
              "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
              "type": "Secondary"
            },
            {
              "cvssData": {
                "attackComplexity": "LOW",
                "attackVector": "LOCAL",
                "availabilityImpact": "HIGH",
                "baseScore": 5.5,
                "baseSeverity": "MEDIUM",
                "confidentialityImpact": "NONE",
                "integrityImpact": "NONE",
                "privilegesRequired": "LOW",
                "scope": "UNCHANGED",
                "userInteraction": "NONE",
                "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
                "version": "3.1"
              },
              "exploitabilityScore": 1.8,
              "impactScore": 3.6,
              "source": "nvd@nist.gov",
              "type": "Primary"
            }
          ]
        },
        "published": "2025-10-04T08:15:47.990",
        "references": [
          {
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
            "tags": [
              "Patch"
            ],
            "url": "https://git.kernel.org/stable/c/80555adb5c892f0e21d243ae96ed997ee520aea9"
          },
          {
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
            "tags": [
              "Patch"
            ],
            "url": "https://git.kernel.org/stable/c/84bf1ac85af84d354c7a2fdbdc0d4efc8aaec34b"
          },
          {
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
            "url": "https://git.kernel.org/stable/c/8729dc4eeb502145418db5f2ca2192fd26f3efda"
          },
          {
            "source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
            "tags": [
              "Patch"
            ],
            "url": "https://git.kernel.org/stable/c/fcb5718ebfe7fd64144e3399280440cce361a3ae"
          }
        ],
        "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "vulnStatus": "Modified",
        "weaknesses": [
          {
            "description": [
              {
                "lang": "en",
                "value": "CWE-401"
              }
            ],
            "source": "nvd@nist.gov",
            "type": "Primary"
          }
        ]
      }
    },
    "redhat_vex": {
      "aggregate_severity": "Moderate",
      "current_release_date": "2026-07-30T08:57:16+00:00",
      "cve": "CVE-2025-39948",
      "id": "CVE-2025-39948",
      "initial_release_date": "2025-10-04T00:00:00+00:00",
      "product_status:known_affected": "78",
      "product_status:known_not_affected": "196",
      "source": "Red Hat CSAF VEX",
      "status": "final",
      "title": "kernel: ice: fix Rx page leak on multi-buffer frames",
      "url": "https://security.access.redhat.com/data/csaf/v2/vex/2025/cve-2025-39948.json",
      "version": "3"
    }
  }
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline

Sightings and recorded dates, grouped by day · UTC

JSON
Events included in the timeline

Loading timeline…


    Loading…

    Loading…

    Loading…

    Related by attack behaviour

    Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.