From 81b21c0f0138ff5a499eafc3eb0578ad2a99622c Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Date: Tue, 11 Apr 2023 19:57:33 +0900
Subject: [PATCH] fs: hfsplus: remove WARN_ON() from
hfsplus_cat_{read,write}_inode()
Git-commit: 81b21c0f0138ff5a499eafc3eb0578ad2a99622c
Patch-mainline: v6.4-rc1
References: git-fixes
syzbot is hitting WARN_ON() in hfsplus_cat_{read,write}_inode(), for
crafted filesystem image can contain bogus length. There conditions are
not kernel bugs that can justify kernel to panic.
Reported-by: syzbot <syzbot+e2787430e752a92b8750@syzkaller.appspotmail.com>
Link: https://syzkaller.appspot.com/bug?extid=e2787430e752a92b8750
Reported-by: syzbot <syzbot+4913dca2ea6e4d43f3f1@syzkaller.appspotmail.com>
Link: https://syzkaller.appspot.com/bug?extid=4913dca2ea6e4d43f3f1
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Message-id: <15308173-5252-d6a3-ae3b-e96d46cb6f41@I-love.SAKURA.ne.jp>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Acked-by: Anthony Iliopoulos <ailiop@suse.com>
---
fs/hfsplus/inode.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -487,7 +487,11 @@ int hfsplus_cat_read_inode(struct inode
if (type == HFSPLUS_FOLDER) {
struct hfsplus_cat_folder *folder = &entry.folder;
- WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_folder));
+ if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) {
+ pr_err("bad catalog folder entry\n");
+ res = -EIO;
+ goto out;
+ }
hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
sizeof(struct hfsplus_cat_folder));
hfsplus_get_perms(inode, &folder->permissions, 1);
@@ -507,7 +511,11 @@ int hfsplus_cat_read_inode(struct inode
} else if (type == HFSPLUS_FILE) {
struct hfsplus_cat_file *file = &entry.file;
- WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_file));
+ if (fd->entrylength < sizeof(struct hfsplus_cat_file)) {
+ pr_err("bad catalog file entry\n");
+ res = -EIO;
+ goto out;
+ }
hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
sizeof(struct hfsplus_cat_file));
@@ -538,6 +546,7 @@ int hfsplus_cat_read_inode(struct inode
pr_err("bad catalog entry used to create inode\n");
res = -EIO;
}
+out:
return res;
}
@@ -546,6 +555,7 @@ int hfsplus_cat_write_inode(struct inode
struct inode *main_inode = inode;
struct hfs_find_data fd;
hfsplus_cat_entry entry;
+ int res = 0;
if (HFSPLUS_IS_RSRC(inode))
main_inode = HFSPLUS_I(inode)->rsrc_inode;
@@ -564,7 +574,11 @@ int hfsplus_cat_write_inode(struct inode
if (S_ISDIR(main_inode->i_mode)) {
struct hfsplus_cat_folder *folder = &entry.folder;
- WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_folder));
+ if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
+ pr_err("bad catalog folder entry\n");
+ res = -EIO;
+ goto out;
+ }
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_folder));
/* simple node checks? */
@@ -589,7 +603,11 @@ int hfsplus_cat_write_inode(struct inode
} else {
struct hfsplus_cat_file *file = &entry.file;
- WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_file));
+ if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
+ pr_err("bad catalog file entry\n");
+ res = -EIO;
+ goto out;
+ }
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
sizeof(struct hfsplus_cat_file));
hfsplus_inode_write_fork(inode, &file->data_fork);
@@ -610,5 +628,5 @@ int hfsplus_cat_write_inode(struct inode
set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
out:
hfs_find_exit(&fd);
- return 0;
+ return res;
}