mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
module: Fix freeing of charp module parameters when CONFIG_SYSFS=n
[ Upstream commitdeffe1edba] When setting a charp module parameter, the param_set_charp() function allocates memory to store a copy of the input value. Later, when the module is potentially unloaded, the destroy_params() function is called to free this allocated memory. However, destroy_params() is available only when CONFIG_SYSFS=y, otherwise only a dummy variant is present. In the unlikely case that the kernel is configured with CONFIG_MODULES=y and CONFIG_SYSFS=n, this results in a memory leak of charp values when a module is unloaded. Fix this issue by making destroy_params() always available when CONFIG_MODULES=y. Rename the function to module_destroy_params() to clarify that it is intended for use by the module loader. Fixes:e180a6b775("param: fix charp parameters set via sysfs") Signed-off-by: Petr Pavlu <petr.pavlu@suse.com> Signed-off-by: Sami Tolvanen <samitolvanen@google.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
e6962cb18a
commit
231b895daa
@@ -392,14 +392,9 @@ extern char *parse_args(const char *name,
|
||||
const char *doing, void *arg));
|
||||
|
||||
/* Called by module remove. */
|
||||
#ifdef CONFIG_SYSFS
|
||||
extern void destroy_params(const struct kernel_param *params, unsigned num);
|
||||
#else
|
||||
static inline void destroy_params(const struct kernel_param *params,
|
||||
unsigned num)
|
||||
{
|
||||
}
|
||||
#endif /* !CONFIG_SYSFS */
|
||||
#ifdef CONFIG_MODULES
|
||||
void module_destroy_params(const struct kernel_param *params, unsigned int num);
|
||||
#endif
|
||||
|
||||
/* All the helper functions */
|
||||
/* The macros to do compile-time type checking stolen from Jakub
|
||||
|
||||
@@ -1261,7 +1261,7 @@ static void free_module(struct module *mod)
|
||||
module_unload_free(mod);
|
||||
|
||||
/* Free any allocated parameters. */
|
||||
destroy_params(mod->kp, mod->num_kp);
|
||||
module_destroy_params(mod->kp, mod->num_kp);
|
||||
|
||||
if (is_livepatch_module(mod))
|
||||
free_module_elf(mod);
|
||||
@@ -2998,7 +2998,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
|
||||
mod_sysfs_teardown(mod);
|
||||
coming_cleanup:
|
||||
mod->state = MODULE_STATE_GOING;
|
||||
destroy_params(mod->kp, mod->num_kp);
|
||||
module_destroy_params(mod->kp, mod->num_kp);
|
||||
blocking_notifier_call_chain(&module_notify_list,
|
||||
MODULE_STATE_GOING, mod);
|
||||
klp_module_going(mod);
|
||||
|
||||
+18
-9
@@ -744,15 +744,6 @@ void module_param_sysfs_remove(struct module *mod)
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroy_params(const struct kernel_param *params, unsigned num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
if (params[i].ops->free)
|
||||
params[i].ops->free(params[i].arg);
|
||||
}
|
||||
|
||||
struct module_kobject * __init_or_module
|
||||
lookup_or_create_module_kobject(const char *name)
|
||||
{
|
||||
@@ -987,3 +978,21 @@ static int __init param_sysfs_builtin_init(void)
|
||||
late_initcall(param_sysfs_builtin_init);
|
||||
|
||||
#endif /* CONFIG_SYSFS */
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
|
||||
/*
|
||||
* module_destroy_params - free all parameters for one module
|
||||
* @params: module parameters (array)
|
||||
* @num: number of module parameters
|
||||
*/
|
||||
void module_destroy_params(const struct kernel_param *params, unsigned int num)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
if (params[i].ops->free)
|
||||
params[i].ops->free(params[i].arg);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
Reference in New Issue
Block a user