* [PATCH] ext4: convert inline data to extents when truncate exceeds inline size
@ 2026-02-07 4:36 Deepanshu Kartikey
2026-02-11 15:46 ` Christoph Hellwig
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Deepanshu Kartikey @ 2026-02-07 4:36 UTC (permalink / raw)
To: tytso, adilger.kernel
Cc: linux-ext4, linux-kernel, Deepanshu Kartikey,
syzbot+7de5fe447862fc37576f, Deepanshu Kartikey
Add a check in ext4_setattr() to convert files from inline data storage
to extent-based storage when truncate() grows the file size beyond the
inline capacity. This prevents the filesystem from entering an
inconsistent state where the inline data flag is set but the file size
exceeds what can be stored inline.
Without this fix, the following sequence causes a kernel BUG_ON():
1. Mount filesystem with inode that has inline flag set and small size
2. truncate(file, 50MB) - grows size but inline flag remains set
3. sendfile() attempts to write data
4. ext4_write_inline_data() hits BUG_ON(write_size > inline_capacity)
The crash occurs because ext4_write_inline_data() expects inline storage
to accommodate the write, but the actual inline capacity (~60 bytes for
i_block + ~96 bytes for xattrs) is far smaller than the file size and
write request.
The fix checks if the new size from setattr exceeds the inode's actual
inline capacity (EXT4_I(inode)->i_inline_size) and converts the file to
extent-based storage before proceeding with the size change.
This addresses the root cause by ensuring the inline data flag and file
size remain consistent during truncate operations.
Reported-by: syzbot+7de5fe447862fc37576f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=7de5fe447862fc37576f
Tested-by: syzbot+7de5fe447862fc37576f@syzkaller.appspotmail.com
Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
---
fs/ext4/inode.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 0c466ccbed69..c3dc0422ff95 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5901,6 +5901,18 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
if (attr->ia_size == inode->i_size)
inc_ivers = false;
+ /*
+ * If file has inline data but new size exceeds inline capacity,
+ * convert to extent-based storage first to prevent inconsistent
+ * state (inline flag set but size exceeds inline capacity).
+ */
+ if (ext4_has_inline_data(inode) &&
+ attr->ia_size > EXT4_I(inode)->i_inline_size) {
+ error = ext4_convert_inline_data(inode);
+ if (error)
+ goto err_out;
+ }
+
if (shrink) {
if (ext4_should_order_data(inode)) {
error = ext4_begin_ordered_truncate(inode,
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] ext4: convert inline data to extents when truncate exceeds inline size
2026-02-07 4:36 [PATCH] ext4: convert inline data to extents when truncate exceeds inline size Deepanshu Kartikey
@ 2026-02-11 15:46 ` Christoph Hellwig
2026-02-12 1:14 ` Deepanshu Kartikey
2026-03-10 1:50 ` Deepanshu Kartikey
2026-03-26 11:57 ` Theodore Ts'o
2 siblings, 1 reply; 5+ messages in thread
From: Christoph Hellwig @ 2026-02-11 15:46 UTC (permalink / raw)
To: Deepanshu Kartikey
Cc: tytso, adilger.kernel, linux-ext4, linux-kernel,
syzbot+7de5fe447862fc37576f
On Sat, Feb 07, 2026 at 10:06:07AM +0530, Deepanshu Kartikey wrote:
> Without this fix, the following sequence causes a kernel BUG_ON():
>
> 1. Mount filesystem with inode that has inline flag set and small size
> 2. truncate(file, 50MB) - grows size but inline flag remains set
> 3. sendfile() attempts to write data
> 4. ext4_write_inline_data() hits BUG_ON(write_size > inline_capacity)
Can you wirte this up in an xfstests test, please?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ext4: convert inline data to extents when truncate exceeds inline size
2026-02-11 15:46 ` Christoph Hellwig
@ 2026-02-12 1:14 ` Deepanshu Kartikey
0 siblings, 0 replies; 5+ messages in thread
From: Deepanshu Kartikey @ 2026-02-12 1:14 UTC (permalink / raw)
To: Christoph Hellwig
Cc: tytso, adilger.kernel, linux-ext4, linux-kernel,
syzbot+7de5fe447862fc37576f
On Wed, Feb 11, 2026 at 9:16 PM Christoph Hellwig <hch@infradead.org> wrote:
>
> On Sat, Feb 07, 2026 at 10:06:07AM +0530, Deepanshu Kartikey wrote:
> > Without this fix, the following sequence causes a kernel BUG_ON():
> >
> > 1. Mount filesystem with inode that has inline flag set and small size
> > 2. truncate(file, 50MB) - grows size but inline flag remains set
> > 3. sendfile() attempts to write data
> > 4. ext4_write_inline_data() hits BUG_ON(write_size > inline_capacity)
>
> Can you wirte this up in an xfstests test, please?
>
I will write the test case and share the patch shortly.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ext4: convert inline data to extents when truncate exceeds inline size
2026-02-07 4:36 [PATCH] ext4: convert inline data to extents when truncate exceeds inline size Deepanshu Kartikey
2026-02-11 15:46 ` Christoph Hellwig
@ 2026-03-10 1:50 ` Deepanshu Kartikey
2026-03-26 11:57 ` Theodore Ts'o
2 siblings, 0 replies; 5+ messages in thread
From: Deepanshu Kartikey @ 2026-03-10 1:50 UTC (permalink / raw)
To: tytso, adilger.kernel
Cc: linux-ext4, linux-kernel, syzbot+7de5fe447862fc37576f
On Sat, Feb 7, 2026 at 10:06 AM Deepanshu Kartikey
<kartikey406@gmail.com> wrote:
>
> Add a check in ext4_setattr() to convert files from inline data storage
> to extent-based storage when truncate() grows the file size beyond the
> inline capacity. This prevents the filesystem from entering an
> inconsistent state where the inline data flag is set but the file size
> exceeds what can be stored inline.
>
> Without this fix, the following sequence causes a kernel BUG_ON():
>
> 1. Mount filesystem with inode that has inline flag set and small size
> 2. truncate(file, 50MB) - grows size but inline flag remains set
> 3. sendfile() attempts to write data
> 4. ext4_write_inline_data() hits BUG_ON(write_size > inline_capacity)
>
> The crash occurs because ext4_write_inline_data() expects inline storage
> to accommodate the write, but the actual inline capacity (~60 bytes for
> i_block + ~96 bytes for xattrs) is far smaller than the file size and
> write request.
>
> The fix checks if the new size from setattr exceeds the inode's actual
> inline capacity (EXT4_I(inode)->i_inline_size) and converts the file to
> extent-based storage before proceeding with the size change.
>
> This addresses the root cause by ensuring the inline data flag and file
> size remain consistent during truncate operations.
>
> Reported-by: syzbot+7de5fe447862fc37576f@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=7de5fe447862fc37576f
> Tested-by: syzbot+7de5fe447862fc37576f@syzkaller.appspotmail.com
> Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
> ---
> fs/ext4/inode.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 0c466ccbed69..c3dc0422ff95 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5901,6 +5901,18 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> if (attr->ia_size == inode->i_size)
> inc_ivers = false;
>
> + /*
> + * If file has inline data but new size exceeds inline capacity,
> + * convert to extent-based storage first to prevent inconsistent
> + * state (inline flag set but size exceeds inline capacity).
> + */
> + if (ext4_has_inline_data(inode) &&
> + attr->ia_size > EXT4_I(inode)->i_inline_size) {
> + error = ext4_convert_inline_data(inode);
> + if (error)
> + goto err_out;
> + }
> +
> if (shrink) {
> if (ext4_should_order_data(inode)) {
> error = ext4_begin_ordered_truncate(inode,
> --
> 2.43.0
>
Hi Ted, Andreas, and ext4 maintainers,
I submitted this patch on February 7th to fix a kernel BUG_ON in
ext4_write_inline_data() reported by syzbot:
https://syzkaller.appspot.com/bug?extid=7de5fe447862fc37576f
The patch adds inline->extent conversion in ext4_setattr() when truncate()
grows a file beyond inline capacity, preventing the filesystem from entering
an inconsistent state where the inline flag is set but size exceeds capacity.
I wanted to follow up to see if there are any comments or feedback on the
approach.
Original patch:
https://lore.kernel.org/all/20260207043607.1175976-1-kartikey406@gmail.com/T/
Thanks,
Deepanshu Kartikey
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ext4: convert inline data to extents when truncate exceeds inline size
2026-02-07 4:36 [PATCH] ext4: convert inline data to extents when truncate exceeds inline size Deepanshu Kartikey
2026-02-11 15:46 ` Christoph Hellwig
2026-03-10 1:50 ` Deepanshu Kartikey
@ 2026-03-26 11:57 ` Theodore Ts'o
2 siblings, 0 replies; 5+ messages in thread
From: Theodore Ts'o @ 2026-03-26 11:57 UTC (permalink / raw)
To: adilger.kernel, Deepanshu Kartikey
Cc: Theodore Ts'o, linux-ext4, linux-kernel,
syzbot+7de5fe447862fc37576f, Deepanshu Kartikey
On Sat, 07 Feb 2026 10:06:07 +0530, Deepanshu Kartikey wrote:
> Add a check in ext4_setattr() to convert files from inline data storage
> to extent-based storage when truncate() grows the file size beyond the
> inline capacity. This prevents the filesystem from entering an
> inconsistent state where the inline data flag is set but the file size
> exceeds what can be stored inline.
>
> Without this fix, the following sequence causes a kernel BUG_ON():
>
> [...]
Applied, thanks!
[1/1] ext4: convert inline data to extents when truncate exceeds inline size
commit: ea3ec364b624093c46426269a34cf7568af6d6cf
Best regards,
--
Theodore Ts'o <tytso@mit.edu>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-03-26 11:58 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-07 4:36 [PATCH] ext4: convert inline data to extents when truncate exceeds inline size Deepanshu Kartikey
2026-02-11 15:46 ` Christoph Hellwig
2026-02-12 1:14 ` Deepanshu Kartikey
2026-03-10 1:50 ` Deepanshu Kartikey
2026-03-26 11:57 ` Theodore Ts'o
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox