aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorYueHaibing <yuehaibing@huawei.com>2019-06-11 11:00:07 -0400
committerJessica Yu <jeyu@kernel.org>2019-06-14 03:31:09 -0400
commitbc6f2a757d525e001268c3658bd88822e768f8db (patch)
treef09e5ab8d7614581bff9607a8757cd5f58e753e0 /kernel/module.c
parent8d1b73dd25ff92c3fa9807a20c22fa2b44c07336 (diff)
kernel/module: Fix mem leak in module_add_modinfo_attrs
In module_add_modinfo_attrs if sysfs_create_file fails, we forget to free allocated modinfo_attrs and roll back the sysfs files. Fixes: 03e88ae1b13d ("[PATCH] fix module sysfs files reference counting") Reviewed-by: Miroslav Benes <mbenes@suse.cz> Signed-off-by: YueHaibing <yuehaibing@huawei.com> Signed-off-by: Jessica Yu <jeyu@kernel.org>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 1a0d8cab9eb7..c1517053e9d6 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1708,6 +1708,8 @@ static int add_usage_links(struct module *mod)
1708 return ret; 1708 return ret;
1709} 1709}
1710 1710
1711static void module_remove_modinfo_attrs(struct module *mod, int end);
1712
1711static int module_add_modinfo_attrs(struct module *mod) 1713static int module_add_modinfo_attrs(struct module *mod)
1712{ 1714{
1713 struct module_attribute *attr; 1715 struct module_attribute *attr;
@@ -1722,24 +1724,34 @@ static int module_add_modinfo_attrs(struct module *mod)
1722 return -ENOMEM; 1724 return -ENOMEM;
1723 1725
1724 temp_attr = mod->modinfo_attrs; 1726 temp_attr = mod->modinfo_attrs;
1725 for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) { 1727 for (i = 0; (attr = modinfo_attrs[i]); i++) {
1726 if (!attr->test || attr->test(mod)) { 1728 if (!attr->test || attr->test(mod)) {
1727 memcpy(temp_attr, attr, sizeof(*temp_attr)); 1729 memcpy(temp_attr, attr, sizeof(*temp_attr));
1728 sysfs_attr_init(&temp_attr->attr); 1730 sysfs_attr_init(&temp_attr->attr);
1729 error = sysfs_create_file(&mod->mkobj.kobj, 1731 error = sysfs_create_file(&mod->mkobj.kobj,
1730 &temp_attr->attr); 1732 &temp_attr->attr);
1733 if (error)
1734 goto error_out;
1731 ++temp_attr; 1735 ++temp_attr;
1732 } 1736 }
1733 } 1737 }
1738
1739 return 0;
1740
1741error_out:
1742 if (i > 0)
1743 module_remove_modinfo_attrs(mod, --i);
1734 return error; 1744 return error;
1735} 1745}
1736 1746
1737static void module_remove_modinfo_attrs(struct module *mod) 1747static void module_remove_modinfo_attrs(struct module *mod, int end)
1738{ 1748{
1739 struct module_attribute *attr; 1749 struct module_attribute *attr;
1740 int i; 1750 int i;
1741 1751
1742 for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) { 1752 for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {
1753 if (end >= 0 && i > end)
1754 break;
1743 /* pick a field to test for end of list */ 1755 /* pick a field to test for end of list */
1744 if (!attr->attr.name) 1756 if (!attr->attr.name)
1745 break; 1757 break;
@@ -1827,7 +1839,7 @@ static int mod_sysfs_setup(struct module *mod,
1827 return 0; 1839 return 0;
1828 1840
1829out_unreg_modinfo_attrs: 1841out_unreg_modinfo_attrs:
1830 module_remove_modinfo_attrs(mod); 1842 module_remove_modinfo_attrs(mod, -1);
1831out_unreg_param: 1843out_unreg_param:
1832 module_param_sysfs_remove(mod); 1844 module_param_sysfs_remove(mod);
1833out_unreg_holders: 1845out_unreg_holders:
@@ -1863,7 +1875,7 @@ static void mod_sysfs_fini(struct module *mod)
1863{ 1875{
1864} 1876}
1865 1877
1866static void module_remove_modinfo_attrs(struct module *mod) 1878static void module_remove_modinfo_attrs(struct module *mod, int end)
1867{ 1879{
1868} 1880}
1869 1881
@@ -1879,7 +1891,7 @@ static void init_param_lock(struct module *mod)
1879static void mod_sysfs_teardown(struct module *mod) 1891static void mod_sysfs_teardown(struct module *mod)
1880{ 1892{
1881 del_usage_links(mod); 1893 del_usage_links(mod);
1882 module_remove_modinfo_attrs(mod); 1894 module_remove_modinfo_attrs(mod, -1);
1883 module_param_sysfs_remove(mod); 1895 module_param_sysfs_remove(mod);
1884 kobject_put(mod->mkobj.drivers_dir); 1896 kobject_put(mod->mkobj.drivers_dir);
1885 kobject_put(mod->holders_dir); 1897 kobject_put(mod->holders_dir);