[PATCH] kernel: fix error handling in lookup_or_create_module_kobject()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In 'lookup_or_create_module_kobject()', an internal kobject is created
using 'module_ktype'. So plain 'kobject_put()' causes an attempt to use
an uninitialied completion pointer in 'module_kobject_release()' and
'mod_kobject_put()' should be used instead. But if the driver (e.g. USB
gadget as in this particular case reported by syzkaller) is configured
as compiled-in, THIS_MODULE is NULL and there is no relevant module
object to call the latter against. So introduce an internal wrapper
'__module_kobject_put()' which is expected 'struct module_kobject' and
so fix error handling in 'lookup_or_create_module_kobject()'.

Reported-by: syzbot+7fb8a372e1f6add936dd@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=7fb8a372e1f6add936dd
Fixes: 1c7777feb0e2 ("kernel: refactor lookup_or_create_module_kobject()")
Signed-off-by: Dmitry Antipov <dmantipov@xxxxxxxxx>
---
 include/linux/module.h |  3 +++
 kernel/module/sysfs.c  | 15 ++++++++++-----
 kernel/params.c        |  3 ++-
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/include/linux/module.h b/include/linux/module.h
index b3329110d668..2b4ab389c1bc 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -891,6 +891,9 @@ static inline void module_for_each_mod(int(*func)(struct module *mod, void *data
 #ifdef CONFIG_SYSFS
 extern struct kset *module_kset;
 extern const struct kobj_type module_ktype;
+void __module_kobject_put(struct module_kobject *mkobj);
+#else /* not CONFIG_SYSFS */
+static inline void __module_kobject_put(struct module_kobject *mkobj) { }
 #endif /* CONFIG_SYSFS */
 
 #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
index b401ff4b02d2..7519920f4f55 100644
--- a/kernel/module/sysfs.c
+++ b/kernel/module/sysfs.c
@@ -323,11 +323,7 @@ static int module_add_modinfo_attrs(struct module *mod)
 
 static void mod_kobject_put(struct module *mod)
 {
-	DECLARE_COMPLETION_ONSTACK(c);
-
-	mod->mkobj.kobj_completion = &c;
-	kobject_put(&mod->mkobj.kobj);
-	wait_for_completion(&c);
+	__module_kobject_put(&mod->mkobj);
 }
 
 static int mod_sysfs_init(struct module *mod)
@@ -362,6 +358,15 @@ static int mod_sysfs_init(struct module *mod)
 	return err;
 }
 
+void __module_kobject_put(struct module_kobject *mkobj)
+{
+	DECLARE_COMPLETION_ONSTACK(c);
+
+	mkobj->kobj_completion = &c;
+	kobject_put(&mkobj->kobj);
+	wait_for_completion(&c);
+}
+
 int mod_sysfs_setup(struct module *mod,
 		    const struct load_info *info,
 			   struct kernel_param *kparam,
diff --git a/kernel/params.c b/kernel/params.c
index e668fc90b83e..2cf1f17840e0 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -780,7 +780,8 @@ struct module_kobject __modinit * lookup_or_create_module_kobject(const char *na
 	if (IS_ENABLED(CONFIG_MODULES) && !err)
 		err = sysfs_create_file(&mk->kobj, &module_uevent.attr);
 	if (err) {
-		kobject_put(&mk->kobj);
+		/* Not 'mod_kobject_put()' because THIS_MODULE may be NULL. */
+		__module_kobject_put(mk);
 		pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n",
 			name, err);
 		return NULL;
-- 
2.49.0





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux