From: Edward Adam Davis <eadavis@qq.com>
To: lkp@intel.com
Cc: adilger.kernel@dilger.ca, eadavis@qq.com,
linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org,
oe-kbuild-all@lists.linux.dev,
syzbot+0c99c3f90699936c1e77@syzkaller.appspotmail.com,
syzkaller-bugs@googlegroups.com, tytso@mit.edu
Subject: [PATCH V2] ext4: Add a sanity check for next dentry when insert
Date: Mon, 28 Oct 2024 22:07:31 +0800 [thread overview]
Message-ID: <tencent_2EB5A7DB06DD92D88651C9B3EED8AEF38C06@qq.com> (raw)
In-Reply-To: <202410272114.DrZ8huEU-lkp@intel.com>
Syzbot reported a use-after-free in ext4_insert_dentry.
Before copying the file name to the next directory entry, it is necessary to
confirm whether there is enough space in the next directory entry.
When the space is insufficient, it will not be inserted and an error code
-EINVAL will be returned.
Reported-by: syzbot+0c99c3f90699936c1e77@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=0c99c3f90699936c1e77
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
V1 -> V2: change check_next_dentry to static and comments
fs/ext4/ext4.h | 2 +-
fs/ext4/inline.c | 4 +++-
fs/ext4/namei.c | 32 ++++++++++++++++++++++++++------
3 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 44b0d418143c..e07ac540ed00 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2834,7 +2834,7 @@ extern int ext4_find_dest_de(struct inode *dir, struct inode *inode,
void *buf, int buf_size,
struct ext4_filename *fname,
struct ext4_dir_entry_2 **dest_de);
-void ext4_insert_dentry(struct inode *dir, struct inode *inode,
+int ext4_insert_dentry(struct inode *dir, struct inode *inode,
struct ext4_dir_entry_2 *de,
int buf_size,
struct ext4_filename *fname);
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 3536ca7e4fcc..e318b13459d1 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -1022,7 +1022,9 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
EXT4_JTR_NONE);
if (err)
return err;
- ext4_insert_dentry(dir, inode, de, inline_size, fname);
+ err = ext4_insert_dentry(dir, inode, de, inline_size, fname);
+ if (err)
+ return err;
ext4_show_inline_dir(dir, iloc->bh, inline_start, inline_size);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 790db7eac6c2..1c9fedf36fb0 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2084,24 +2084,38 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
return 0;
}
-void ext4_insert_dentry(struct inode *dir,
+static int check_next_dentry(struct inode *dir,
struct inode *inode,
struct ext4_dir_entry_2 *de,
int buf_size,
struct ext4_filename *fname)
{
-
int nlen, rlen;
nlen = ext4_dir_rec_len(de->name_len, dir);
rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
if (de->inode) {
- struct ext4_dir_entry_2 *de1 =
+ struct ext4_dir_entry_2 *nde =
(struct ext4_dir_entry_2 *)((char *)de + nlen);
- de1->rec_len = ext4_rec_len_to_disk(rlen - nlen, buf_size);
+ nde->rec_len = ext4_rec_len_to_disk(rlen - nlen, buf_size);
de->rec_len = ext4_rec_len_to_disk(nlen, buf_size);
- de = de1;
+ de = nde;
+ rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
+ return fname_len(fname) > rlen - EXT4_BASE_DIR_LEN;
}
+
+ return 0;
+}
+
+int ext4_insert_dentry(struct inode *dir,
+ struct inode *inode,
+ struct ext4_dir_entry_2 *de,
+ int buf_size,
+ struct ext4_filename *fname)
+{
+ if (check_next_dentry(dir, inode, de, buf_size, fname))
+ return -EINVAL;
+
de->file_type = EXT4_FT_UNKNOWN;
de->inode = cpu_to_le32(inode->i_ino);
ext4_set_de_type(inode->i_sb, de, inode->i_mode);
@@ -2114,6 +2128,8 @@ void ext4_insert_dentry(struct inode *dir,
EXT4_DIRENT_HASHES(de)->minor_hash =
cpu_to_le32(hinfo->minor_hash);
}
+
+ return 0;
}
/*
@@ -2151,7 +2167,11 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
}
/* By now the buffer is marked for journaling */
- ext4_insert_dentry(dir, inode, de, blocksize, fname);
+ err = ext4_insert_dentry(dir, inode, de, blocksize, fname);
+ if (err) {
+ ext4_std_error(dir->i_sb, err);
+ return err;
+ }
/*
* XXX shouldn't update any times until successful
--
2.43.0
next prev parent reply other threads:[~2024-10-28 14:12 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-25 22:56 [syzbot] [ext4?] KASAN: use-after-free Write in ext4_insert_dentry syzbot
2024-10-27 11:09 ` [PATCH] ext4: Add a sanity check for next dentry when insert Edward Adam Davis
2024-10-27 15:45 ` kernel test robot
2024-10-28 14:07 ` Edward Adam Davis [this message]
2024-11-04 6:43 ` [PATCH V2] " kernel test robot
2024-10-27 16:06 ` [PATCH] " kernel test robot
2024-10-28 14:14 ` kernel test robot
2024-11-06 15:22 ` [syzbot] [ext4?] KASAN: use-after-free Write in ext4_insert_dentry syzbot
2025-04-15 17:29 ` Thadeu Lima de Souza Cascardo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=tencent_2EB5A7DB06DD92D88651C9B3EED8AEF38C06@qq.com \
--to=eadavis@qq.com \
--cc=adilger.kernel@dilger.ca \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lkp@intel.com \
--cc=oe-kbuild-all@lists.linux.dev \
--cc=syzbot+0c99c3f90699936c1e77@syzkaller.appspotmail.com \
--cc=syzkaller-bugs@googlegroups.com \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox