Skip to content

Commit 231b895

Browse files
petrpavlugregkh
authored andcommitted
module: Fix freeing of charp module parameters when CONFIG_SYSFS=n
[ Upstream commit deffe1e ] 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: e180a6b ("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>
1 parent e6962cb commit 231b895

3 files changed

Lines changed: 23 additions & 19 deletions

File tree

include/linux/moduleparam.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -392,14 +392,9 @@ extern char *parse_args(const char *name,
392392
const char *doing, void *arg));
393393

394394
/* Called by module remove. */
395-
#ifdef CONFIG_SYSFS
396-
extern void destroy_params(const struct kernel_param *params, unsigned num);
397-
#else
398-
static inline void destroy_params(const struct kernel_param *params,
399-
unsigned num)
400-
{
401-
}
402-
#endif /* !CONFIG_SYSFS */
395+
#ifdef CONFIG_MODULES
396+
void module_destroy_params(const struct kernel_param *params, unsigned int num);
397+
#endif
403398

404399
/* All the helper functions */
405400
/* The macros to do compile-time type checking stolen from Jakub

kernel/module/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,7 @@ static void free_module(struct module *mod)
12611261
module_unload_free(mod);
12621262

12631263
/* Free any allocated parameters. */
1264-
destroy_params(mod->kp, mod->num_kp);
1264+
module_destroy_params(mod->kp, mod->num_kp);
12651265

12661266
if (is_livepatch_module(mod))
12671267
free_module_elf(mod);
@@ -2998,7 +2998,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
29982998
mod_sysfs_teardown(mod);
29992999
coming_cleanup:
30003000
mod->state = MODULE_STATE_GOING;
3001-
destroy_params(mod->kp, mod->num_kp);
3001+
module_destroy_params(mod->kp, mod->num_kp);
30023002
blocking_notifier_call_chain(&module_notify_list,
30033003
MODULE_STATE_GOING, mod);
30043004
klp_module_going(mod);

kernel/params.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -744,15 +744,6 @@ void module_param_sysfs_remove(struct module *mod)
744744
}
745745
#endif
746746

747-
void destroy_params(const struct kernel_param *params, unsigned num)
748-
{
749-
unsigned int i;
750-
751-
for (i = 0; i < num; i++)
752-
if (params[i].ops->free)
753-
params[i].ops->free(params[i].arg);
754-
}
755-
756747
struct module_kobject * __init_or_module
757748
lookup_or_create_module_kobject(const char *name)
758749
{
@@ -987,3 +978,21 @@ static int __init param_sysfs_builtin_init(void)
987978
late_initcall(param_sysfs_builtin_init);
988979

989980
#endif /* CONFIG_SYSFS */
981+
982+
#ifdef CONFIG_MODULES
983+
984+
/*
985+
* module_destroy_params - free all parameters for one module
986+
* @params: module parameters (array)
987+
* @num: number of module parameters
988+
*/
989+
void module_destroy_params(const struct kernel_param *params, unsigned int num)
990+
{
991+
unsigned int i;
992+
993+
for (i = 0; i < num; i++)
994+
if (params[i].ops->free)
995+
params[i].ops->free(params[i].arg);
996+
}
997+
998+
#endif /* CONFIG_MODULES */

0 commit comments

Comments
 (0)