CVE-2025-21860
In the Linux kernel, the following vulnerability has been resolved:
mm/zswap: fix inconsistency when zswap_store_page() fails
Commit b7c0ccdfbafd ("mm: zswap: support large folios in zswap_store()") skips charging any zswap entries when it failed to zswap the entire folio.
However, when some base pages are zswapped but it failed to zswap the entire folio, the zswap operation is rolled back. When freeing zswap entries for those pages, zswap_entry_free() uncharges the zswap entries that were not previously charged, causing zswap charging to become inconsistent.
zswap_stored_pages also becomes inconsistent in the same way.
Leer descripción completaMostrar menos
As suggested by Kanchana, increment zswap_stored_pages and charge zswap entries within zswap_store_page() when it succeeds. This way, zswap_entry_free() will decrement the counter and uncharge the entries when it failed to zswap the entire folio.
While this could potentially be optimized by batching objcg charging and incrementing the counter, let's focus on fixing the bug this time and leave the optimization for later after some evaluation.
After resolving the inconsistency, the warnings disappear.
[42.hyeyoo@gmail.com: refactor zswap_store_page()]
Detalles técnicos trazas, registros y código del informe original
This inconsistency triggers two warnings with following steps:
# On a machine with 64GiB of RAM and 36GiB of zswap
$ stress-ng --bigheap 2 # wait until the OOM-killer kills stress-ng
$ sudo reboot
The two warnings are:
in mm/memcontrol.c:163, function obj_cgroup_release():
WARN_ON_ONCE(nr_bytes & (PAGE_SIZE - 1));
in mm/page_counter.c:60, function page_counter_cancel():
if (WARN_ONCE(new < 0, "page_counter underflow: %ld nr_pages=%lu\n",
new, nr_pages))CVSS
- Versión: 3.1
- Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L
- Puntuación base: 3.3
Probabilidad de explotación (EPSS)
- Probabilidad de explotación en los próximos 30 días: 0.22%
- Percentil entre todas las CVEs puntuadas: 12
- Fecha de la puntuación: 6/10/2026
EPSS (Exploit Prediction Scoring System, de FIRST) estima la probabilidad de que una vulnerabilidad sea explotada en 30 días. Complementa a CVSS (impacto) y a CISA KEV (explotación confirmada).
Tecnologías afectadas (1)
CWE
- NVD-CWE-noinfo
Referencias
JSON original (NVD)
Mostrar
{
"id": "CVE-2025-21860",
"cveTags": [],
"metrics": {
"cvssMetricV31": [
{
"type": "Primary",
"source": "nvd@nist.gov",
"cvssData": {
"scope": "UNCHANGED",
"version": "3.1",
"baseScore": 3.3,
"attackVector": "LOCAL",
"baseSeverity": "LOW",
"vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L",
"integrityImpact": "NONE",
"userInteraction": "NONE",
"attackComplexity": "LOW",
"availabilityImpact": "LOW",
"privilegesRequired": "LOW",
"confidentialityImpact": "NONE"
},
"impactScore": 1.4,
"exploitabilityScore": 1.8
}
]
},
"affected": [
{
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"affectedData": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "b7c0ccdfbafdec98699ddb6f164beebf16f0bc45",
"lessThan": "a3652f5552b20903315612da487a7be2b95394d5",
"versionType": "git"
},
{
"status": "affected",
"version": "b7c0ccdfbafdec98699ddb6f164beebf16f0bc45",
"lessThan": "63895d20d63b446f5049a963983489319c2ea3e2",
"versionType": "git"
}
],
"programFiles": [
"mm/zswap.c"
],
"defaultStatus": "unaffected"
},
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"product": "Linux",
"versions": [
{
"status": "affected",
"version": "6.13"
},
{
"status": "unaffected",
"version": "0",
"lessThan": "6.13",
"versionType": "semver"
},
{
"status": "unaffected",
"version": "6.13.5",
"versionType": "semver",
"lessThanOrEqual": "6.13.*"
},
{
"status": "unaffected",
"version": "6.14",
"versionType": "original_commit_for_fix",
"lessThanOrEqual": "*"
}
],
"programFiles": [
"mm/zswap.c"
],
"defaultStatus": "affected"
}
]
}
],
"published": "2025-03-12T10:15:18.990",
"references": [
{
"url": "https://git.kernel.org/stable/c/63895d20d63b446f5049a963983489319c2ea3e2",
"tags": [
"Patch"
],
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
},
{
"url": "https://git.kernel.org/stable/c/a3652f5552b20903315612da487a7be2b95394d5",
"tags": [
"Patch"
],
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}
],
"vulnStatus": "Modified",
"weaknesses": [
{
"type": "Primary",
"source": "nvd@nist.gov",
"description": [
{
"lang": "en",
"value": "NVD-CWE-noinfo"
}
]
}
],
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\nmm/zswap: fix inconsistency when zswap_store_page() fails\n\nCommit b7c0ccdfbafd (\"mm: zswap: support large folios in zswap_store()\")\nskips charging any zswap entries when it failed to zswap the entire folio.\n\nHowever, when some base pages are zswapped but it failed to zswap the\nentire folio, the zswap operation is rolled back. When freeing zswap\nentries for those pages, zswap_entry_free() uncharges the zswap entries\nthat were not previously charged, causing zswap charging to become\ninconsistent.\n\nThis inconsistency triggers two warnings with following steps:\n # On a machine with 64GiB of RAM and 36GiB of zswap\n $ stress-ng --bigheap 2 # wait until the OOM-killer kills stress-ng\n $ sudo reboot\n\n The two warnings are:\n in mm/memcontrol.c:163, function obj_cgroup_release():\n WARN_ON_ONCE(nr_bytes & (PAGE_SIZE - 1));\n\n in mm/page_counter.c:60, function page_counter_cancel():\n if (WARN_ONCE(new < 0, \"page_counter underflow: %ld nr_pages=%lu\\n\",\n\t new, nr_pages))\n\nzswap_stored_pages also becomes inconsistent in the same way.\n\nAs suggested by Kanchana, increment zswap_stored_pages and charge zswap\nentries within zswap_store_page() when it succeeds. This way,\nzswap_entry_free() will decrement the counter and uncharge the entries\nwhen it failed to zswap the entire folio.\n\nWhile this could potentially be optimized by batching objcg charging and\nincrementing the counter, let's focus on fixing the bug this time and\nleave the optimization for later after some evaluation.\n\nAfter resolving the inconsistency, the warnings disappear.\n\n[42.hyeyoo@gmail.com: refactor zswap_store_page()]"
},
{
"lang": "es",
"value": "En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: mm/zswap: se corrige una inconsistencia al fallar zswap_store_page(). El commit b7c0ccdfbafd (\"mm: zswap: admite folios grandes en zswap_store()\") omite el cobro de las entradas zswap cuando no se logra el cobro de todo el folio. Sin embargo, cuando se realizan cobros de algunas páginas base, pero no se logra el cobro de todo el folio, la operación de cobro se revierte. Al liberar las entradas zswap de esas páginas, zswap_entry_free() descarga las entradas zswap que no se habían cargado previamente, lo que provoca que el cobro de zswap se vuelva inconsistente. Esta inconsistencia activa dos advertencias con los siguientes pasos: # En una máquina con 64 GiB de RAM y 36 GiB de zswap $ stress-ng --bigheap 2 # esperar hasta que OOM-killer elimine stress-ng $ sudo reboot Las dos advertencias son: en mm/memcontrol.c:163, función obj_cgroup_release(): WARN_ON_ONCE(nr_bytes & (PAGE_SIZE - 1)); en mm/page_counter.c:60, función page_counter_cancel(): if (WARN_ONCE(new < 0, \"page_counter underflow: %ld nr_pages=%lu\\n\", new, nr_pages)) zswap_stored_pages también se vuelve inconsistente de la misma manera. Como sugirió Kanchana, incremente zswap_stored_pages y cargue las entradas zswap dentro de zswap_store_page() cuando tenga éxito. De esta forma, zswap_entry_free() decrementará el contador y descargará las entradas cuando no pueda intercambiar todo el folio con zswap. Si bien esto podría optimizarse agrupando la carga de objcg e incrementando el contador, centrémonos en corregir el error esta vez y dejemos la optimización para más adelante, tras una evaluación. Tras resolver la inconsistencia, las advertencias desaparecen. [42.hyeyoo@gmail.com: refactorizar zswap_store_page()] Enlace: https://lkml.kernel.org/r/20250131082037.2426-1-42.hyeyoo@gmail.com"
}
],
"lastModified": "2026-06-17T08:44:28.123",
"configurations": [
{
"nodes": [
{
"negate": false,
"cpeMatch": [
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"vulnerable": true,
"matchCriteriaId": "72E69ABB-9015-43A6-87E1-5150383CFFD9",
"versionEndExcluding": "6.13.5",
"versionStartIncluding": "6.13"
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc1:*:*:*:*:*:*",
"vulnerable": true,
"matchCriteriaId": "186716B6-2B66-4BD0-852E-D48E71C0C85F"
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc2:*:*:*:*:*:*",
"vulnerable": true,
"matchCriteriaId": "0D3E781C-403A-498F-9DA9-ECEE50F41E75"
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:6.14:rc3:*:*:*:*:*:*",
"vulnerable": true,
"matchCriteriaId": "66619FB8-0AAF-4166-B2CF-67B24143261D"
}
],
"operator": "OR"
}
]
}
],
"sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}