On Tue, Jul 01, 2025 at 05:11:41PM +0300, Dmitry Antipov wrote: > On a corrupted filesystem, an unexpectedly large invalid value > returned by 'ext4_rec_len_from_disk()' may cause 'ext4_readdir()' > to read the next dirent from an area beyond the corresponding > buffer head's data. At this point, an exact length of the dirent > is not known yet but it's possible to check whether the shortest > possible dirent will be read from within the bh's data at least. > > Reported-by: syzbot+5322c5c260eb44d209ed@xxxxxxxxxxxxxxxxxxxxxxxxx > Closes: https://syzkaller.appspot.com/bug?extid=5322c5c260eb44d209ed > Signed-off-by: Dmitry Antipov <dmantipov@xxxxxxxxx> > --- > fs/ext4/dir.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c > index d4164c507a90..8097016f69aa 100644 > --- a/fs/ext4/dir.c > +++ b/fs/ext4/dir.c > @@ -258,6 +258,12 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) > > while (ctx->pos < inode->i_size > && offset < sb->s_blocksize) { > + /* Ensure that at least the shortest possible > + * dirent will be read from within the bh's data. > + */ > + if (offset + offsetof(struct ext4_dir_entry_2, name) > + > bh->b_size) > + break; Why wouldn't you encode this check in __ext4_check_dir_entry and solve this problem for all the callsites? --D > de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); > if (ext4_check_dir_entry(inode, file, de, bh, > bh->b_data, bh->b_size, > -- > 2.50.0 > >