Skip to content

Commit

Permalink
mm: shrinkers: fix double kfree on shrinker name
Browse files Browse the repository at this point in the history
syzbot is reporting double kfree() at free_prealloced_shrinker() [1], for
destroy_unused_super() calls free_prealloced_shrinker() even if
prealloc_shrinker() returned an error.  Explicitly clear shrinker name
when prealloc_shrinker() called kfree().

[roman.gushchin@linux.dev: zero shrinker->name in all cases where shrinker->name is freed]
  Link: https://lkml.kernel.org/r/YtgteTnQTgyuKUSY@castle
Link: https://syzkaller.appspot.com/bug?extid=8b481578352d4637f510 [1]
Link: https://lkml.kernel.org/r/ffa62ece-6a42-2644-16cf-0d33ef32c676@I-love.SAKURA.ne.jp
Fixes: e33c267 ("mm: shrinkers: provide shrinkers with names")
Reported-by: syzbot <syzbot+8b481578352d4637f510@syzkaller.appspotmail.com>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Acked-by: Roman Gushchin <roman.gushchin@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
  • Loading branch information
Tetsuo Handa authored and akpm00 committed Jul 30, 2022
1 parent 187e7c4 commit 14773bf
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 2 deletions.
1 change: 1 addition & 0 deletions mm/shrinker_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ void shrinker_debugfs_remove(struct shrinker *shrinker)
lockdep_assert_held(&shrinker_rwsem);

kfree_const(shrinker->name);
shrinker->name = NULL;

if (!shrinker->debugfs_entry)
return;
Expand Down
9 changes: 7 additions & 2 deletions mm/vmscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,8 +644,10 @@ int prealloc_shrinker(struct shrinker *shrinker, const char *fmt, ...)
return -ENOMEM;

err = __prealloc_shrinker(shrinker);
if (err)
if (err) {
kfree_const(shrinker->name);
shrinker->name = NULL;
}

return err;
}
Expand All @@ -660,6 +662,7 @@ void free_prealloced_shrinker(struct shrinker *shrinker)
{
#ifdef CONFIG_SHRINKER_DEBUG
kfree_const(shrinker->name);
shrinker->name = NULL;
#endif
if (shrinker->flags & SHRINKER_MEMCG_AWARE) {
down_write(&shrinker_rwsem);
Expand Down Expand Up @@ -704,8 +707,10 @@ int register_shrinker(struct shrinker *shrinker, const char *fmt, ...)
return -ENOMEM;

err = __register_shrinker(shrinker);
if (err)
if (err) {
kfree_const(shrinker->name);
shrinker->name = NULL;
}
return err;
}
#else
Expand Down

0 comments on commit 14773bf

Please sign in to comment.