In the Linux kernel, the following vulnerability has been resolved:
fs/erofs/fileio: call erofsonlinefoliosplit() after bioaddfolio()
If bioaddfolio() fails (because it is full),
erofsfileioscanfolio() needs to submit the I/O request via
erofsfileiorqsubmit() and allocate a new I/O request with an empty
struct bio. Then it retries the bioaddfolio() call.
However, at this point, erofsonlinefoliosplit() has already been
called which increments folio->private; the retry will call
erofsonlinefoliosplit() again, but there will never be a matching
erofsonlinefolioend() call. This leaves the folio locked forever
and all waiters will be stuck in foliowaitbit_common().
This bug has been added by commit ce63cb62d794 ("erofs: support
unencoded inodes for fileio"), but was practically unreachable because
there was room for 256 folios in the struct bio - until commit
9f74ae8c9ac9 ("erofs: shorten bvecs[] for file-backed mounts") which
reduced the array capacity to 16 folios.
It was now trivial to trigger the bug by manually invoking readahead from userspace, e.g.:
posixfadvise(fd, 0, st.stsize, POSIXFADVWILLNEED);
This should be fixed by invoking erofsonlinefoliosplit() only after bioaddfolio() has succeeded. This is safe: asynchronous completions invoking erofsonlinefolioend() will not unlock the folio because erofsfileioscanfolio() is still holding a reference to be released by erofsonlinefolio_end() at the end.
[
{
"id": "CVE-2025-37999-0ee8c225",
"target": {
"file": "fs/erofs/fileio.c",
"function": "erofs_fileio_scan_folio"
},
"digest": {
"length": 1855.0,
"function_hash": "130880858593715943446735613263357937355"
},
"deprecated": false,
"signature_type": "Function",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@bbfe756dc3062c1e934f06e5ba39c239aa953b92",
"signature_version": "v1"
},
{
"id": "CVE-2025-37999-4ffb09d8",
"target": {
"file": "fs/erofs/fileio.c"
},
"digest": {
"threshold": 0.9,
"line_hashes": [
"318253438087067599579888027350090629439",
"146446731652862586092523942406289633614",
"14817472168763304243604047258410759882",
"139204512901480416080911156232917359591",
"57550605146305862792662997718651877286",
"157613367902166321856057733045913389464",
"18984984930957773712600658872292994105"
]
},
"deprecated": false,
"signature_type": "Line",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@c26076197df348c84cc23e5962d61902e072a0f5",
"signature_version": "v1"
},
{
"id": "CVE-2025-37999-8e7b75ae",
"target": {
"file": "fs/erofs/fileio.c",
"function": "erofs_fileio_scan_folio"
},
"digest": {
"length": 1861.0,
"function_hash": "310180236282678387323779868639272353850"
},
"deprecated": false,
"signature_type": "Function",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@c26076197df348c84cc23e5962d61902e072a0f5",
"signature_version": "v1"
},
{
"id": "CVE-2025-37999-8fa0f415",
"target": {
"file": "fs/erofs/fileio.c"
},
"digest": {
"threshold": 0.9,
"line_hashes": [
"318253438087067599579888027350090629439",
"146446731652862586092523942406289633614",
"14817472168763304243604047258410759882",
"139204512901480416080911156232917359591",
"57550605146305862792662997718651877286",
"157613367902166321856057733045913389464",
"18984984930957773712600658872292994105"
]
},
"deprecated": false,
"signature_type": "Line",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@bbfe756dc3062c1e934f06e5ba39c239aa953b92",
"signature_version": "v1"
}
]