diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/kernel/module.c b/kernel/module.c index ae79ce615cb9..88cec1ddb1e3 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -135,7 +135,7 @@ static int param_set_bool_enable_only(const char *val, | |||
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static const struct kernel_param_ops param_ops_bool_enable_only = { | 137 | static const struct kernel_param_ops param_ops_bool_enable_only = { |
| 138 | .flags = KERNEL_PARAM_FL_NOARG, | 138 | .flags = KERNEL_PARAM_OPS_FL_NOARG, |
| 139 | .set = param_set_bool_enable_only, | 139 | .set = param_set_bool_enable_only, |
| 140 | .get = param_get_bool, | 140 | .get = param_get_bool, |
| 141 | }; | 141 | }; |
| @@ -1842,7 +1842,9 @@ static void free_module(struct module *mod) | |||
| 1842 | 1842 | ||
| 1843 | /* We leave it in list to prevent duplicate loads, but make sure | 1843 | /* We leave it in list to prevent duplicate loads, but make sure |
| 1844 | * that noone uses it while it's being deconstructed. */ | 1844 | * that noone uses it while it's being deconstructed. */ |
| 1845 | mutex_lock(&module_mutex); | ||
| 1845 | mod->state = MODULE_STATE_UNFORMED; | 1846 | mod->state = MODULE_STATE_UNFORMED; |
| 1847 | mutex_unlock(&module_mutex); | ||
| 1846 | 1848 | ||
| 1847 | /* Remove dynamic debug info */ | 1849 | /* Remove dynamic debug info */ |
| 1848 | ddebug_remove_module(mod->name); | 1850 | ddebug_remove_module(mod->name); |
| @@ -3304,6 +3306,11 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3304 | mutex_lock(&module_mutex); | 3306 | mutex_lock(&module_mutex); |
| 3305 | module_bug_cleanup(mod); | 3307 | module_bug_cleanup(mod); |
| 3306 | mutex_unlock(&module_mutex); | 3308 | mutex_unlock(&module_mutex); |
| 3309 | |||
| 3310 | /* we can't deallocate the module until we clear memory protection */ | ||
| 3311 | unset_module_init_ro_nx(mod); | ||
| 3312 | unset_module_core_ro_nx(mod); | ||
| 3313 | |||
| 3307 | ddebug_cleanup: | 3314 | ddebug_cleanup: |
| 3308 | dynamic_debug_remove(info->debug); | 3315 | dynamic_debug_remove(info->debug); |
| 3309 | synchronize_sched(); | 3316 | synchronize_sched(); |
| @@ -3381,7 +3388,9 @@ static inline int within(unsigned long addr, void *start, unsigned long size) | |||
| 3381 | */ | 3388 | */ |
| 3382 | static inline int is_arm_mapping_symbol(const char *str) | 3389 | static inline int is_arm_mapping_symbol(const char *str) |
| 3383 | { | 3390 | { |
| 3384 | return str[0] == '$' && strchr("atd", str[1]) | 3391 | if (str[0] == '.' && str[1] == 'L') |
| 3392 | return true; | ||
| 3393 | return str[0] == '$' && strchr("axtd", str[1]) | ||
| 3385 | && (str[2] == '\0' || str[2] == '.'); | 3394 | && (str[2] == '\0' || str[2] == '.'); |
| 3386 | } | 3395 | } |
| 3387 | 3396 | ||
| @@ -3444,8 +3453,7 @@ const char *module_address_lookup(unsigned long addr, | |||
| 3444 | list_for_each_entry_rcu(mod, &modules, list) { | 3453 | list_for_each_entry_rcu(mod, &modules, list) { |
| 3445 | if (mod->state == MODULE_STATE_UNFORMED) | 3454 | if (mod->state == MODULE_STATE_UNFORMED) |
| 3446 | continue; | 3455 | continue; |
| 3447 | if (within_module_init(addr, mod) || | 3456 | if (within_module(addr, mod)) { |
| 3448 | within_module_core(addr, mod)) { | ||
| 3449 | if (modname) | 3457 | if (modname) |
| 3450 | *modname = mod->name; | 3458 | *modname = mod->name; |
| 3451 | ret = get_ksymbol(mod, addr, size, offset); | 3459 | ret = get_ksymbol(mod, addr, size, offset); |
| @@ -3469,8 +3477,7 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) | |||
| 3469 | list_for_each_entry_rcu(mod, &modules, list) { | 3477 | list_for_each_entry_rcu(mod, &modules, list) { |
| 3470 | if (mod->state == MODULE_STATE_UNFORMED) | 3478 | if (mod->state == MODULE_STATE_UNFORMED) |
| 3471 | continue; | 3479 | continue; |
| 3472 | if (within_module_init(addr, mod) || | 3480 | if (within_module(addr, mod)) { |
| 3473 | within_module_core(addr, mod)) { | ||
| 3474 | const char *sym; | 3481 | const char *sym; |
| 3475 | 3482 | ||
| 3476 | sym = get_ksymbol(mod, addr, NULL, NULL); | 3483 | sym = get_ksymbol(mod, addr, NULL, NULL); |
| @@ -3495,8 +3502,7 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
| 3495 | list_for_each_entry_rcu(mod, &modules, list) { | 3502 | list_for_each_entry_rcu(mod, &modules, list) { |
| 3496 | if (mod->state == MODULE_STATE_UNFORMED) | 3503 | if (mod->state == MODULE_STATE_UNFORMED) |
| 3497 | continue; | 3504 | continue; |
| 3498 | if (within_module_init(addr, mod) || | 3505 | if (within_module(addr, mod)) { |
| 3499 | within_module_core(addr, mod)) { | ||
| 3500 | const char *sym; | 3506 | const char *sym; |
| 3501 | 3507 | ||
| 3502 | sym = get_ksymbol(mod, addr, size, offset); | 3508 | sym = get_ksymbol(mod, addr, size, offset); |
| @@ -3760,8 +3766,7 @@ struct module *__module_address(unsigned long addr) | |||
| 3760 | list_for_each_entry_rcu(mod, &modules, list) { | 3766 | list_for_each_entry_rcu(mod, &modules, list) { |
| 3761 | if (mod->state == MODULE_STATE_UNFORMED) | 3767 | if (mod->state == MODULE_STATE_UNFORMED) |
| 3762 | continue; | 3768 | continue; |
| 3763 | if (within_module_core(addr, mod) | 3769 | if (within_module(addr, mod)) |
| 3764 | || within_module_init(addr, mod)) | ||
| 3765 | return mod; | 3770 | return mod; |
| 3766 | } | 3771 | } |
| 3767 | return NULL; | 3772 | return NULL; |
