]> git.baikalelectronics.ru Git - kernel.git/commitdiff
mm: shrinkers: fix double kfree on shrinker name
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Wed, 20 Jul 2022 14:47:55 +0000 (23:47 +0900)
committerakpm <akpm@linux-foundation.org>
Sat, 30 Jul 2022 01:07:13 +0000 (18:07 -0700)
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
Link: https://lkml.kernel.org/r/ffa62ece-6a42-2644-16cf-0d33ef32c676@I-love.SAKURA.ne.jp
Fixes: 55267caba61961f3 ("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>
mm/shrinker_debug.c
mm/vmscan.c

index e5b40c43221d07a335f900cd7ea6df54535a3134..b05295bab3222645b8cb029f10f5148e03ce3e13 100644 (file)
@@ -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;
index f58761cea0a0609b0dab9d0a5e19f82ee7ed88d3..fbb4108250ee4efab573f49f14bb636c6f902d0a 100644 (file)
@@ -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;
 }
@@ -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);
@@ -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