Takashi Iwai 1a0085
From c65234b283a65cfbfc94619655e820a5e55199eb Mon Sep 17 00:00:00 2001
Takashi Iwai 1a0085
From: Chen Zhongjin <chenzhongjin@huawei.com>
Takashi Iwai 1a0085
Date: Mon, 17 Oct 2022 09:42:30 +0800
Takashi Iwai 1a0085
Subject: [PATCH] configfs: fix possible memory leak in configfs_create_dir()
Takashi Iwai 1a0085
Git-commit: c65234b283a65cfbfc94619655e820a5e55199eb
Takashi Iwai 1a0085
Patch-mainline: v6.2-rc1
Takashi Iwai 1a0085
References: git-fixes
Takashi Iwai 1a0085
Takashi Iwai 1a0085
kmemleak reported memory leaks in configfs_create_dir():
Takashi Iwai 1a0085
Takashi Iwai 1a0085
unreferenced object 0xffff888009f6af00 (size 192):
Takashi Iwai 1a0085
  comm "modprobe", pid 3777, jiffies 4295537735 (age 233.784s)
Takashi Iwai 1a0085
  backtrace:
Takashi Iwai 1a0085
    kmem_cache_alloc (mm/slub.c:3250 mm/slub.c:3256 mm/slub.c:3263 mm/slub.c:3273)
Takashi Iwai 1a0085
    new_fragment (./include/linux/slab.h:600 fs/configfs/dir.c:163)
Takashi Iwai 1a0085
    configfs_register_subsystem (fs/configfs/dir.c:1857)
Takashi Iwai 1a0085
    basic_write (drivers/hwtracing/stm/p_basic.c:14) stm_p_basic
Takashi Iwai 1a0085
    do_one_initcall (init/main.c:1296)
Takashi Iwai 1a0085
    do_init_module (kernel/module/main.c:2455)
Takashi Iwai 1a0085
    ...
Takashi Iwai 1a0085
Takashi Iwai 1a0085
unreferenced object 0xffff888003ba7180 (size 96):
Takashi Iwai 1a0085
  comm "modprobe", pid 3777, jiffies 4295537735 (age 233.784s)
Takashi Iwai 1a0085
  backtrace:
Takashi Iwai 1a0085
    kmem_cache_alloc (mm/slub.c:3250 mm/slub.c:3256 mm/slub.c:3263 mm/slub.c:3273)
Takashi Iwai 1a0085
    configfs_new_dirent (./include/linux/slab.h:723 fs/configfs/dir.c:194)
Takashi Iwai 1a0085
    configfs_make_dirent (fs/configfs/dir.c:248)
Takashi Iwai 1a0085
    configfs_create_dir (fs/configfs/dir.c:296)
Takashi Iwai 1a0085
    configfs_attach_group.isra.28 (fs/configfs/dir.c:816 fs/configfs/dir.c:852)
Takashi Iwai 1a0085
    configfs_register_subsystem (fs/configfs/dir.c:1881)
Takashi Iwai 1a0085
    basic_write (drivers/hwtracing/stm/p_basic.c:14) stm_p_basic
Takashi Iwai 1a0085
    do_one_initcall (init/main.c:1296)
Takashi Iwai 1a0085
    do_init_module (kernel/module/main.c:2455)
Takashi Iwai 1a0085
    ...
Takashi Iwai 1a0085
Takashi Iwai 1a0085
This is because the refcount is not correct in configfs_make_dirent().
Takashi Iwai 1a0085
For normal stage, the refcount is changing as:
Takashi Iwai 1a0085
Takashi Iwai 1a0085
configfs_register_subsystem()
Takashi Iwai 1a0085
  configfs_create_dir()
Takashi Iwai 1a0085
    configfs_make_dirent()
Takashi Iwai 1a0085
      configfs_new_dirent() # set s_count = 1
Takashi Iwai 1a0085
      dentry->d_fsdata = configfs_get(sd); # s_count = 2
Takashi Iwai 1a0085
...
Takashi Iwai 1a0085
configfs_unregister_subsystem()
Takashi Iwai 1a0085
  configfs_remove_dir()
Takashi Iwai 1a0085
    remove_dir()
Takashi Iwai 1a0085
      configfs_remove_dirent() # s_count = 1
Takashi Iwai 1a0085
    dput() ...
Takashi Iwai 1a0085
      *dentry_unlink_inode()*
Takashi Iwai 1a0085
        configfs_d_iput() # s_count = 0, release
Takashi Iwai 1a0085
Takashi Iwai 1a0085
However, if we failed in configfs_create():
Takashi Iwai 1a0085
Takashi Iwai 1a0085
configfs_register_subsystem()
Takashi Iwai 1a0085
  configfs_create_dir()
Takashi Iwai 1a0085
    configfs_make_dirent() # s_count = 2
Takashi Iwai 1a0085
    ...
Takashi Iwai 1a0085
    configfs_create() # fail
Takashi Iwai 1a0085
    ->out_remove:
Takashi Iwai 1a0085
    configfs_remove_dirent(dentry)
Takashi Iwai 1a0085
      configfs_put(sd) # s_count = 1
Takashi Iwai 1a0085
      return PTR_ERR(inode);
Takashi Iwai 1a0085
Takashi Iwai 1a0085
There is no inode in the error path, so the configfs_d_iput() is lost
Takashi Iwai 1a0085
and makes sd and fragment memory leaked.
Takashi Iwai 1a0085
Takashi Iwai 1a0085
To fix this, when we failed in configfs_create(), manually call
Takashi Iwai 1a0085
configfs_put(sd) to keep the refcount correct.
Takashi Iwai 1a0085
Takashi Iwai 1a0085
Fixes: 7063fbf22611 ("[PATCH] configfs: User-driven configuration filesystem")
Takashi Iwai 1a0085
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
Takashi Iwai 1a0085
Signed-off-by: Christoph Hellwig <hch@lst.de>
Takashi Iwai 1a0085
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 1a0085
Takashi Iwai 1a0085
---
Takashi Iwai 1a0085
 fs/configfs/dir.c | 2 ++
Takashi Iwai 1a0085
 1 file changed, 2 insertions(+)
Takashi Iwai 1a0085
Takashi Iwai 1a0085
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
Takashi Iwai 1a0085
index d1f9d2632202..ec6519e1ca3b 100644
Takashi Iwai 1a0085
--- a/fs/configfs/dir.c
Takashi Iwai 1a0085
+++ b/fs/configfs/dir.c
Takashi Iwai 1a0085
@@ -316,6 +316,7 @@ static int configfs_create_dir(struct config_item *item, struct dentry *dentry,
Takashi Iwai 1a0085
 	return 0;
Takashi Iwai 1a0085
 
Takashi Iwai 1a0085
 out_remove:
Takashi Iwai 1a0085
+	configfs_put(dentry->d_fsdata);
Takashi Iwai 1a0085
 	configfs_remove_dirent(dentry);
Takashi Iwai 1a0085
 	return PTR_ERR(inode);
Takashi Iwai 1a0085
 }
Takashi Iwai 1a0085
@@ -382,6 +383,7 @@ int configfs_create_link(struct configfs_dirent *target, struct dentry *parent,
Takashi Iwai 1a0085
 	return 0;
Takashi Iwai 1a0085
 
Takashi Iwai 1a0085
 out_remove:
Takashi Iwai 1a0085
+	configfs_put(dentry->d_fsdata);
Takashi Iwai 1a0085
 	configfs_remove_dirent(dentry);
Takashi Iwai 1a0085
 	return PTR_ERR(inode);
Takashi Iwai 1a0085
 }
Takashi Iwai 1a0085
-- 
Takashi Iwai 1a0085
2.35.3
Takashi Iwai 1a0085