Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

module: Fix freeing of charp module parameters when CONFIG_SYSFS=n

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: e180a6b7759a ("param: fix charp parameters set via sysfs")
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>

authored by

Petr Pavlu and committed by
Sami Tolvanen
deffe1ed 4afc71bb

+23 -19
+3 -8
include/linux/moduleparam.h
··· 426 426 void *arg, parse_unknown_fn unknown); 427 427 428 428 /* Called by module remove. */ 429 - #ifdef CONFIG_SYSFS 430 - extern void destroy_params(const struct kernel_param *params, unsigned num); 431 - #else 432 - static inline void destroy_params(const struct kernel_param *params, 433 - unsigned num) 434 - { 435 - } 436 - #endif /* !CONFIG_SYSFS */ 429 + #ifdef CONFIG_MODULES 430 + void module_destroy_params(const struct kernel_param *params, unsigned int num); 431 + #endif 437 432 438 433 /* All the helper functions */ 439 434 /* The macros to do compile-time type checking stolen from Jakub
+2 -2
kernel/module/main.c
··· 1408 1408 module_unload_free(mod); 1409 1409 1410 1410 /* Free any allocated parameters. */ 1411 - destroy_params(mod->kp, mod->num_kp); 1411 + module_destroy_params(mod->kp, mod->num_kp); 1412 1412 1413 1413 if (is_livepatch_module(mod)) 1414 1414 free_module_elf(mod); ··· 3519 3519 mod_sysfs_teardown(mod); 3520 3520 coming_cleanup: 3521 3521 mod->state = MODULE_STATE_GOING; 3522 - destroy_params(mod->kp, mod->num_kp); 3522 + module_destroy_params(mod->kp, mod->num_kp); 3523 3523 blocking_notifier_call_chain(&module_notify_list, 3524 3524 MODULE_STATE_GOING, mod); 3525 3525 klp_module_going(mod);
+18 -9
kernel/params.c
··· 745 745 } 746 746 #endif 747 747 748 - void destroy_params(const struct kernel_param *params, unsigned num) 749 - { 750 - unsigned int i; 751 - 752 - for (i = 0; i < num; i++) 753 - if (params[i].ops->free) 754 - params[i].ops->free(params[i].arg); 755 - } 756 - 757 748 struct module_kobject * __init_or_module 758 749 lookup_or_create_module_kobject(const char *name) 759 750 { ··· 976 985 late_initcall(param_sysfs_builtin_init); 977 986 978 987 #endif /* CONFIG_SYSFS */ 988 + 989 + #ifdef CONFIG_MODULES 990 + 991 + /* 992 + * module_destroy_params - free all parameters for one module 993 + * @params: module parameters (array) 994 + * @num: number of module parameters 995 + */ 996 + void module_destroy_params(const struct kernel_param *params, unsigned int num) 997 + { 998 + unsigned int i; 999 + 1000 + for (i = 0; i < num; i++) 1001 + if (params[i].ops->free) 1002 + params[i].ops->free(params[i].arg); 1003 + } 1004 + 1005 + #endif /* CONFIG_MODULES */