From: Viacheslav Dubeyko <slava@dubeyko.com>
To: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>,
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>,
Yangtao Li <frank.li@vivo.com>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: Re: [PATCH v2] hfsplus: Verify inode mode when loading from disk
Date: Mon, 17 Nov 2025 14:52:24 -0800 [thread overview]
Message-ID: <eaf1c94b70ba7fdc516c5e10bb821f3e8b9aaa9d.camel@dubeyko.com> (raw)
In-Reply-To: <04ded9f9-73fb-496c-bfa5-89c4f5d1d7bb@I-love.SAKURA.ne.jp>
On Sat, 2025-11-15 at 18:18 +0900, Tetsuo Handa wrote:
> syzbot is reporting that S_IFMT bits of inode->i_mode can become
> bogus when
> the S_IFMT bits of the 16bits "mode" field loaded from disk are
> corrupted.
>
> According to [1], the permissions field was treated as reserved in
> Mac OS
> 8 and 9. According to [2], the reserved field was explicitly
> initialized
> with 0, and that field must remain 0 as long as reserved. Therefore,
> when
> the "mode" field is not 0 (i.e. no longer reserved), the file must be
> S_IFDIR if dir == 1, and the file must be one of
> S_IFREG/S_IFLNK/S_IFCHR/
> S_IFBLK/S_IFIFO/S_IFSOCK if dir == 0.
>
> Reported-by: syzbot
> <syzbot+895c23f6917da440ed0d@syzkaller.appspotmail.com>
> Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d
> Link:
> https://developer.apple.com/library/archive/technotes/tn/tn1150.html#HFSPlusPermissions
> [1]
> Link:
> https://developer.apple.com/library/archive/technotes/tn/tn1150.html#ReservedAndPadFields
> [2]
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> ---
> fs/hfsplus/inode.c | 32 ++++++++++++++++++++++++++++----
> 1 file changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
> index b51a411ecd23..e290e417ed3a 100644
> --- a/fs/hfsplus/inode.c
> +++ b/fs/hfsplus/inode.c
> @@ -180,13 +180,29 @@ const struct dentry_operations
> hfsplus_dentry_operations = {
> .d_compare = hfsplus_compare_dentry,
> };
>
> -static void hfsplus_get_perms(struct inode *inode,
> - struct hfsplus_perm *perms, int dir)
> +static int hfsplus_get_perms(struct inode *inode,
> + struct hfsplus_perm *perms, int dir)
> {
> struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
> u16 mode;
>
> mode = be16_to_cpu(perms->mode);
> + if (dir) {
> + if (mode && !S_ISDIR(mode))
> + goto bad_type;
> + } else if (mode) {
> + switch (mode & S_IFMT) {
> + case S_IFREG:
> + case S_IFLNK:
> + case S_IFCHR:
> + case S_IFBLK:
> + case S_IFIFO:
> + case S_IFSOCK:
> + break;
> + default:
> + goto bad_type;
> + }
> + }
>
> i_uid_write(inode, be32_to_cpu(perms->owner));
> if ((test_bit(HFSPLUS_SB_UID, &sbi->flags)) ||
> (!i_uid_read(inode) && !mode))
> @@ -212,6 +228,10 @@ static void hfsplus_get_perms(struct inode
> *inode,
> inode->i_flags |= S_APPEND;
> else
> inode->i_flags &= ~S_APPEND;
> + return 0;
> +bad_type:
> + pr_err("invalid file type 0%04o for inode %lu\n", mode,
> inode->i_ino);
> + return -EIO;
> }
>
> static int hfsplus_file_open(struct inode *inode, struct file *file)
> @@ -516,7 +536,9 @@ int hfsplus_cat_read_inode(struct inode *inode,
> struct hfs_find_data *fd)
> }
> hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
> sizeof(struct
> hfsplus_cat_folder));
> - hfsplus_get_perms(inode, &folder->permissions, 1);
> + res = hfsplus_get_perms(inode, &folder->permissions,
> 1);
> + if (res)
> + goto out;
> set_nlink(inode, 1);
> inode->i_size = 2 + be32_to_cpu(folder->valence);
> inode_set_atime_to_ts(inode, hfsp_mt2ut(folder-
> >access_date));
> @@ -545,7 +567,9 @@ int hfsplus_cat_read_inode(struct inode *inode,
> struct hfs_find_data *fd)
>
> hfsplus_inode_read_fork(inode,
> HFSPLUS_IS_RSRC(inode) ?
> &file->rsrc_fork : &file-
> >data_fork);
> - hfsplus_get_perms(inode, &file->permissions, 0);
> + res = hfsplus_get_perms(inode, &file->permissions,
> 0);
> + if (res)
> + goto out;
> set_nlink(inode, 1);
> if (S_ISREG(inode->i_mode)) {
> if (file->permissions.dev)
Looks good.
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Thanks,
Slava.
prev parent reply other threads:[~2025-11-17 22:52 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-04 13:34 [PATCH] hfsplus: Verify inode mode when loading from disk Tetsuo Handa
2025-10-07 14:22 ` Viacheslav Dubeyko
2025-10-08 11:21 ` Tetsuo Handa
2025-11-14 15:35 ` Tetsuo Handa
2025-11-14 19:29 ` Viacheslav Dubeyko
2025-11-15 9:18 ` [PATCH v2] " Tetsuo Handa
2025-11-17 22:52 ` Viacheslav Dubeyko [this message]
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=eaf1c94b70ba7fdc516c5e10bb821f3e8b9aaa9d.camel@dubeyko.com \
--to=slava@dubeyko.com \
--cc=frank.li@vivo.com \
--cc=glaubitz@physik.fu-berlin.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=penguin-kernel@I-love.SAKURA.ne.jp \
/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;
as well as URLs for NNTP newsgroup(s).