All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] shmem: don't call put_super() when fill_super() failed.
@ 2018-05-14  6:57 Tetsuo Handa
  2018-05-14 17:04 ` Eric Biggers
  0 siblings, 1 reply; 9+ messages in thread
From: Tetsuo Handa @ 2018-05-14  6:57 UTC (permalink / raw)
  To: syzbot+d2586fde8fdcead3647f, viro; +Cc: hughd, syzkaller-bugs, linux-mm



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] shmem: don't call put_super() when fill_super() failed.
  2018-05-14  6:57 [PATCH] shmem: don't call put_super() when fill_super() failed Tetsuo Handa
@ 2018-05-14 17:04 ` Eric Biggers
  2018-05-14 17:11   ` Eric Biggers
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Biggers @ 2018-05-14 17:04 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: syzbot+d2586fde8fdcead3647f, viro, hughd, syzkaller-bugs, linux-mm

Hi Tetsuo,

On Mon, May 14, 2018 at 03:57:31PM +0900, Tetsuo Handa wrote:
> From 193d9cb8b5dfc50c693d4bdd345cedb615bbf5ae Mon Sep 17 00:00:00 2001
> From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Date: Mon, 14 May 2018 15:25:13 +0900
> Subject: [PATCH] shmem: don't call put_super() when fill_super() failed.
> 
> syzbot is reporting NULL pointer dereference at shmem_unused_huge_count()
> [1]. This is because shmem_fill_super() is calling shmem_put_super() which
> immediately releases memory before unregister_shrinker() is called by
> deactivate_locked_super() after fill_super() in mount_nodev() failed.
> Fix this by leaving the call to shmem_put_super() to
> generic_shutdown_super() from kill_anon_super() from kill_litter_super()
>  from deactivate_locked_super().
> 
> [1] https://syzkaller.appspot.com/bug?id=46e792849791f4abbac898880e8522054e032391
> 
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Reported-by: syzbot <syzbot+d2586fde8fdcead3647f@syzkaller.appspotmail.com>
> Cc: Al Viro <viro@ZenIV.linux.org.uk>
> ---
>  mm/shmem.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 9d6c7e5..18e134c 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -3843,7 +3843,6 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
>  	return 0;
>  
>  failed:
> -	shmem_put_super(sb);
>  	return err;
>  }
>  
> -- 
> 1.8.3.1

I'm not following, since generic_shutdown_super() only calls ->put_super() if
->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
real problem that s_shrink is registered too early, causing super_cache_count()
and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
completed?  Or alternatively, the problem is that super_cache_count() doesn't
check for SB_ACTIVE.

Eric

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] shmem: don't call put_super() when fill_super() failed.
  2018-05-14 17:04 ` Eric Biggers
@ 2018-05-14 17:11   ` Eric Biggers
  2018-05-14 18:07     ` Al Viro
                       ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Eric Biggers @ 2018-05-14 17:11 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: syzbot+d2586fde8fdcead3647f, viro, hughd, syzkaller-bugs,
	linux-mm, Dave Chinner

On Mon, May 14, 2018 at 10:04:23AM -0700, Eric Biggers wrote:
> Hi Tetsuo,
> 
> On Mon, May 14, 2018 at 03:57:31PM +0900, Tetsuo Handa wrote:
> > From 193d9cb8b5dfc50c693d4bdd345cedb615bbf5ae Mon Sep 17 00:00:00 2001
> > From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> > Date: Mon, 14 May 2018 15:25:13 +0900
> > Subject: [PATCH] shmem: don't call put_super() when fill_super() failed.
> > 
> > syzbot is reporting NULL pointer dereference at shmem_unused_huge_count()
> > [1]. This is because shmem_fill_super() is calling shmem_put_super() which
> > immediately releases memory before unregister_shrinker() is called by
> > deactivate_locked_super() after fill_super() in mount_nodev() failed.
> > Fix this by leaving the call to shmem_put_super() to
> > generic_shutdown_super() from kill_anon_super() from kill_litter_super()
> >  from deactivate_locked_super().
> > 
> > [1] https://syzkaller.appspot.com/bug?id=46e792849791f4abbac898880e8522054e032391
> > 
> > Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> > Reported-by: syzbot <syzbot+d2586fde8fdcead3647f@syzkaller.appspotmail.com>
> > Cc: Al Viro <viro@ZenIV.linux.org.uk>
> > ---
> >  mm/shmem.c | 1 -
> >  1 file changed, 1 deletion(-)
> > 
> > diff --git a/mm/shmem.c b/mm/shmem.c
> > index 9d6c7e5..18e134c 100644
> > --- a/mm/shmem.c
> > +++ b/mm/shmem.c
> > @@ -3843,7 +3843,6 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
> >  	return 0;
> >  
> >  failed:
> > -	shmem_put_super(sb);
> >  	return err;
> >  }
> >  
> > -- 
> > 1.8.3.1
> 
> I'm not following, since generic_shutdown_super() only calls ->put_super() if
> ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> real problem that s_shrink is registered too early, causing super_cache_count()
> and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> completed?  Or alternatively, the problem is that super_cache_count() doesn't
> check for SB_ACTIVE.
> 

Coincidentally, this is already going to be fixed by commit 79f546a696bff259
("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.

- Eric

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] shmem: don't call put_super() when fill_super() failed.
  2018-05-14 17:11   ` Eric Biggers
@ 2018-05-14 18:07     ` Al Viro
  2018-05-14 20:59     ` Tetsuo Handa
  2018-05-15  0:27     ` Tetsuo Handa
  2 siblings, 0 replies; 9+ messages in thread
From: Al Viro @ 2018-05-14 18:07 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Tetsuo Handa, syzbot+d2586fde8fdcead3647f, hughd, syzkaller-bugs,
	linux-mm, Dave Chinner

On Mon, May 14, 2018 at 10:11:54AM -0700, Eric Biggers wrote:

> > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > real problem that s_shrink is registered too early, causing super_cache_count()
> > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > check for SB_ACTIVE.
> > 
> 
> Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.

Exactly.  While we are at it, we could add

static void shmem_kill_super(struct super_block *sb)
{
        struct shmem_sb_info *sbinfo = SHMEM_SB(sb);

	kill_litter_super(sb);
	if (sbinfo) {
		percpu_counter_destroy(&sbinfo->used_blocks);
		mpol_put(sbinfo->mpol);
		kfree(sbinfo);
	}
}

use that for ->kill_sb() and to hell with shmem_put_super() *and* its call in
cleanup path of shmem_fill_super() - these err = -E...; goto failed; in there
become simply return -E...;

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] shmem: don't call put_super() when fill_super() failed.
  2018-05-14 17:11   ` Eric Biggers
  2018-05-14 18:07     ` Al Viro
@ 2018-05-14 20:59     ` Tetsuo Handa
  2018-05-15  0:27     ` Tetsuo Handa
  2 siblings, 0 replies; 9+ messages in thread
From: Tetsuo Handa @ 2018-05-14 20:59 UTC (permalink / raw)
  To: ebiggers3
  Cc: syzbot+d2586fde8fdcead3647f, viro, hughd, syzkaller-bugs,
	linux-mm, dchinner

Eric Biggers wrote:
> > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > real problem that s_shrink is registered too early, causing super_cache_count()
> > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > check for SB_ACTIVE.
> > 
> 
> Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.

Indeed. This is use before initialisation bug which will be fixed by commit 79f546a696bff259.

#syz fix: fs: don't scan the inode cache before SB_BORN is set

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] shmem: don't call put_super() when fill_super() failed.
  2018-05-14 17:11   ` Eric Biggers
  2018-05-14 18:07     ` Al Viro
  2018-05-14 20:59     ` Tetsuo Handa
@ 2018-05-15  0:27     ` Tetsuo Handa
  2018-05-15  0:39       ` Al Viro
  2 siblings, 1 reply; 9+ messages in thread
From: Tetsuo Handa @ 2018-05-15  0:27 UTC (permalink / raw)
  To: Eric Biggers
  Cc: syzbot+d2586fde8fdcead3647f, viro, hughd, syzkaller-bugs,
	linux-mm, Dave Chinner

Eric Biggers wrote:
> > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > real problem that s_shrink is registered too early, causing super_cache_count()
> > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > check for SB_ACTIVE.
> > 
> 
> Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.
> 

Just an idea, but if shrinker registration is too early, can't we postpone it
like below?

--- a/fs/super.c
+++ b/fs/super.c
@@ -521,7 +521,6 @@ struct super_block *sget_userns(struct file_system_type *type,
 	hlist_add_head(&s->s_instances, &type->fs_supers);
 	spin_unlock(&sb_lock);
 	get_filesystem(type);
-	register_shrinker_prepared(&s->s_shrink);
 	return s;
 }
 
@@ -1287,6 +1286,7 @@ struct dentry *
 	WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
 		"negative value (%lld)\n", type->name, sb->s_maxbytes);
 
+	register_shrinker_prepared(&sb->s_shrink);
 	up_write(&sb->s_umount);
 	free_secdata(secdata);
 	return root;
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -313,6 +313,7 @@ int prealloc_shrinker(struct shrinker *shrinker)
 	shrinker->nr_deferred = kzalloc(size, GFP_KERNEL);
 	if (!shrinker->nr_deferred)
 		return -ENOMEM;
+	INIT_LIST_HEAD(&shrinker->list);
 	return 0;
 }
 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] shmem: don't call put_super() when fill_super() failed.
  2018-05-15  0:27     ` Tetsuo Handa
@ 2018-05-15  0:39       ` Al Viro
  2018-05-15  0:52         ` Tetsuo Handa
  0 siblings, 1 reply; 9+ messages in thread
From: Al Viro @ 2018-05-15  0:39 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: Eric Biggers, syzbot+d2586fde8fdcead3647f, hughd, syzkaller-bugs,
	linux-mm, Dave Chinner

On Tue, May 15, 2018 at 09:27:35AM +0900, Tetsuo Handa wrote:
> Eric Biggers wrote:
> > > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > > real problem that s_shrink is registered too early, causing super_cache_count()
> > > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > > check for SB_ACTIVE.
> > > 
> > 
> > Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> > ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.
> > 
> 
> Just an idea, but if shrinker registration is too early, can't we postpone it
> like below?

Wonderful.  And when ->mount() returns you a subtree of the same filesystem again,
that will do what, exactly?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] shmem: don't call put_super() when fill_super() failed.
  2018-05-15  0:39       ` Al Viro
@ 2018-05-15  0:52         ` Tetsuo Handa
  2018-05-15  1:13           ` Al Viro
  0 siblings, 1 reply; 9+ messages in thread
From: Tetsuo Handa @ 2018-05-15  0:52 UTC (permalink / raw)
  To: Al Viro
  Cc: Eric Biggers, syzbot+d2586fde8fdcead3647f, hughd, syzkaller-bugs,
	linux-mm, Dave Chinner

> On Tue, May 15, 2018 at 09:27:35AM +0900, Tetsuo Handa wrote:
> > Eric Biggers wrote:
> > > > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > > > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > > > real problem that s_shrink is registered too early, causing super_cache_count()
> > > > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > > > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > > > check for SB_ACTIVE.
> > > > 
> > > 
> > > Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> > > ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.
> > > 
> > 
> > Just an idea, but if shrinker registration is too early, can't we postpone it
> > like below?
> 
> Wonderful.  And when ->mount() returns you a subtree of the same filesystem again,
> that will do what, exactly?
> 
Can't we detect it via list_empty(&sb->s_shrink.list) test
before calling register_shrinker_prepared(&sb->s_shrink) ?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] shmem: don't call put_super() when fill_super() failed.
  2018-05-15  0:52         ` Tetsuo Handa
@ 2018-05-15  1:13           ` Al Viro
  0 siblings, 0 replies; 9+ messages in thread
From: Al Viro @ 2018-05-15  1:13 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: Eric Biggers, syzbot+d2586fde8fdcead3647f, hughd, syzkaller-bugs,
	linux-mm, Dave Chinner

On Tue, May 15, 2018 at 09:52:37AM +0900, Tetsuo Handa wrote:
> > On Tue, May 15, 2018 at 09:27:35AM +0900, Tetsuo Handa wrote:
> > > Eric Biggers wrote:
> > > > > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > > > > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > > > > real problem that s_shrink is registered too early, causing super_cache_count()
> > > > > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > > > > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > > > > check for SB_ACTIVE.
> > > > > 
> > > > 
> > > > Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> > > > ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.
> > > > 
> > > 
> > > Just an idea, but if shrinker registration is too early, can't we postpone it
> > > like below?
> > 
> > Wonderful.  And when ->mount() returns you a subtree of the same filesystem again,
> > that will do what, exactly?
> > 
> Can't we detect it via list_empty(&sb->s_shrink.list) test
> before calling register_shrinker_prepared(&sb->s_shrink) ?

What for?  Seriously, what's the benefit of doing that in such a convoluted way?
Avoiding a trivial check in super_cache_count()?  The same check we normally
do in places where we are not holding an active reference to superblock and
want to make sure it's alive, at that...

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-05-15  1:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-14  6:57 [PATCH] shmem: don't call put_super() when fill_super() failed Tetsuo Handa
2018-05-14 17:04 ` Eric Biggers
2018-05-14 17:11   ` Eric Biggers
2018-05-14 18:07     ` Al Viro
2018-05-14 20:59     ` Tetsuo Handa
2018-05-15  0:27     ` Tetsuo Handa
2018-05-15  0:39       ` Al Viro
2018-05-15  0:52         ` Tetsuo Handa
2018-05-15  1:13           ` Al Viro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.