In the Linux kernel, the following vulnerability has been resolved:
f2fs: only redirty pinned folios in redirty_blocks
redirty_blocks() pins folios with read_cache_folio() and then walks the
same range again with filemap_lock_folio() to redirty them and drop the
references it took.
Commit 5951fee46bef ("f2fs: Use a folio in redirty_blocks()") changed
the second pass to a do/while loop. If read_cache_folio() fails before
anything is pinned, page_idx does not advance but the cleanup loop still
runs once.
If readahead has already populated the failed folio in page cache, that
extra iteration finds it and folio_put_refs(folio, 2) drops one
reference too many. Later drop_caches or reclaim can then report
"BUG: Bad page state".
Only redirty the range that was pinned successfully.
CVSS Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CVSS Score: 7.8
AV:L - redirty_blocks() is reached only via local F2FS_IOC_COMPRESS_FILE/F2FS_IOC_DECOMPRESS_FILE ioctls (f2fs_ioctl → f2fs_ioc_{compress,decompress}_file) on a mounted f2fs file; these are not network, Bluetooth, or USB protocol handlers.
AC:L - The attacker drives the ioctl and can force the first read_cache_folio() to fail (memcg/ENOMEM, or a fatal signal during the killable wait after readahead inserted the folio), so the do/while cleanup always runs once; no victim-timed race or layout outside their control is required.
PR:L - Neither ioctl checks capable()/CAP_SYS_ADMIN; they need only a writable fd (FMODE_WRITE) of a compression-enabled file, and owners can set FS_COMPR_FL via FS_IOC_SETFLAGS/chattr +c on Android/embedded f2fs userdata with compress_mode=user.
UI:N - On typical f2fs deployments (Android userdata already mounted with compression/compress_mode=user) the attacker creates or opens their own file and issues the ioctl with no victim mount, open, or other action.
S:U - Page-cache refcount underflow and the resulting kernel oops stay inside the host kernel's security authority; this is not a VM guest-to-host escape, IOMMU bypass, or sandbox breakout.
C:H - The extra folio_put_refs(folio, 2) drops the page-cache reference and can free a folio still indexed in mapping->i_pages; that use-after-free of page-cache memory is a read primitive for arbitrary kernel/user data.
I:H - The same underflow lets the freed folio be reused while still in the mapping (the stray pass also dirties and unlocks it), yielding a write primitive usable for control-flow hijack.
A:H - If the folio is absent, filemap_lock_folio() returns ERR_PTR(-ENOENT) and production f2fs_bug_on() WARNs then dereferences it (oops); the extra-put path reports BUG: Bad page state on reclaim/drop_caches and can panic.
| Attack Vector |
Local |
Scope |
Unchanged |
| Attack Complexity |
Low |
Confidentiality Impact |
High |
| Privileges Required |
Low |
Integrity Impact |
High |
| User Interaction |
None |
Availability Impact |
High |
AV:L - redirty_blocks() is reached only via local F2FS_IOC_COMPRESS_FILE/F2FS_IOC_DECOMPRESS_FILE ioctls (f2fs_ioctl → f2fs_ioc_{compress,decompress}_file) on a mounted f2fs file; these are not network, Bluetooth, or USB protocol handlers.
AC:L - The attacker drives the ioctl and can force the first read_cache_folio() to fail (memcg/ENOMEM, or a fatal signal during the killable wait after readahead inserted the folio), so the do/while cleanup always runs once; no victim-timed race or layout outside their control is required.
PR:L - Neither ioctl checks capable()/CAP_SYS_ADMIN; they need only a writable fd (FMODE_WRITE) of a compression-enabled file, and owners can set FS_COMPR_FL via FS_IOC_SETFLAGS/chattr +c on Android/embedded f2fs userdata with compress_mode=user.
UI:N - On typical f2fs deployments (Android userdata already mounted with compression/compress_mode=user) the attacker creates or opens their own file and issues the ioctl with no victim mount, open, or other action.
S:U - Page-cache refcount underflow and the resulting kernel oops stay inside the host kernel's security authority; this is not a VM guest-to-host escape, IOMMU bypass, or sandbox breakout.
C:H - The extra folio_put_refs(folio, 2) drops the page-cache reference and can free a folio still indexed in mapping->i_pages; that use-after-free of page-cache memory is a read primitive for arbitrary kernel/user data.
I:H - The same underflow lets the freed folio be reused while still in the mapping (the stray pass also dirties and unlocks it), yielding a write primitive usable for control-flow hijack.
A:H - If the folio is absent, filemap_lock_folio() returns ERR_PTR(-ENOENT) and production f2fs_bug_on() WARNs then dereferences it (oops); the extra-put path reports BUG: Bad page state on reclaim/drop_caches and can panic.
CVSS 3.1