diff mbox

hfsplus: don't return 0 when fill_super() failed

Message ID d83ce31a-874c-dd5b-f790-41405983a5be@I-love.SAKURA.ne.jp (mailing list archive)
State New, archived
Headers show

Commit Message

Tetsuo Handa May 15, 2018, 10:08 a.m. UTC
From f78a5fe168290cb9e009f4d907d04b5bfe277831 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Date: Tue, 15 May 2018 11:38:38 +0900
Subject: [PATCH] hfsplus: don't return 0 when fill_super() failed

syzbot is reporting NULL pointer dereference at mount_fs() [1].
This is because hfsplus_fill_super() is by error returning 0 when
hfsplus_fill_super() detected invalid filesystem image, and mount_bdev()
is returning NULL because dget(s->s_root) == NULL if s->s_root == NULL,
and mount_fs() is accessing root->d_sb because IS_ERR(root) == false
if root == NULL. Fix this by returning -EINVAL when hfsplus_fill_super()
detected invalid filesystem image.

[1] https://syzkaller.appspot.com/bug?id=21acb6850cecbc960c927229e597158cf35f33d0

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Reported-by: syzbot <syzbot+01ffaf5d9568dd1609f7@syzkaller.appspotmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/hfsplus/super.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Ernesto A. Fernández May 19, 2018, 11:25 p.m. UTC | #1
On Sat, May 19, 2018 at 10:55:04PM +0900, Tetsuo Handa wrote:
> Ernesto A. Fernandez wrote:
> > On Tue, May 15, 2018 at 07:08:24PM +0900, Tetsuo Handa wrote:
> > > From f78a5fe168290cb9e009f4d907d04b5bfe277831 Mon Sep 17 00:00:00 2001
> > > From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> > > Date: Tue, 15 May 2018 11:38:38 +0900
> > > Subject: [PATCH] hfsplus: don't return 0 when fill_super() failed
> > > 
> > > syzbot is reporting NULL pointer dereference at mount_fs() [1].
> > > This is because hfsplus_fill_super() is by error returning 0 when
> > > hfsplus_fill_super() detected invalid filesystem image, and mount_bdev()
> > > is returning NULL because dget(s->s_root) == NULL if s->s_root == NULL,
> > > and mount_fs() is accessing root->d_sb because IS_ERR(root) == false
> > > if root == NULL. Fix this by returning -EINVAL when hfsplus_fill_super()
> > > detected invalid filesystem image.
> > > 
> > > [1] https://syzkaller.appspot.com/bug?id=21acb6850cecbc960c927229e597158cf35f33d0
> > > 
> > > Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> > > Reported-by: syzbot <syzbot+01ffaf5d9568dd1609f7@syzkaller.appspotmail.com>
> > > Cc: Al Viro <viro@zeniv.linux.org.uk>
> > > ---
> > >  fs/hfsplus/super.c | 4 +++-
> > >  1 file changed, 3 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
> > > index 513c357..9e690ae 100644
> > > --- a/fs/hfsplus/super.c
> > > +++ b/fs/hfsplus/super.c
> > > @@ -524,8 +524,10 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
> > >  		goto out_put_root;
> > >  	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
> > >  		hfs_find_exit(&fd);
> > > -		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER))
> > > +		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
> > > +			err = -EINVAL;
> > >  			goto out_put_root;
> > > +		}
> > >  		inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id));
> > >  		if (IS_ERR(inode)) {
> > >  			err = PTR_ERR(inode);
> > > -- 
> > > 1.8.3.1
> > > 
> > > 
> > 
> > I sent this same patch some time ago:
> > 
> > https://www.spinics.net/lists/linux-fsdevel/msg125241.html
> > 
> > This syzbot report did not reach me, though. I don't know why.
> > 
> Oh, I didn't notice that you already wrote that patch.
> Anyway, whom to ask for merge? Al Viro? Andrew Morton?

I think Andrew Morton, but only one of my patches for hfsplus has been
picked up so far, so I can't tell you for sure.

Al Viro wasn't happy with this patchset and thought it was better to let
->put_super() handle the cleanup. I made a second version but I don't
think he had the time to look at it yet.
Al Viro May 19, 2018, 11:47 p.m. UTC | #2
On Sat, May 19, 2018 at 08:25:04PM -0300, Ernesto A. Fernández wrote:

> > Oh, I didn't notice that you already wrote that patch.
> > Anyway, whom to ask for merge? Al Viro? Andrew Morton?
> 
> I think Andrew Morton, but only one of my patches for hfsplus has been
> picked up so far, so I can't tell you for sure.
> 
> Al Viro wasn't happy with this patchset and thought it was better to let
> ->put_super() handle the cleanup. I made a second version but I don't
> think he had the time to look at it yet.

Sorry, buried under fs/aio.c review (aio-poll stuff) and assorted shite
around mkdir/open-by-handle right now ;-/  I'll get to that tonight or
tomorrow morning.
Ernesto A. Fernández June 21, 2018, 1:45 a.m. UTC | #3
On Tue, May 15, 2018 at 07:08:24PM +0900, Tetsuo Handa wrote:
> From f78a5fe168290cb9e009f4d907d04b5bfe277831 Mon Sep 17 00:00:00 2001
> From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Date: Tue, 15 May 2018 11:38:38 +0900
> Subject: [PATCH] hfsplus: don't return 0 when fill_super() failed
> 
> syzbot is reporting NULL pointer dereference at mount_fs() [1].
> This is because hfsplus_fill_super() is by error returning 0 when
> hfsplus_fill_super() detected invalid filesystem image, and mount_bdev()
> is returning NULL because dget(s->s_root) == NULL if s->s_root == NULL,
> and mount_fs() is accessing root->d_sb because IS_ERR(root) == false
> if root == NULL. Fix this by returning -EINVAL when hfsplus_fill_super()
> detected invalid filesystem image.
> 
> [1] https://syzkaller.appspot.com/bug?id=21acb6850cecbc960c927229e597158cf35f33d0
> 
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Reported-by: syzbot <syzbot+01ffaf5d9568dd1609f7@syzkaller.appspotmail.com>
> Cc: Al Viro <viro@zeniv.linux.org.uk>

It's been too long. I think I should give up on my patch. Maybe a review
can help your version get merged.

Reviewed-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>

> ---
>  fs/hfsplus/super.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
> index 513c357..9e690ae 100644
> --- a/fs/hfsplus/super.c
> +++ b/fs/hfsplus/super.c
> @@ -524,8 +524,10 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
>  		goto out_put_root;
>  	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
>  		hfs_find_exit(&fd);
> -		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER))
> +		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
> +			err = -EINVAL;
>  			goto out_put_root;
> +		}
>  		inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id));
>  		if (IS_ERR(inode)) {
>  			err = PTR_ERR(inode);
> -- 
> 1.8.3.1
> 
>
diff mbox

Patch

diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 513c357..9e690ae 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -524,8 +524,10 @@  static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
 		goto out_put_root;
 	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
 		hfs_find_exit(&fd);
-		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER))
+		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
+			err = -EINVAL;
 			goto out_put_root;
+		}
 		inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id));
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);