]> git.itanic.dy.fi Git - linux-stable/commitdiff
fs: hfsplus: remove WARN_ON() from hfsplus_cat_{read,write}_inode()
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Tue, 11 Apr 2023 10:57:33 +0000 (19:57 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 May 2023 11:38:34 +0000 (12:38 +0100)
[ Upstream commit 81b21c0f0138ff5a499eafc3eb0578ad2a99622c ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/hfsplus/inode.c

index ccb2a94c2032a3fdc8ba5f05870e7bb00da0b7da..4924a489c8ac0a2a24e7ae07b167dfa85dc479a7 100644 (file)
@@ -488,7 +488,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        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);
@@ -508,7 +512,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        } 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));
 
@@ -539,6 +547,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
                pr_err("bad catalog entry used to create inode\n");
                res = -EIO;
        }
+out:
        return res;
 }
 
@@ -547,6 +556,7 @@ int hfsplus_cat_write_inode(struct inode *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;
@@ -565,7 +575,11 @@ int hfsplus_cat_write_inode(struct inode *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? */
@@ -590,7 +604,11 @@ int hfsplus_cat_write_inode(struct inode *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);
@@ -611,5 +629,5 @@ int hfsplus_cat_write_inode(struct inode *inode)
        set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
 out:
        hfs_find_exit(&fd);
-       return 0;
+       return res;
 }