Linux EXT4 FS development
 help / color / mirror / Atom feed
* Re: [PATCH next] ext4: Fix diagnostic printf formats
From: Andy Shevchenko @ 2026-03-27 10:48 UTC (permalink / raw)
  To: david.laight.linux
  Cc: Theodore Ts'o, Andreas Dilger, linux-ext4, linux-kernel,
	Masami Hiramatsu, Petr Mladek, Rasmus Villemoes, Steven Rostedt,
	Sergey Senozhatsky, Andrew Morton
In-Reply-To: <20260326201804.3881-1-david.laight.linux@gmail.com>

On Thu, Mar 26, 2026 at 08:18:04PM +0000, david.laight.linux@gmail.com wrote:

> The formats for non-terminated names should be "%.*s" not "%*.s".
> The kernel currently treats "%*.s" as equivalent to "%*s" whereas
> userspace requires it be equivalent to "%*.0s".
> Neither is correct here.

This entire code seems was never tested properly and it's a dead code
until one defines manually DX_DEBUG. It also has tons of plain printk()
calls that may behave differently if the first character is not printable
but maps to the level of printk().

I'm not sure how your patch helps with all that, but apparently the
printed data has to be NUL-terminated, otherwise I have no idea how
it was ever working without crashes.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH] ovl: make fsync after metadata copy-up opt-in mount option
From: Amir Goldstein @ 2026-03-27 11:09 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Miklos Szeredi, Christian Brauner, linux-fsdevel, linux-unionfs,
	Fei Lv, Chenglong Tang, stable, Theodore Tso, Ext4
In-Reply-To: <acYZglh4iyauvDZj@infradead.org>

[CC ext4]

On Fri, Mar 27, 2026 at 6:45 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> On Wed, Mar 25, 2026 at 02:11:31PM +0100, Amir Goldstein wrote:
> > When an overlayfs file is modified for the first time, copy up will
> > create a copy of the lower file and its parent directories in the upper
> > layer.  Since the Linux filesystem API does not enforce any particular
> > ordering on storing changes without explicit fsync(2) calls, in case
> > of a system crash, the upper file could end up with no data at all
> > (i.e. zeros), which would be an unusual outcome.  To avoid this
> > experience, overlayfs calls fsync(2) on the upper file before completing
> > data copy up with rename(2) to make the copy up "atomic".
>
> Sounds good so far.
>
> > By default, overlayfs does not call fsync(2) on copied up directories,
> > so after a crash, a copied up directory could be observed in the upper
> > layer without some of its attributes.
>
> This does sound a bit scary.  How does a directory copy up work?
> mkdir + adding the copies up entries, probably with some chmod or
> chown thrown in?
>

Don't worry, there is no attempt to implement "directory content copy up"

There is only "directory inode copy up"
or in a more generic description there is:
1. "inode metadata copy up" - attributes, xattr and some fileattr
2. "inode data copy up"

Copy up of directory a is:
mkdir workdir/tmpdir
set attrs on workdir/tmpdir
fsync workdir/tmpdir (fsync == strict)
mv workdir/tmpdir upperdir/a

Copy up of a/b/c/file is
copy up a (if needed)
copy up a/b (if needed)
copy up a/b/c (if needed)
open O_TMPFILE
write data to tmpfile
fsync tmpfile (fsync != volatile)
set attr on tmpfile
fsync tmpfile (fsync == strict)
link tmpfile to upperdir/a/b/c/file

But note that the trigger to copy up is file data or metadata modification.
Overlayfs provides no guarantee to persist the modification unless
user does fsync themselves.

Overlayfs only provides the guarantee that if the copy up is observed,
the observed data is not zeros because data is synced before the link(2).

> > - "ordered": (default)
> >     Call fsync(2) on upper file before completion of data copy up.
> >     No fsync(2) is called on directory or metadata-only copy up.
>
> "ordered" sounds like an odd name here.  It's more like lazy or

The inspiration is the journal=orderded mode which provides
similar guarantee to ext4 (after the delalloc mitigation) -
no zeros observed after write+rename even without  explicit fsync.

> "nodirfsync".  And it might help to explain what this implies, which
> is that the fsync on the files in the directory also sync the
> directories out, because they are usually modified in the same
> transaction, and a traditional simple log model implies that.  That
> traditional single log model also implies that you get the metadata
> file fsync for free in that case.  I.e. if you did:

I wish to avoid a naming discussion, so this is going to be fsync=auto
and documentation will elaborate on what it does.
See rephrased doc below.

>
>         for each file:
>                 sync_file_range(file, .., SYNC_FILE_RANGE_WRITE |
>                                     SYNC_FILE_RANGE_WAIT_AFTER);
>
>         fsync(dir)
>         for each file:
>                 fsync(file)

This doesn't happen but I get what you mean.

>
> at least for xfs (and probably the others) you should get the
> performance of your ordered mode with the durability guarantees
> of the strict version.
>

Honestly, we did not think that adding fsync on the parent dirs
would impact performance so much, that is why we did not
do this opt-in to begin with.

My guess is that ext4 fell from a fast commit workload to
non-fast commit workload due to this change.

If ext4 developers want to investigate, then may do so with the fsync=strict
mount option. The regression report is from Google COS so...

I just want to make this ovl behavior change opt-in because I do not
want any more surprises from any other upper fs.

Thanks,
Amir.

Durability and copy up
----------------------

The fsync(2) system call ensures that the data and metadata of a file
are safely written to the backing storage, which is expected to
guarantee the existence of the information post system crash.

Without an fsync(2) call, there is no guarantee that the observed
data after a system crash will be either the old or the new data, but
in practice, the observed data after crash is often the old or new data
or a mix of both.

When an overlayfs file is modified for the first time, copy up will
create a copy of the lower file and its parent directories in the upper
layer.  Since the Linux filesystem API does not enforce any particular
ordering on storing changes without explicit fsync(2) calls, in case
of a system crash, the upper file could end up with no data at all
(i.e. zeros), which would be an unusual outcome.  To avoid this
experience, overlayfs calls fsync(2) on the upper file before completing
data copy up with rename(2) or link(2) to make the copy up "atomic".

By default, overlayfs does not explicitly call fsync(2) on copied up
directories or on metadata-only copy up, so it provides no guarantee to
persist the user's modification unless the user calls fsync(2).
The fsync during copy up only guarantees that if a copy up is observed
after a crash, the observed data is not zeroes or intermediate values
from the copy up staging area.

On traditional local filesystems with a single journal (e.g. ext4, xfs),
fsync on a file also persists the parent directory changes, because they
are usually modified in the same transaction, so metadata durability during
data copy up effectively comes for free.  Overlayfs further limits risk by
disallowing network filesystems as upper layer.

Overlayfs can be tuned to prefer performance or durability when storing
to the underlying upper layer.  This is controlled by the "fsync" mount
option, which supports these values:

- "auto": (default)
    Call fsync(2) on upper file before completion of data copy up.
    No explicit fsync(2) on directory or metadata-only copy up.
- "strict":
    Call fsync(2) on upper file and directories before completion of any
    copy up.
- "volatile": [*]
    Prefer performance over durability (see `Volatile mount`_)

[*] The mount option "volatile" is an alias to "fsync=volatile".

^ permalink raw reply

* [PATCH] ext4: initialize ext4_allocation_request with {}
From: Vivek BalachandharTN @ 2026-03-27 12:40 UTC (permalink / raw)
  To: tytso, adilger.kernel; +Cc: linux-ext4, linux-kernel, vivek.balachandhar

Replace explicit memset() with struct initialization using = {} for
ext4_allocation_request. This simplifies the code and makes the
initialization clearer while preserving behavior.

Signed-off-by: Vivek BalachandharTN <vivek.balachandhar@gmail.com>
---
 fs/ext4/balloc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 8040c731b3e4..21ea53346c55 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -737,10 +737,9 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
 				  ext4_fsblk_t goal, unsigned int flags,
 				  unsigned long *count, int *errp)
 {
-	struct ext4_allocation_request ar;
+	struct ext4_allocation_request ar = {};
 	ext4_fsblk_t ret;
 
-	memset(&ar, 0, sizeof(ar));
 	/* Fill with neighbour allocated blocks */
 	ar.inode = inode;
 	ar.goal = goal;
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH next] ext4: Fix diagnostic printf formats
From: David Laight @ 2026-03-27 12:54 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Theodore Ts'o, Andreas Dilger, linux-ext4, linux-kernel,
	Masami Hiramatsu, Petr Mladek, Rasmus Villemoes, Steven Rostedt,
	Sergey Senozhatsky, Andrew Morton
In-Reply-To: <acZgmKv38HLhky6q@ashevche-desk.local>

On Fri, 27 Mar 2026 12:48:56 +0200
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:

> On Thu, Mar 26, 2026 at 08:18:04PM +0000, david.laight.linux@gmail.com wrote:
> 
> > The formats for non-terminated names should be "%.*s" not "%*.s".
> > The kernel currently treats "%*.s" as equivalent to "%*s" whereas
> > userspace requires it be equivalent to "%*.0s".
> > Neither is correct here.  
> 
> This entire code seems was never tested properly and it's a dead code
> until one defines manually DX_DEBUG. It also has tons of plain printk()
> calls that may behave differently if the first character is not printable
> but maps to the level of printk().
> 
> I'm not sure how your patch helps with all that, but apparently the
> printed data has to be NUL-terminated, otherwise I have no idea how
> it was ever working without crashes.
> 

I noticed that as well.
I suspect it way have worked for the person that wrote it because the
name strings all happened to be NUL terminated.
There is certainly likely to be a '\0' before you 'fall off' mapped
memory and crash - so maybe they just ignored the extra characters.

Clearly the other option is to delete it all.
But regardless the format string is wrong.

	David
 

^ permalink raw reply

* [tytso-ext4:dev] BUILD SUCCESS 86709d389530941e5816505e3c12c757ceca374d
From: kernel test robot @ 2026-03-27 14:10 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: linux-ext4

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev
branch HEAD: 86709d389530941e5816505e3c12c757ceca374d  ext4: avoid infinite loops caused by residual data

elapsed time: 975m

configs tested: 188
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                              allmodconfig    gcc-15.2.0
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                                 defconfig    gcc-15.2.0
arc                   randconfig-001-20260327    gcc-11.5.0
arc                   randconfig-001-20260327    gcc-8.5.0
arc                   randconfig-002-20260327    gcc-8.5.0
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                              allyesconfig    gcc-15.2.0
arm                                 defconfig    gcc-15.2.0
arm                   randconfig-001-20260327    gcc-8.5.0
arm                   randconfig-002-20260327    clang-23
arm                   randconfig-002-20260327    gcc-8.5.0
arm                   randconfig-003-20260327    clang-18
arm                   randconfig-003-20260327    gcc-8.5.0
arm                   randconfig-004-20260327    gcc-11.5.0
arm                   randconfig-004-20260327    gcc-8.5.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260327    clang-23
arm64                 randconfig-002-20260327    clang-23
arm64                 randconfig-003-20260327    clang-23
arm64                 randconfig-004-20260327    clang-23
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260327    clang-23
csky                  randconfig-002-20260327    clang-23
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260327    gcc-8.5.0
hexagon               randconfig-002-20260327    gcc-8.5.0
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260327    clang-20
i386        buildonly-randconfig-002-20260327    clang-20
i386        buildonly-randconfig-003-20260327    clang-20
i386        buildonly-randconfig-003-20260327    gcc-14
i386        buildonly-randconfig-004-20260327    clang-20
i386        buildonly-randconfig-005-20260327    clang-20
i386        buildonly-randconfig-006-20260327    clang-20
i386        buildonly-randconfig-006-20260327    gcc-14
i386                                defconfig    gcc-15.2.0
i386                  randconfig-001-20260327    clang-20
i386                  randconfig-002-20260327    clang-20
i386                  randconfig-003-20260327    clang-20
i386                  randconfig-004-20260327    clang-20
i386                  randconfig-005-20260327    clang-20
i386                  randconfig-006-20260327    clang-20
i386                  randconfig-007-20260327    clang-20
i386                  randconfig-011-20260327    gcc-14
i386                  randconfig-012-20260327    gcc-14
i386                  randconfig-013-20260327    gcc-14
i386                  randconfig-014-20260327    gcc-14
i386                  randconfig-015-20260327    gcc-14
i386                  randconfig-016-20260327    gcc-14
i386                  randconfig-017-20260327    gcc-14
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260327    gcc-8.5.0
loongarch             randconfig-002-20260327    gcc-8.5.0
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                             allyesconfig    gcc-15.2.0
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
mips                  decstation_64_defconfig    gcc-15.2.0
mips                      pic32mzda_defconfig    gcc-15.2.0
nios2                            allmodconfig    clang-23
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260327    gcc-8.5.0
nios2                 randconfig-002-20260327    gcc-8.5.0
openrisc                         allmodconfig    clang-23
openrisc                         allmodconfig    gcc-15.2.0
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-15.2.0
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-15.2.0
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260327    clang-18
parisc                randconfig-002-20260327    clang-18
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-15.2.0
powerpc               randconfig-001-20260327    clang-18
powerpc               randconfig-002-20260327    clang-18
powerpc64             randconfig-001-20260327    clang-18
powerpc64             randconfig-002-20260327    clang-18
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-15.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260327    gcc-12.5.0
riscv                 randconfig-002-20260327    gcc-12.5.0
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260327    gcc-12.5.0
s390                  randconfig-002-20260327    gcc-12.5.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-15.2.0
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260327    gcc-12.5.0
sh                    randconfig-002-20260327    gcc-12.5.0
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-15.2.0
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260327    gcc-14
sparc                 randconfig-002-20260327    gcc-14
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260327    gcc-14
sparc64               randconfig-002-20260327    gcc-14
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260327    gcc-14
um                    randconfig-002-20260327    gcc-14
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260327    clang-20
x86_64      buildonly-randconfig-002-20260327    clang-20
x86_64      buildonly-randconfig-003-20260327    clang-20
x86_64      buildonly-randconfig-004-20260327    clang-20
x86_64      buildonly-randconfig-005-20260327    clang-20
x86_64      buildonly-randconfig-006-20260327    clang-20
x86_64                              defconfig    gcc-14
x86_64                randconfig-001-20260327    gcc-14
x86_64                randconfig-002-20260327    gcc-14
x86_64                randconfig-003-20260327    gcc-14
x86_64                randconfig-004-20260327    gcc-14
x86_64                randconfig-005-20260327    gcc-14
x86_64                randconfig-006-20260327    gcc-14
x86_64                randconfig-011-20260327    gcc-14
x86_64                randconfig-012-20260327    gcc-14
x86_64                randconfig-013-20260327    gcc-14
x86_64                randconfig-014-20260327    gcc-14
x86_64                randconfig-015-20260327    gcc-14
x86_64                randconfig-016-20260327    gcc-14
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-15.2.0
xtensa                           allyesconfig    clang-23
xtensa                randconfig-001-20260327    gcc-14
xtensa                randconfig-002-20260327    gcc-14

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH next] ext4: Fix diagnostic printf formats
From: Andy Shevchenko @ 2026-03-27 14:12 UTC (permalink / raw)
  To: David Laight
  Cc: Theodore Ts'o, Andreas Dilger, linux-ext4, linux-kernel,
	Masami Hiramatsu, Petr Mladek, Rasmus Villemoes, Steven Rostedt,
	Sergey Senozhatsky, Andrew Morton
In-Reply-To: <20260327125412.47944386@pumpkin>

On Fri, Mar 27, 2026 at 12:54:12PM +0000, David Laight wrote:
> On Fri, 27 Mar 2026 12:48:56 +0200
> Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> > On Thu, Mar 26, 2026 at 08:18:04PM +0000, david.laight.linux@gmail.com wrote:
> > 
> > > The formats for non-terminated names should be "%.*s" not "%*.s".
> > > The kernel currently treats "%*.s" as equivalent to "%*s" whereas
> > > userspace requires it be equivalent to "%*.0s".
> > > Neither is correct here.  
> > 
> > This entire code seems was never tested properly and it's a dead code
> > until one defines manually DX_DEBUG. It also has tons of plain printk()
> > calls that may behave differently if the first character is not printable
> > but maps to the level of printk().
> > 
> > I'm not sure how your patch helps with all that, but apparently the
> > printed data has to be NUL-terminated, otherwise I have no idea how
> > it was ever working without crashes.
> 
> I noticed that as well.
> I suspect it way have worked for the person that wrote it because the
> name strings all happened to be NUL terminated.
> There is certainly likely to be a '\0' before you 'fall off' mapped
> memory and crash - so maybe they just ignored the extra characters.
> 
> Clearly the other option is to delete it all.

I would go for the history of the change and if it's old enough and not
mentioned in any Documentation or not-so-old email thread, kill all that
for good. But better to hear the ext4 maintainers first.

> But regardless the format string is wrong.

P.S. A bit of off-topic, have you seen this?
https://elixir.bootlin.com/linux/v7.0-rc5/source/kernel/stacktrace.c#L33
Is it correct use of %c?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH] ext4: add bounds check in ext4_xattr_ibody_get() to prevent out-of-bounds access
From: Deepanshu Kartikey @ 2026-03-27 14:32 UTC (permalink / raw)
  To: Theodore Tso
  Cc: adilger.kernel, linux-ext4, linux-kernel,
	syzbot+fb32afec111a7d61b939
In-Reply-To: <20260326054718.GC4383@macsyma.local>

On Thu, Mar 26, 2026 at 11:17 AM Theodore Tso <tytso@mit.edu> wrote:
>
>
> Actually, it does more than that.  It also calls xattr_check_inode()
> which should validate the xattr block in the inode.
>
> So instead of adding the check in ext4_xattr_ibody_get(), we should
> fix the check in __xattr_check_inode().  This is preferable since it's
> more efficient than checking every time we try to fetch an extended
> attribute, instead of validating it when the inode is read from the
> inode table block.
>
>                                         - Ted


Subject: Re: [PATCH] ext4: add bounds check in ext4_xattr_ibody_get()
to prevent out-of-bounds access

Hi Ted,

Thank you for the review. I tried moving the fix to check_xattrs()
as you suggested, but the syzbot reproducer still crashes. I added
printk statements to trace the code path and found the root cause.

The issue is that __xattr_check_inode() runs once during ext4_iget(),
but ext4_xattr_ibody_get() re-reads the inode from disk via
ext4_get_inode_loc() on every call. The reproducer exploits this by
shrinking the loop device after mount, causing the re-read to return
corrupted data.

Here is the relevant debug output showing the sequence:

1) Inode 12 is loaded, __xattr_check_inode passes with gap=92:

  DEBUG: inode 12: calling ext4_iget_extra_inode
  DEBUG: inode 12: __xattr_check_inode called,
         IFIRST=ffff88805b9f9fa4 end=ffff88805b9fa000 gap=92

2) The loop device is then shrunk:

  loop0: detected capacity change from 1024 to 64

3) First access after shrink, inode re-read still looks okay:

  DEBUG: inode 12: ibody_get
         IFIRST=ffff88806edbcfa4 end=ffff88806edbd000 gap=92

4) Second access, re-read returns corrupted data with gap=-4:

  DEBUG: inode 12: ibody_get
         IFIRST=ffff88806edbd004 end=ffff88806edbd000 gap=-4

5) Crash follows immediately in xattr_find_entry().

Note that IFIRST and end are at different addresses between steps
1 and 4 - ext4_get_inode_loc() returned a different buffer_head
with corrupted i_extra_isize, pushing IFIRST 4 bytes past end.
The initial __xattr_check_inode() validation cannot protect
against this because it validated the original buffer, not the
corrupted re-read.

I think we need both fixes:

  1) The bounds fix in check_xattrs() as you suggested, changing
     (void *)next >= end to (void *)next + sizeof(u32) > end

  2) A bounds check in ext4_xattr_ibody_get() before calling
     xattr_find_entry(), to catch corrupted re-reads

Should I submit a v2 with both fixes as a patch series?

Thanks,
Deepanshu Kartikey

^ permalink raw reply

* Re: [PATCH] ext4: Fix call trace when remounting to read only in data=journal mode
From: Theodore Tso @ 2026-03-27 15:42 UTC (permalink / raw)
  To: Gerald Yang; +Cc: Jan Kara, adilger.kernel, linux-ext4, gerald.yang.tw
In-Reply-To: <CAMsNC+u83HArYs1zjQ-YUHyADruros20LOB2m52=aeDXcpuJVQ@mail.gmail.com>

On Fri, Mar 27, 2026 at 03:26:38PM +0800, Gerald Yang wrote:
> 
> Would this be merged into the next merge window?
> https://lore.kernel.org/linux-ext4/20260205092223.21287-2-jack@suse.cz/

Yes, it's in the ext4 git tree already and will be sent along with a
number of other bugfixes to Linus before 7.0 is released.

       	  		    	  	     - Ted

^ permalink raw reply

* Re: [PATCH next] ext4: Fix diagnostic printf formats
From: David Laight @ 2026-03-27 16:08 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Theodore Ts'o, Andreas Dilger, linux-ext4, linux-kernel,
	Masami Hiramatsu, Petr Mladek, Rasmus Villemoes, Steven Rostedt,
	Sergey Senozhatsky, Andrew Morton
In-Reply-To: <acaQVpYREnJJuJF5@ashevche-desk.local>

On Fri, 27 Mar 2026 16:12:38 +0200
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:

...
> P.S. A bit of off-topic, have you seen this?
> https://elixir.bootlin.com/linux/v7.0-rc5/source/kernel/stacktrace.c#L33
> Is it correct use of %c?
> 

Works with glibc (or, rather, with whichever libc the shell I'm using
is linked against):

$ printf '|%*c|\n' 5 x
|    x|
$

'man fprintf' tends to agree.
Left justify also works, either "%-*c" or passing -5.

The 'fun' starts if you print a zero with %c in the middle of some output.

I know some compilers have supported: int c = 'abcd';
But I can't remember whether the value could be printed with %4c.
I do remember that the value ended up byteswapped in memory on both
x86 and sparc.

	David

^ permalink raw reply

* Re: [PATCH 14/42] fs: Rename generic_file_fsync() to simple_fsync()
From: Jan Kara @ 2026-03-27 16:26 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Jan Kara, linux-fsdevel, linux-block, Christian Brauner, Al Viro,
	linux-ext4, Ted Tso, Tigran A. Aivazian, David Sterba,
	OGAWA Hirofumi, Muchun Song, Oscar Salvador, David Hildenbrand,
	linux-mm, linux-aio, Benjamin LaHaise
In-Reply-To: <acYiH4ByDc1-nPqD@infradead.org>

On Thu 26-03-26 23:22:23, Christoph Hellwig wrote:
> > -extern int __generic_file_fsync(struct file *, loff_t, loff_t, int);
> > -extern int generic_file_fsync(struct file *, loff_t, loff_t, int);
> > +extern int simple_fsync_noflush(struct file *, loff_t, loff_t, int);
> > +extern int simple_fsync(struct file *, loff_t, loff_t, int);
> 
> Please drop the pointless externs, and maybe also add the parameter names
> when you touch it.
> 
> Otherwise looks good.

I believe Christian has a patch from Jeff in his tree cleaning up the whole
fs.h header in this way. Not sure how Christian ended up resolving the
conflict but we can clean this up after the merge window if some externs
are still left there.

								Honza
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply

* SYZKALLER BUG: messing with a mounted file system via loop ioctls (was: Re: [PATCH] ext4: add bounds check in ext4_xattr_ibody_get() to) prevent out-of-bounds access
From: Theodore Tso @ 2026-03-27 16:31 UTC (permalink / raw)
  To: Deepanshu Kartikey
  Cc: adilger.kernel, linux-ext4, linux-kernel,
	syzbot+fb32afec111a7d61b939, syzkaller
In-Reply-To: <CADhLXY5E_4Hi=Uzu3LPwg_YNgcFR+UcAbfY-XzwVnmFBaJqjkA@mail.gmail.com>

On Fri, Mar 27, 2026 at 08:02:30PM +0530, Deepanshu Kartikey wrote:
> 
> Thank you for the review. I tried moving the fix to check_xattrs()
> as you suggested, but the syzbot reproducer still crashes. I added
> printk statements to trace the code path and found the root cause.
> 
> The issue is that __xattr_check_inode() runs once during ext4_iget(),
> but ext4_xattr_ibody_get() re-reads the inode from disk via
> ext4_get_inode_loc() on every call. The reproducer exploits this by
> shrinking the loop device after mount, causing the re-read to return
> corrupted data.

I consider this more a defect in Syzkaller than in ext4.  Syzkaller
already unsets CONFIG_BLK_DEV_WRITE_MOUNTED because modifying a
mounted file system is not considered a valid security concern.
Unfortunately, the syzkaller fuzzer which corrupts a mounted file
system by messing with a loop device using a privileged ioctl bypasses
!CONFIG_DEV_BLK_WRITE_MOUNTED.

I'll accept a change to add a to check_xattrs(), which will protect
against static corruptions, but adding an extra check to a hotpath
(this would slow down SELinux, which aggressively needs to read the
file's sid) to protect against a corruption issue which requires root
privs is not something I'm interested in.

My priority is improving ext4 --- not reducing the syzkaller reports
against ext4 to zero, since there are false positives like this.  For
people who care about reducing the syzkaller report gamification, my
suggestion is to either extend CONFIG_BLK_DEV_WRITE_MOUNTED to prevent
these loop device reconfiguration while a file system is mounted on
that loop device, or to fix syzkaller to not create fuzzers like this.

Cheers,

						- Ted








> 
> Here is the relevant debug output showing the sequence:
> 
> 1) Inode 12 is loaded, __xattr_check_inode passes with gap=92:
> 
>   DEBUG: inode 12: calling ext4_iget_extra_inode
>   DEBUG: inode 12: __xattr_check_inode called,
>          IFIRST=ffff88805b9f9fa4 end=ffff88805b9fa000 gap=92
> 
> 2) The loop device is then shrunk:
> 
>   loop0: detected capacity change from 1024 to 64
> 
> 3) First access after shrink, inode re-read still looks okay:
> 
>   DEBUG: inode 12: ibody_get
>          IFIRST=ffff88806edbcfa4 end=ffff88806edbd000 gap=92
> 
> 4) Second access, re-read returns corrupted data with gap=-4:
> 
>   DEBUG: inode 12: ibody_get
>          IFIRST=ffff88806edbd004 end=ffff88806edbd000 gap=-4
> 
> 5) Crash follows immediately in xattr_find_entry().
> 
> Note that IFIRST and end are at different addresses between steps
> 1 and 4 - ext4_get_inode_loc() returned a different buffer_head
> with corrupted i_extra_isize, pushing IFIRST 4 bytes past end.
> The initial __xattr_check_inode() validation cannot protect
> against this because it validated the original buffer, not the
> corrupted re-read.
> 
> I think we need both fixes:
> 
>   1) The bounds fix in check_xattrs() as you suggested, changing
>      (void *)next >= end to (void *)next + sizeof(u32) > end
> 
>   2) A bounds check in ext4_xattr_ibody_get() before calling
>      xattr_find_entry(), to catch corrupted re-reads
> 
> Should I submit a v2 with both fixes as a patch series?
> 
> Thanks,
> Deepanshu Kartikey

^ permalink raw reply

* Re: [PATCH next] ext4: Fix diagnostic printf formats
From: Theodore Tso @ 2026-03-27 17:14 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: David Laight, Andreas Dilger, linux-ext4, linux-kernel,
	Masami Hiramatsu, Petr Mladek, Rasmus Villemoes, Steven Rostedt,
	Sergey Senozhatsky, Andrew Morton
In-Reply-To: <acaQVpYREnJJuJF5@ashevche-desk.local>

On Fri, Mar 27, 2026 at 04:12:38PM +0200, Andy Shevchenko wrote:
> > > I'm not sure how your patch helps with all that, but apparently the
> > > printed data has to be NUL-terminated, otherwise I have no idea how
> > > it was ever working without crashes.
> > 
> > I noticed that as well.
> > I suspect it way have worked for the person that wrote it because the
> > name strings all happened to be NUL terminated.
> > There is certainly likely to be a '\0' before you 'fall off' mapped
> > memory and crash - so maybe they just ignored the extra characters.
> > 
> > Clearly the other option is to delete it all.
> 
> I would go for the history of the change and if it's old enough and not
> mentioned in any Documentation or not-so-old email thread, kill all that
> for good. But better to hear the ext4 maintainers first.

This is code that can only be manually enabled by adding a

#define DX_DEBUG

to the sources; it's not anything that users can configure using
Kconfig.  It *has* been used relatively recently, when developers
added support for three level htree directories.  I'm not sure why
they didn't run into the NULL termination issue, but since it is handy
to have the debugging code for developers' use, my preference would be
to keep the code and fix it up the problems.

   	    	     	    - Ted

^ permalink raw reply

* Re: [PATCH -v2] ext4: handle wraparound when searching for blocks for indirect mapped blocks
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: Ext4 Developers List, Theodore Ts'o; +Cc: Jan Kara
In-Reply-To: <20260326045834.1175822-1-tytso@mit.edu>


On Thu, 26 Mar 2026 00:58:34 -0400, Theodore Ts'o wrote:
> Commit 4865c768b563 ("ext4: always allocate blocks only from groups
> inode can use") restricts what blocks will be allocated for indirect
> block based files to block numbers that fit within 32-bit block
> numbers.
> 
> However, when using a review bot running on the latest Gemini LLM to
> check this commit when backporting into an LTS based kernel, it raised
> this concern:
> 
> [...]

Applied, thanks!

[1/1] ext4: handle wraparound when searching for blocks for indirect mapped blocks
      commit: bb81702370fad22c06ca12b6e1648754dbc37e0f

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* Re: [PATCH] ext4: reject mount if bigalloc with s_first_data_block != 0
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: adilger.kernel, linux-ext4, linux-fsdevel, linux-kernel,
	kernel-dev, syzbot+b73703b873a33d8eb8f6, Helen Koike
  Cc: Theodore Ts'o
In-Reply-To: <20260317142325.135074-1-koike@igalia.com>


On Tue, 17 Mar 2026 11:23:10 -0300, Helen Koike wrote:
> bigalloc with s_first_data_block != 0 is not supported, reject mounting
> it.

Applied, thanks!

[1/1] ext4: reject mount if bigalloc with s_first_data_block != 0
      commit: 3822743dc20386d9897e999dbb990befa3a5b3f8

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* Re: [PATCH] ext4: Fix deadlock on inode reallocation
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: Jan Kara; +Cc: Theodore Ts'o, linux-ext4, yi1.lai, Mateusz Guzik, stable
In-Reply-To: <20260320090428.24899-2-jack@suse.cz>


On Fri, 20 Mar 2026 10:04:29 +0100, Jan Kara wrote:
> Currently there is a race in ext4 when reallocating freed inode
> resulting in a deadlock:
> 
> Task1					Task2
> ext4_evict_inode()
>   handle = ext4_journal_start();
>   ...
>   if (IS_SYNC(inode))
>     handle->h_sync = 1;
>   ext4_free_inode()
> 					ext4_new_inode()
> 					  handle = ext4_journal_start()
> 					  finds the bit in inode bitmap
> 					    already clear
> 					  insert_inode_locked()
> 					    waits for inode to be
> 					      removed from the hash.
>   ext4_journal_stop(handle)
>     jbd2_journal_stop(handle)
>       jbd2_log_wait_commit(journal, tid);
>         - deadlocks waiting for transaction handle Task2 holds
> 
> [...]

Applied, thanks!

[1/1] ext4: Fix deadlock on inode reallocation
      commit: 0c90eed1b95335eba4f546e6742a8e4503d79349

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* Re: [PATCH] ext4: Fix the might_sleep() warnings in kvfree()
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: adilger.kernel, libaokun, Zqiang
  Cc: Theodore Ts'o, linux-ext4, linux-kernel
In-Reply-To: <20260319094545.19291-1-qiang.zhang@linux.dev>


On Thu, 19 Mar 2026 17:45:45 +0800, Zqiang wrote:
> Use the kvfree() in the RCU read critical section can trigger
> the following warnings:
> 
> EXT4-fs (vdb): unmounting filesystem cd983e5b-3c83-4f5a-a136-17b00eb9d018.
> 
> WARNING: suspicious RCU usage
> 
> [...]

Applied, thanks!

[1/1] ext4: Fix the might_sleep() warnings in kvfree()
      commit: 496bb99b7e66f48b178126626f47e9ba79e2d0fa

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* Re: [PATCH v2] ext4: skip split extent recovery on corruption
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: adilger.kernel, jack, yi.zhang, ojaswin, hongao
  Cc: Theodore Ts'o, linux-ext4, linux-kernel,
	syzbot+1ffa5d865557e51cb604
In-Reply-To: <EF77870F23FF9C90+20260324015815.35248-1-hongao@uniontech.com>


On Tue, 24 Mar 2026 09:58:15 +0800, hongao wrote:
> ext4_split_extent_at() retries after ext4_ext_insert_extent() fails by
> refinding the original extent and restoring its length. That recovery is
> only safe for transient resource failures such as -ENOSPC, -EDQUOT, and
> -ENOMEM.
> 
> When ext4_ext_insert_extent() fails because the extent tree is already
> corrupted, ext4_find_extent() can return a leaf path without p_ext.
> ext4_split_extent_at() then dereferences path[depth].p_ext while trying to
> fix up the original extent length, causing a NULL pointer dereference while
> handling a pre-existing filesystem corruption.
> 
> [...]

Applied, thanks!

[1/1] ext4: skip split extent recovery on corruption
      commit: 3ceda17325fc2600f66fd85b526592bc8a9dfb9d

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* Re: [PATCH v2 1/1] jbd2: gracefully abort on checkpointing state corruptions
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: jack, Milos Nikic
  Cc: Theodore Ts'o, linux-ext4, linux-kernel, Andreas Dilger,
	Zhang Yi, Baokun Li
In-Reply-To: <20260311041548.159424-1-nikic.milos@gmail.com>


On Tue, 10 Mar 2026 21:15:48 -0700, Milos Nikic wrote:
> This patch targets two internal state machine invariants in checkpoint.c
> residing inside functions that natively return integer error codes.
> 
> - In jbd2_cleanup_journal_tail(): A blocknr of 0 indicates a severely
> corrupted journal superblock. Replaced the J_ASSERT with a WARN_ON_ONCE
> and a graceful journal abort, returning -EFSCORRUPTED.
> 
> [...]

Applied, thanks!

[1/1] jbd2: gracefully abort on checkpointing state corruptions
      commit: bac3190a8e79beff6ed221975e0c9b1b5f2a21da

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* Re: [PATCH v3] ext4: fix use-after-free in update_super_work when racing with umount
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: linux-ext4, jack, Jiayuan Chen
  Cc: Theodore Ts'o, Jiayuan Chen, Andreas Dilger, Ritesh Harjani,
	Ye Bin, linux-kernel
In-Reply-To: <20260319120336.157873-1-jiayuan.chen@linux.dev>


On Thu, 19 Mar 2026 20:03:35 +0800, Jiayuan Chen wrote:
> Commit b98535d09179 ("ext4: fix bug_on in start_this_handle during umount
> filesystem") moved ext4_unregister_sysfs() before flushing s_sb_upd_work
> to prevent new error work from being queued via /proc/fs/ext4/xx/mb_groups
> reads during unmount. However, this introduced a use-after-free because
> update_super_work calls ext4_notify_error_sysfs() -> sysfs_notify() which
> accesses the kobject's kernfs_node after it has been freed by kobject_del()
> in ext4_unregister_sysfs():
> 
> [...]

Applied, thanks!

[1/1] ext4: fix use-after-free in update_super_work when racing with umount
      commit: d15e4b0a418537aafa56b2cb80d44add83e83697

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* Re: [PATCH v2 0/3] decoupling the ext4 test module
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: adilger.kernel, linux-ext4, Ye Bin; +Cc: Theodore Ts'o, jack
In-Reply-To: <20260314075258.1317579-1-yebin@huaweicloud.com>


On Sat, 14 Mar 2026 15:52:55 +0800, Ye Bin wrote:
> This patchset is split out from the "Fix some issues about ext4-test"
> patchset. It decouples mballoc-test.c and extents-test.c from the
> ext4 module, resolving the issue where these two tests could not be run
> when EXT4_KUNIT_TESTS is set to M.
> 
> Ye Bin (3):
>   ext4: introduce EXPORT_SYMBOL_FOR_EXT4_TEST() helper
>   ext4: fix mballoc-test.c is not compiled when EXT4_KUNIT_TESTS=M
>   ext4: fix extents-test.c is not compiled when EXT4_KUNIT_TESTS=M
> 
> [...]

Applied, thanks!

[1/3] ext4: introduce EXPORT_SYMBOL_FOR_EXT4_TEST() helper
      commit: 49504a512587147dd6da3b4b08832ccc157b97dc
[2/3] ext4: fix mballoc-test.c is not compiled when EXT4_KUNIT_TESTS=M
      commit: 519b76ac0b31d86b45784735d4ef964e8efdc56b
[3/3] ext4: fix extents-test.c is not compiled when EXT4_KUNIT_TESTS=M
      commit: 9e1b14320b154094bb2c1bee6d8c6cb851fc3215

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* Re: [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: linux-ext4, Baokun Li
  Cc: Theodore Ts'o, adilger.kernel, jack, yi.zhang, ojaswin,
	ritesh.list, Joseph Qi
In-Reply-To: <20260323060836.3452660-1-libaokun@linux.alibaba.com>


On Mon, 23 Mar 2026 14:08:36 +0800, Baokun Li wrote:
> During code review, Joseph found that ext4_fc_replay_inode() calls
> ext4_get_fc_inode_loc() to get the inode location, which holds a
> reference to iloc.bh that must be released via brelse().
> 
> However, several error paths jump to the 'out' label without
> releasing iloc.bh:
> 
> [...]

Applied, thanks!

[1/1] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
      commit: ec0a7500d8eace5b4f305fa0c594dd148f0e8d29

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply

* [PATCH v2] ext4: fix bounds check in check_xattrs() to prevent out-of-bounds access
From: Deepanshu Kartikey @ 2026-03-28 15:00 UTC (permalink / raw)
  To: tytso, adilger.kernel
  Cc: linux-ext4, linux-kernel, Deepanshu Kartikey, stable,
	syzbot+fb32afec111a7d61b939

The bounds check for the next xattr entry in check_xattrs() uses
(void *)next >= end, which allows next to point within sizeof(u32)
bytes of end. On the next loop iteration, IS_LAST_ENTRY() reads 4
bytes via *(__u32 *)(entry), which can overrun the valid xattr region.

For example, if next lands at end - 1, the check passes since
next < end, but IS_LAST_ENTRY() reads 4 bytes starting at end - 1,
accessing 3 bytes beyond the valid region.

Fix this by changing the check to (void *)next + sizeof(u32) > end,
ensuring there is always enough space for the IS_LAST_ENTRY() read
on the subsequent iteration.

Fixes: 3478c83cf26b ("ext4: improve xattr consistency checking and error reporting")
Cc: stable@vger.kernel.org
Reported-by: syzbot+fb32afec111a7d61b939@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=fb32afec111a7d61b939
Link: https://lore.kernel.org/all/20260224231429.31361-1-kartikey406@gmail.com/T/ [v1]
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>

---
v2: Move the fix to check_xattrs() as suggested by Ted Ts'o,
    instead of adding a check in ext4_xattr_ibody_get().
---
 fs/ext4/xattr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 7bf9ba19a89d..c6205b405efe 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -226,7 +226,7 @@ check_xattrs(struct inode *inode, struct buffer_head *bh,
 	/* Find the end of the names list */
 	while (!IS_LAST_ENTRY(e)) {
 		struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e);
-		if ((void *)next >= end) {
+		if ((void *)next + sizeof(u32) > end) {
 			err_str = "e_name out of bounds";
 			goto errout;
 		}
-- 
2.43.0


^ permalink raw reply related

* Re: SYZKALLER BUG: messing with a mounted file system via loop ioctls (was: Re: [PATCH] ext4: add bounds check in ext4_xattr_ibody_get() to) prevent out-of-bounds access
From: Deepanshu Kartikey @ 2026-03-28 15:02 UTC (permalink / raw)
  To: Theodore Tso
  Cc: adilger.kernel, linux-ext4, linux-kernel,
	syzbot+fb32afec111a7d61b939, syzkaller
In-Reply-To: <20260327163135.GE4383@macsyma.local>

On Fri, Mar 27, 2026 at 10:01 PM Theodore Tso <tytso@mit.edu> wrote:
>
> On Fri, Mar 27, 2026 at 08:02:30PM +0530, Deepanshu Kartikey wrote:
> >
> > Thank you for the review. I tried moving the fix to check_xattrs()
> > as you suggested, but the syzbot reproducer still crashes. I added
> > printk statements to trace the code path and found the root cause.
> >
> > The issue is that __xattr_check_inode() runs once during ext4_iget(),
> > but ext4_xattr_ibody_get() re-reads the inode from disk via
> > ext4_get_inode_loc() on every call. The reproducer exploits this by
> > shrinking the loop device after mount, causing the re-read to return
> > corrupted data.
>
> I consider this more a defect in Syzkaller than in ext4.  Syzkaller
> already unsets CONFIG_BLK_DEV_WRITE_MOUNTED because modifying a
> mounted file system is not considered a valid security concern.
> Unfortunately, the syzkaller fuzzer which corrupts a mounted file
> system by messing with a loop device using a privileged ioctl bypasses
> !CONFIG_DEV_BLK_WRITE_MOUNTED.
>
> I'll accept a change to add a to check_xattrs(), which will protect
> against static corruptions, but adding an extra check to a hotpath
> (this would slow down SELinux, which aggressively needs to read the
> file's sid) to protect against a corruption issue which requires root
> privs is not something I'm interested in.
>
> My priority is improving ext4 --- not reducing the syzkaller reports
> against ext4 to zero, since there are false positives like this.  For
> people who care about reducing the syzkaller report gamification, my
> suggestion is to either extend CONFIG_BLK_DEV_WRITE_MOUNTED to prevent
> these loop device reconfiguration while a file system is mounted on
> that loop device, or to fix syzkaller to not create fuzzers like this.
>
> Cheers,
>
>                                                 - Ted
>

Thanks for the clarification. I have sent the patch v2 with check in
check_xattrs.

Deepanshu

^ permalink raw reply

* [BUG] lseek in sparse files broken on ext3 mounted as ext4
From: Alexander Monakov @ 2026-03-28 16:24 UTC (permalink / raw)
  To: linux-ext4

Hi!

Mounting ext3 with '-o delalloc' is explicitly rejected by the kernel
("EXT4-fs: Mount option(s) incompatible with ext3" in dmesg).

At the same time, mounting ext3 with '-t ext4' is accepted, and enables
delayed allocation. In this case, lseek with SEEK_DATA/SEEK_HOLE requests
does not work correctly and breaks userspace programs such as install(1)
from coreutils.

To reproduce, it is sufficient to prepare an ext3 image as usual and mount it
as ext4:

truncate -s 1G img-ext3
mkfs.ext3 img-ext3
mkdir mnt-ext3
mount -t ext4 img-ext3 mnt-ext3

and run the following repro script:

#!/bin/sh
echo | dd of=src bs=1 count=1 seek=64K
strace -v -o install.strace install src dst
cmp src dst

the output should be

src dst differ: char 65537, line 1

with

lseek(3, 0, SEEK_DATA)                  = -1 ENXIO

in install.strace on the first lseek call, meaning that it reports
"no more data until EOF" (and hence install does not copy anything).

Either mounting with '-o nodelalloc' or fdatasync'ing the file before install
(conv=fdatasync in dd or 'sync -d src' after dd) avoids the problem.

The old ext4 wiki [1], the KernelNewbies wiki [2], and the Arch wiki [3]
all claim that mounting ext3 as ext4 is expected to work correctly.

[1] https://archive.kernel.org/oldwiki/ext4.wiki.kernel.org/index.php/UpgradeToExt4.html
[2] https://kernelnewbies.org/Ext4
[3] https://wiki.archlinux.org/title/Ext4

Thanks.
Alexander

^ permalink raw reply

* [tytso-ext4:dev] BUILD SUCCESS 9ee29d20aab228adfb02ca93f87fb53c56c2f3af
From: kernel test robot @ 2026-03-28 16:43 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: linux-ext4

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev
branch HEAD: 9ee29d20aab228adfb02ca93f87fb53c56c2f3af  ext4: always drain queued discard work in ext4_mb_release()

elapsed time: 752m

configs tested: 187
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                                 defconfig    gcc-15.2.0
arc                   randconfig-001-20260328    gcc-15.2.0
arc                   randconfig-002-20260328    gcc-15.2.0
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                       aspeed_g4_defconfig    clang-23
arm                          collie_defconfig    gcc-15.2.0
arm                                 defconfig    gcc-15.2.0
arm                   randconfig-001-20260328    gcc-15.2.0
arm                   randconfig-002-20260328    gcc-15.2.0
arm                   randconfig-003-20260328    gcc-15.2.0
arm                   randconfig-004-20260328    gcc-15.2.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260328    gcc-14.3.0
arm64                 randconfig-002-20260328    gcc-14.3.0
arm64                 randconfig-003-20260328    gcc-14.3.0
arm64                 randconfig-004-20260328    gcc-14.3.0
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260328    gcc-14.3.0
csky                  randconfig-002-20260328    gcc-14.3.0
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260328    gcc-11.5.0
hexagon               randconfig-002-20260328    gcc-11.5.0
i386                             allmodconfig    clang-20
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    clang-20
i386        buildonly-randconfig-001-20260328    clang-20
i386        buildonly-randconfig-002-20260328    clang-20
i386        buildonly-randconfig-003-20260328    clang-20
i386        buildonly-randconfig-004-20260328    clang-20
i386        buildonly-randconfig-005-20260328    clang-20
i386        buildonly-randconfig-006-20260328    clang-20
i386                                defconfig    gcc-15.2.0
i386                  randconfig-001-20260328    clang-20
i386                  randconfig-002-20260328    clang-20
i386                  randconfig-003-20260328    clang-20
i386                  randconfig-004-20260328    clang-20
i386                  randconfig-005-20260328    clang-20
i386                  randconfig-006-20260328    clang-20
i386                  randconfig-007-20260328    clang-20
i386                  randconfig-011-20260328    gcc-13
i386                  randconfig-012-20260328    gcc-13
i386                  randconfig-013-20260328    gcc-13
i386                  randconfig-014-20260328    gcc-13
i386                  randconfig-015-20260328    gcc-13
i386                  randconfig-016-20260328    gcc-13
i386                  randconfig-017-20260328    gcc-13
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260328    gcc-11.5.0
loongarch             randconfig-002-20260328    gcc-11.5.0
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            allmodconfig    clang-23
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260328    gcc-11.5.0
nios2                 randconfig-002-20260328    gcc-11.5.0
openrisc                         allmodconfig    clang-23
openrisc                         allmodconfig    gcc-15.2.0
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-15.2.0
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-15.2.0
parisc                           allyesconfig    clang-19
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260328    gcc-10.5.0
parisc                randconfig-002-20260328    gcc-10.5.0
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-15.2.0
powerpc                        cell_defconfig    gcc-15.2.0
powerpc               randconfig-001-20260328    gcc-10.5.0
powerpc               randconfig-002-20260328    gcc-10.5.0
powerpc64             randconfig-001-20260328    gcc-10.5.0
powerpc64             randconfig-002-20260328    gcc-10.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-15.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260328    clang-23
riscv                 randconfig-002-20260328    clang-23
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260328    clang-23
s390                  randconfig-002-20260328    clang-23
sh                               alldefconfig    gcc-15.2.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-15.2.0
sh                               allyesconfig    clang-19
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260328    clang-23
sh                    randconfig-002-20260328    clang-23
sh                           se7705_defconfig    gcc-15.2.0
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-15.2.0
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260328    gcc-14
sparc                 randconfig-002-20260328    gcc-14
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260328    gcc-14
sparc64               randconfig-002-20260328    gcc-14
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260328    gcc-14
um                    randconfig-002-20260328    gcc-14
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260328    clang-20
x86_64      buildonly-randconfig-002-20260328    clang-20
x86_64      buildonly-randconfig-003-20260328    clang-20
x86_64      buildonly-randconfig-004-20260328    clang-20
x86_64      buildonly-randconfig-005-20260328    clang-20
x86_64      buildonly-randconfig-006-20260328    clang-20
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20260328    gcc-14
x86_64                randconfig-002-20260328    gcc-14
x86_64                randconfig-003-20260328    gcc-14
x86_64                randconfig-004-20260328    gcc-14
x86_64                randconfig-005-20260328    gcc-14
x86_64                randconfig-006-20260328    gcc-14
x86_64                randconfig-011-20260328    clang-20
x86_64                randconfig-012-20260328    clang-20
x86_64                randconfig-013-20260328    clang-20
x86_64                randconfig-014-20260328    clang-20
x86_64                randconfig-015-20260328    clang-20
x86_64                randconfig-016-20260328    clang-20
x86_64                randconfig-071-20260328    gcc-12
x86_64                randconfig-072-20260328    gcc-12
x86_64                randconfig-073-20260328    gcc-12
x86_64                randconfig-074-20260328    gcc-12
x86_64                randconfig-075-20260328    gcc-12
x86_64                randconfig-076-20260328    gcc-12
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-15.2.0
xtensa                           allyesconfig    clang-23
xtensa                randconfig-001-20260328    gcc-14
xtensa                randconfig-002-20260328    gcc-14

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox