Re: [PATCH] fs: erofs: remember if kobject_init_and_add was done

From: Huang Jianan
Date: Tue Mar 15 2022 - 07:05:40 EST


在 2022/3/15 18:55, Gao Xiang 写道:
On Tue, Mar 15, 2022 at 06:43:01PM +0800, Huang Jianan wrote:
在 2022/3/15 15:51, Dongliang Mu 写道:
From: Dongliang Mu <mudongliangabcd@xxxxxxxxx>

Syzkaller hit 'WARNING: kobject bug in erofs_unregister_sysfs'. This bug
is triggered by injecting fault in kobject_init_and_add of
erofs_unregister_sysfs.

Fix this by remembering if kobject_init_and_add is successful.

Note that I've tested the patch and the crash does not occur any more.

Reported-by: syzkaller <syzkaller@xxxxxxxxxxxxxxxx>
Signed-off-by: Dongliang Mu <mudongliangabcd@xxxxxxxxx>
---
fs/erofs/internal.h | 1 +
fs/erofs/sysfs.c | 9 ++++++---
2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 5aa2cf2c2f80..9e20665e3f68 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -144,6 +144,7 @@ struct erofs_sb_info {
u32 feature_incompat;
/* sysfs support */
+ bool s_sysfs_inited;
Hi Dongliang,

How about using sbi->s_kobj.state_in_sysfs to avoid adding a extra member in
sbi ?
Ok, I have no tendency of these (I'm fine with either ways).
I've seen some usage like:

static inline int device_is_registered(struct device *dev)
{
return dev->kobj.state_in_sysfs;
}

But I'm still not sure if we need to rely on such internal
interface.. More thoughts?

Yeah... It seems that it is better to use some of the interfaces provided by kobject,
otherwise we should still maintain this state in sbi.

Thanks,
Jianan

Thanks,
Gao Xiang
Thanks,
Jianan

struct kobject s_kobj; /* /sys/fs/erofs/<devname> */
struct completion s_kobj_unregister;
};
diff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c
index dac252bc9228..2b48a4df19b4 100644
--- a/fs/erofs/sysfs.c
+++ b/fs/erofs/sysfs.c
@@ -209,6 +209,7 @@ int erofs_register_sysfs(struct super_block *sb)
"%s", sb->s_id);
if (err)
goto put_sb_kobj;
+ sbi->s_sysfs_inited = true;
return 0;
put_sb_kobj:
@@ -221,9 +222,11 @@ void erofs_unregister_sysfs(struct super_block *sb)
{
struct erofs_sb_info *sbi = EROFS_SB(sb);
- kobject_del(&sbi->s_kobj);
- kobject_put(&sbi->s_kobj);
- wait_for_completion(&sbi->s_kobj_unregister);
+ if (sbi->s_sysfs_inited) {
+ kobject_del(&sbi->s_kobj);
+ kobject_put(&sbi->s_kobj);
+ wait_for_completion(&sbi->s_kobj_unregister);
+ }
}
int __init erofs_init_sysfs(void)