diff options
author | YueHaibing <yuehaibing@huawei.com> | 2019-06-11 11:00:07 -0400 |
---|---|---|
committer | Jessica Yu <jeyu@kernel.org> | 2019-06-14 03:31:09 -0400 |
commit | bc6f2a757d525e001268c3658bd88822e768f8db (patch) | |
tree | f09e5ab8d7614581bff9607a8757cd5f58e753e0 /kernel/module.c | |
parent | 8d1b73dd25ff92c3fa9807a20c22fa2b44c07336 (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.c | 22 |
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 | ||
1711 | static void module_remove_modinfo_attrs(struct module *mod, int end); | ||
1712 | |||
1711 | static int module_add_modinfo_attrs(struct module *mod) | 1713 | static 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 | |||
1741 | error_out: | ||
1742 | if (i > 0) | ||
1743 | module_remove_modinfo_attrs(mod, --i); | ||
1734 | return error; | 1744 | return error; |
1735 | } | 1745 | } |
1736 | 1746 | ||
1737 | static void module_remove_modinfo_attrs(struct module *mod) | 1747 | static 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 | ||
1829 | out_unreg_modinfo_attrs: | 1841 | out_unreg_modinfo_attrs: |
1830 | module_remove_modinfo_attrs(mod); | 1842 | module_remove_modinfo_attrs(mod, -1); |
1831 | out_unreg_param: | 1843 | out_unreg_param: |
1832 | module_param_sysfs_remove(mod); | 1844 | module_param_sysfs_remove(mod); |
1833 | out_unreg_holders: | 1845 | out_unreg_holders: |
@@ -1863,7 +1875,7 @@ static void mod_sysfs_fini(struct module *mod) | |||
1863 | { | 1875 | { |
1864 | } | 1876 | } |
1865 | 1877 | ||
1866 | static void module_remove_modinfo_attrs(struct module *mod) | 1878 | static 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) | |||
1879 | static void mod_sysfs_teardown(struct module *mod) | 1891 | static 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); |