FAILED: patch "[PATCH] ocfs2: fix out-of-bounds write in ocfs2_write_end_inline" failed to apply to 6.18-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 7bc5da4842bed3252d26e742213741a4d0ac1b14
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026041350-tableware-passover-f18e@gregkh' --subject-prefix 'PATCH 6.18.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 7bc5da4842bed3252d26e742213741a4d0ac1b14 Mon Sep 17 00:00:00 2001
From: Joseph Qi <[email protected]>
Date: Fri, 3 Apr 2026 14:38:30 +0800
Subject: [PATCH] ocfs2: fix out-of-bounds write in ocfs2_write_end_inline
KASAN reports a use-after-free write of 4086 bytes in ocfs2_write_end_inline, called from ocfs2_write_end_nolock during a copy_file_range splice fallback on a corrupted ocfs2 filesystem mounted on a loop device. The actual bug is an out-of-bounds write past the inode block buffer, not a true use-after-free. The write overflows into an adjacent freed page, which KASAN reports as UAF.
The root cause is that ocfs2_try_to_write_inline_data trusts the on-disk id_count field to determine whether a write fits in inline data. On a corrupted filesystem, id_count can exceed the physical maximum inline data capacity, causing writes to overflow the inode block buffer.
Call trace (crash path):
vfs_copy_file_range (fs/read_write.c:1634)
do_splice_direct
splice_direct_to_actor
iter_file_splice_write
ocfs2_file_write_iter
generic_perform_write
ocfs2_write_end
ocfs2_write_end_nolock (fs/ocfs2/aops.c:1949)
ocfs2_write_end_inline (fs/ocfs2/aops.c:1915)
memcpy_from_folio <-- KASAN: write OOBSo add id_count upper bound check in ocfs2_validate_inode_block() to alongside the existing i_size check to fix it.
fs/ocfs2/inode.c +10 -0
@@ -1505,6 +1505,16 @@ int ocfs2_validate_inode_block(struct super_block *sb, goto bail; } +if (le16_to_cpu (data->id_count) > +ocfs2_max_inline_data_with_xattr (sb, di)) { + rc =ocfs2_error (sb, +"Invalid dinode #%llu: inline data id_count %u exceeds max %d\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (data->id_count), +ocfs2_max_inline_data_with_xattr (sb, di)); + goto bail; + } +if (le64_to_cpu (di->i_size) >le16_to_cpu (data->id_count)) { rc = ocfs2_error(sb, "Invalid dinode #%llu: inline data i_size %llu exceeds id_count %u\n",
Sasha Levin
maintainerPATCH 1/3 ocfs2: add inline inode consistency check to ocfs2_validate_inode_block()
From: Dmitry Antipov <[email protected]>
[ Upstream commit a2b1c419ff72ec62ff5831684e30cd1d4f0b09ee ]
In 'ocfs2_validate_inode_block()', add an extra check whether an inode with inline data (i.e. self-contained) has no clusters, thus preventing an invalid inode from being passed to 'ocfs2_evict_inode()' and below.
Stable-dep-of: 7bc5da4842be ("ocfs2: fix out-of-bounds write in ocfs2_write_end_inline")
--- fs/ocfs2/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/ocfs2/inode.c +8 -0
@@ -1505,6 +1505,14 @@ int ocfs2_validate_inode_block(struct super_block *sb, goto bail; } +if ((le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) && +le32_to_cpu (di->i_clusters)) { + rc =ocfs2_error (sb,"Invalid dinode %llu: %u clusters\n" , + (unsigned long long )bh->b_blocknr, +le32_to_cpu (di->i_clusters)); + goto bail; + } + rc =0 ; bail:
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 ocfs2: validate inline data i_size during inode read
From: Deepanshu Kartikey <[email protected]>
[ Upstream commit 1524af3685b35feac76662cc551cbc37bd14775f ]
When reading an inode from disk, ocfs2_validate_inode_block() performs various sanity checks but does not validate the size of inline data. If the filesystem is corrupted, an inode's i_size can exceed the actual inline data capacity (id_count).
This causes ocfs2_dir_foreach_blk_id() to iterate beyond the inline data buffer, triggering a use-after-free when accessing directory entries from freed memory.
In the syzbot report:
- i_size was 1099511627576 bytes (~1TB)
- Actual inline data capacity (id_count) is typically <256 bytes
- A garbage rec_len (54648) caused ctx->pos to jump out of bounds
- This triggered a UAF in ocfs2_check_dir_entry()
Fix by adding a validation check in ocfs2_validate_inode_block() to ensure inodes with inline data have i_size <= id_count. This catches the corruption early during inode read and prevents all downstream code from operating on invalid data.
Stable-dep-of: 7bc5da4842be ("ocfs2: fix out-of-bounds write in ocfs2_write_end_inline")
--- fs/ocfs2/inode.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
fs/ocfs2/inode.c +19 -6
@@ -1505,12 +1505,25 @@ int ocfs2_validate_inode_block(struct super_block *sb, goto bail; } -if ((le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) && -le32_to_cpu (di->i_clusters)) { - rc =ocfs2_error (sb,"Invalid dinode %llu: %u clusters\n" , - (unsigned long long )bh->b_blocknr, -le32_to_cpu (di->i_clusters)); - goto bail; +if (le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) { +struct ocfs2_inline_data *data = &di->id2.i_data; + +if (le32_to_cpu (di->i_clusters)) { + rc =ocfs2_error (sb, +"Invalid dinode %llu: %u clusters\n" , + (unsigned long long )bh->b_blocknr, +le32_to_cpu (di->i_clusters)); + goto bail; + } + +if (le64_to_cpu (di->i_size) >le16_to_cpu (data->id_count)) { + rc =ocfs2_error (sb, +"Invalid dinode #%llu: inline data i_size %llu exceeds id_count %u\n" , + (unsigned long long )bh->b_blocknr, + (unsigned long long )le64_to_cpu (di->i_size), +le16_to_cpu (data->id_count)); + goto bail; + } } rc =0 ;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 ocfs2: fix out-of-bounds write in ocfs2_write_end_inline
In reply to Sasha LevinFrom: Joseph Qi <[email protected]>
[ Upstream commit 7bc5da4842bed3252d26e742213741a4d0ac1b14 ]
KASAN reports a use-after-free write of 4086 bytes in ocfs2_write_end_inline, called from ocfs2_write_end_nolock during a copy_file_range splice fallback on a corrupted ocfs2 filesystem mounted on a loop device. The actual bug is an out-of-bounds write past the inode block buffer, not a true use-after-free. The write overflows into an adjacent freed page, which KASAN reports as UAF.
The root cause is that ocfs2_try_to_write_inline_data trusts the on-disk id_count field to determine whether a write fits in inline data. On a corrupted filesystem, id_count can exceed the physical maximum inline data capacity, causing writes to overflow the inode block buffer.
Call trace (crash path):
vfs_copy_file_range (fs/read_write.c:1634)
do_splice_direct
splice_direct_to_actor
iter_file_splice_write
ocfs2_file_write_iter
generic_perform_write
ocfs2_write_end
ocfs2_write_end_nolock (fs/ocfs2/aops.c:1949)
ocfs2_write_end_inline (fs/ocfs2/aops.c:1915)
memcpy_from_folio <-- KASAN: write OOBSo add id_count upper bound check in ocfs2_validate_inode_block() to alongside the existing i_size check to fix it.
--- fs/ocfs2/inode.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/ocfs2/inode.c +10 -0
@@ -1516,6 +1516,16 @@ int ocfs2_validate_inode_block(struct super_block *sb, goto bail; } +if (le16_to_cpu (data->id_count) > +ocfs2_max_inline_data_with_xattr (sb, di)) { + rc =ocfs2_error (sb, +"Invalid dinode #%llu: inline data id_count %u exceeds max %d\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (data->id_count), +ocfs2_max_inline_data_with_xattr (sb, di)); + goto bail; + } +if (le64_to_cpu (di->i_size) >le16_to_cpu (data->id_count)) { rc = ocfs2_error(sb, "Invalid dinode #%llu: inline data i_size %llu exceeds id_count %u\n",
Signature · 1 line
2.53.0