{"resultsPerPage":1,"startIndex":0,"totalResults":1,"format":"NVD_CVE","version":"2.0","timestamp":"2026-04-18T12:42:02.124","vulnerabilities":[{"cve":{"id":"CVE-2026-23233","sourceIdentifier":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","published":"2026-03-04T15:16:13.603","lastModified":"2026-03-17T21:21:30.687","vulnStatus":"Analyzed","cveTags":[],"descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nf2fs: fix to avoid mapping wrong physical block for swapfile\n\nXiaolong Guo reported a f2fs bug in bugzilla [1]\n\n[1] https://bugzilla.kernel.org/show_bug.cgi?id=220951\n\nQuoted:\n\n\"When using stress-ng's swap stress test on F2FS filesystem with kernel 6.6+,\nthe system experiences data corruption leading to either:\n1 dm-verity corruption errors and device reboot\n2 F2FS node corruption errors and boot hangs\n\nThe issue occurs specifically when:\n1 Using F2FS filesystem (ext4 is unaffected)\n2 Swapfile size is less than F2FS section size (2MB)\n3 Swapfile has fragmented physical layout (multiple non-contiguous extents)\n4 Kernel version is 6.6+ (6.1 is unaffected)\n\nThe root cause is in check_swap_activate() function in fs/f2fs/data.c. When the\nfirst extent of a small swapfile (< 2MB) is not aligned to section boundaries,\nthe function incorrectly treats it as the last extent, failing to map\nsubsequent extents. This results in incorrect swap_extent creation where only\nthe first extent is mapped, causing subsequent swap writes to overwrite wrong\nphysical locations (other files' data).\n\nSteps to Reproduce\n1 Setup a device with F2FS-formatted userdata partition\n2 Compile stress-ng from https://github.com/ColinIanKing/stress-ng\n3 Run swap stress test: (Android devices)\nadb shell \"cd /data/stressng; ./stress-ng-64 --metrics-brief --timeout 60\n--swap 0\"\n\nLog:\n1 Ftrace shows in kernel 6.6, only first extent is mapped during second\nf2fs_map_blocks call in check_swap_activate():\nstress-ng-swap-8990: f2fs_map_blocks: ino=11002, file offset=0, start\nblkaddr=0x43143, len=0x1\n(Only 4KB mapped, not the full swapfile)\n2 in kernel 6.1, both extents are correctly mapped:\nstress-ng-swap-5966: f2fs_map_blocks: ino=28011, file offset=0, start\nblkaddr=0x13cd4, len=0x1\nstress-ng-swap-5966: f2fs_map_blocks: ino=28011, file offset=1, start\nblkaddr=0x60c84b, len=0xff\n\nThe problematic code is in check_swap_activate():\nif ((pblock - SM_I(sbi)->main_blkaddr) % blks_per_sec ||\n    nr_pblocks % blks_per_sec ||\n    !f2fs_valid_pinned_area(sbi, pblock)) {\n    bool last_extent = false;\n\n    not_aligned++;\n\n    nr_pblocks = roundup(nr_pblocks, blks_per_sec);\n    if (cur_lblock + nr_pblocks > sis->max)\n        nr_pblocks -= blks_per_sec;\n\n    /* this extent is last one */\n    if (!nr_pblocks) {\n        nr_pblocks = last_lblock - cur_lblock;\n        last_extent = true;\n    }\n\n    ret = f2fs_migrate_blocks(inode, cur_lblock, nr_pblocks);\n    if (ret) {\n        if (ret == -ENOENT)\n            ret = -EINVAL;\n        goto out;\n    }\n\n    if (!last_extent)\n        goto retry;\n}\n\nWhen the first extent is unaligned and roundup(nr_pblocks, blks_per_sec)\nexceeds sis->max, we subtract blks_per_sec resulting in nr_pblocks = 0. The\ncode then incorrectly assumes this is the last extent, sets nr_pblocks =\nlast_lblock - cur_lblock (entire swapfile), and performs migration. After\nmigration, it doesn't retry mapping, so subsequent extents are never processed.\n\"\n\nIn order to fix this issue, we need to lookup block mapping info after\nwe migrate all blocks in the tail of swapfile."},{"lang":"es","value":"En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta:\n\nf2fs: corrección para evitar mapear un bloque físico incorrecto para el archivo de intercambio\n\nXiaolong Guo informó de un error de f2fs en bugzilla [1]\n\n[1] HTTPS://bugzilla.kernel.org/show_bug.cgi?id=220951\n\nCitado:\n\nCuando se utiliza la prueba de estrés de intercambio de stress-ng en el sistema de archivos F2FS con kernel 6.6+, el sistema experimenta corrupción de datos que lleva a una de las siguientes situaciones:\n1 errores de corrupción de dm-verity y reinicio del dispositivo\n2 errores de corrupción de nodo F2FS y cuelgues de arranque\n\nEl problema ocurre específicamente cuando:\n1 Se utiliza el sistema de archivos F2FS (ext4 no se ve afectado)\n2 El tamaño del archivo de intercambio es menor que el tamaño de sección de F2FS (2MB)\n3 El archivo de intercambio tiene un diseño físico fragmentado (múltiples extensiones no contiguas)\n4 La versión del kernel es 6.6+ (6.1 no se ve afectada)\n\nLa causa raíz está en la función check_swap_activate() en fs/f2fs/data.c. Cuando la primera extensión de un archivo de intercambio pequeño (&lt; 2MB) no está alineada con los límites de sección, la función lo trata incorrectamente como la última extensión, fallando en mapear extensiones subsiguientes. Esto resulta en una creación incorrecta de swap_extent donde solo la primera extensión es mapeada, causando que las escrituras de intercambio subsiguientes sobrescriban ubicaciones físicas incorrectas (datos de otros archivos).\n\nPasos para Reproducir\n1 Configurar un dispositivo con una partición de datos de usuario formateada en F2FS\n2 Compilar stress-ng desde HTTPS://github.com/ColinIanKing/stress-ng\n3 Ejecutar la prueba de estrés de intercambio: (dispositivos Android)\nadb shell 'cd /data/stressng; ./stress-ng-64 --metrics-brief --timeout 60 --swap 0'\n\nRegistro:\n1 Ftrace muestra que en el kernel 6.6, solo la primera extensión se mapea durante la segunda llamada a f2fs_map_blocks en check_swap_activate():\nstress-ng-swap-8990: f2fs_map_blocks: ino=11002, file offset=0, start blkaddr=0x43143, len=0x1\n(Solo 4KB mapeados, no el archivo de intercambio completo)\n2 en el kernel 6.1, ambas extensiones se mapean correctamente:\nstress-ng-swap-5966: f2fs_map_blocks: ino=28011, file offset=0, start blkaddr=0x13cd4, len=0x1\nstress-ng-swap-5966: f2fs_map_blocks: ino=28011, file offset=1, start blkaddr=0x60c84b, len=0xff\n\nEl código problemático está en check_swap_activate():\nif ((pblock - SM_I(sbi)-&gt;main_blkaddr) % blks_per_sec ||\n    nr_pblocks % blks_per_sec ||\n    !f2fs_valid_pinned_area(sbi, pblock)) {\n    bool last_extent = false;\n\n    not_aligned++;\n\n    nr_pblocks = roundup(nr_pblocks, blks_per_sec);\n    if (cur_lblock + nr_pblocks &gt; sis-&gt;max)\n        nr_pblocks -= blks_per_sec;\n\n    /* esta extensión es la última */\n    if (!nr_pblocks) {\n        nr_pblocks = last_lblock - cur_lblock;\n        last_extent = true;\n    }\n\n    ret = f2fs_migrate_blocks(inode, cur_lblock, nr_pblocks);\n    if (ret) {\n        if (ret == -ENOENT)\n            ret = -EINVAL;\n        goto out;\n    }\n\n    if (!last_extent)\n        goto retry;\n}\n\nCuando la primera extensión no está alineada y roundup(nr_pblocks, blks_per_sec) excede sis-&gt;max, restamos blks_per_sec resultando en nr_pblocks = 0. El código asume incorrectamente que esta es la última extensión, establece nr_pblocks = last_lblock - cur_lblock (archivo de intercambio completo), y realiza la migración. Después de la migración, no reintenta el mapeo, por lo que las extensiones subsiguientes nunca se procesan.\n\nPara solucionar este problema, necesitamos buscar la información de mapeo de bloques después de migrar todos los bloques en la cola del archivo de intercambio."}],"metrics":{"cvssMetricV31":[{"source":"nvd@nist.gov","type":"Primary","cvssData":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","baseScore":7.8,"baseSeverity":"HIGH","attackVector":"LOCAL","attackComplexity":"LOW","privilegesRequired":"LOW","userInteraction":"NONE","scope":"UNCHANGED","confidentialityImpact":"HIGH","integrityImpact":"HIGH","availabilityImpact":"HIGH"},"exploitabilityScore":1.8,"impactScore":5.9}]},"weaknesses":[{"source":"nvd@nist.gov","type":"Primary","description":[{"lang":"en","value":"CWE-787"}]}],"configurations":[{"nodes":[{"operator":"OR","negate":false,"cpeMatch":[{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.6.33","versionEndExcluding":"6.6.127","matchCriteriaId":"9F91BA22-77B9-4D50-8EDF-CF73844D56F2"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.9","versionEndExcluding":"6.12.74","matchCriteriaId":"78063C1B-6788-4C2F-AB8B-2EE10C43515A"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.13","versionEndExcluding":"6.18.13","matchCriteriaId":"6BDEF9FB-423E-49F6-991B-9277CC3AF400"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.19","versionEndExcluding":"6.19.3","matchCriteriaId":"7853A337-FB2A-4E19-AB47-4E38343532AA"}]}]}],"references":[{"url":"https://git.kernel.org/stable/c/1ff415eef513bf12deb058fc50d57788c46c48e6","source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":["Patch"]},{"url":"https://git.kernel.org/stable/c/5c145c03188bc9ba1c29e0bc4d527a5978fc47f9","source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":["Patch"]},{"url":"https://git.kernel.org/stable/c/607cb9d83838d2cd9f0406c2403ed61aadf0edff","source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":["Patch"]},{"url":"https://git.kernel.org/stable/c/d4534a7f6c92baaf7e12a45fc6e37332cafafc33","source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":["Patch"]},{"url":"https://git.kernel.org/stable/c/fee27b69dde1a05908b350eea42937af2387c4fe","source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":["Patch"]}]}}]}