diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/kernel/module.c b/kernel/module.c index 87cfeb25cf65..041200ca4a2d 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <asm/sections.h> | 53 | #include <asm/sections.h> |
54 | #include <linux/tracepoint.h> | 54 | #include <linux/tracepoint.h> |
55 | #include <linux/ftrace.h> | 55 | #include <linux/ftrace.h> |
56 | #include <linux/livepatch.h> | ||
56 | #include <linux/async.h> | 57 | #include <linux/async.h> |
57 | #include <linux/percpu.h> | 58 | #include <linux/percpu.h> |
58 | #include <linux/kmemleak.h> | 59 | #include <linux/kmemleak.h> |
@@ -984,6 +985,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, | |||
984 | mod->exit(); | 985 | mod->exit(); |
985 | blocking_notifier_call_chain(&module_notify_list, | 986 | blocking_notifier_call_chain(&module_notify_list, |
986 | MODULE_STATE_GOING, mod); | 987 | MODULE_STATE_GOING, mod); |
988 | klp_module_going(mod); | ||
987 | ftrace_release_mod(mod); | 989 | ftrace_release_mod(mod); |
988 | 990 | ||
989 | async_synchronize_full(); | 991 | async_synchronize_full(); |
@@ -3258,6 +3260,7 @@ fail: | |||
3258 | module_put(mod); | 3260 | module_put(mod); |
3259 | blocking_notifier_call_chain(&module_notify_list, | 3261 | blocking_notifier_call_chain(&module_notify_list, |
3260 | MODULE_STATE_GOING, mod); | 3262 | MODULE_STATE_GOING, mod); |
3263 | klp_module_going(mod); | ||
3261 | ftrace_release_mod(mod); | 3264 | ftrace_release_mod(mod); |
3262 | free_module(mod); | 3265 | free_module(mod); |
3263 | wake_up_all(&module_wq); | 3266 | wake_up_all(&module_wq); |
@@ -3335,9 +3338,6 @@ static int complete_formation(struct module *mod, struct load_info *info) | |||
3335 | mod->state = MODULE_STATE_COMING; | 3338 | mod->state = MODULE_STATE_COMING; |
3336 | mutex_unlock(&module_mutex); | 3339 | mutex_unlock(&module_mutex); |
3337 | 3340 | ||
3338 | ftrace_module_enable(mod); | ||
3339 | blocking_notifier_call_chain(&module_notify_list, | ||
3340 | MODULE_STATE_COMING, mod); | ||
3341 | return 0; | 3341 | return 0; |
3342 | 3342 | ||
3343 | out: | 3343 | out: |
@@ -3345,6 +3345,20 @@ out: | |||
3345 | return err; | 3345 | return err; |
3346 | } | 3346 | } |
3347 | 3347 | ||
3348 | static int prepare_coming_module(struct module *mod) | ||
3349 | { | ||
3350 | int err; | ||
3351 | |||
3352 | ftrace_module_enable(mod); | ||
3353 | err = klp_module_coming(mod); | ||
3354 | if (err) | ||
3355 | return err; | ||
3356 | |||
3357 | blocking_notifier_call_chain(&module_notify_list, | ||
3358 | MODULE_STATE_COMING, mod); | ||
3359 | return 0; | ||
3360 | } | ||
3361 | |||
3348 | static int unknown_module_param_cb(char *param, char *val, const char *modname, | 3362 | static int unknown_module_param_cb(char *param, char *val, const char *modname, |
3349 | void *arg) | 3363 | void *arg) |
3350 | { | 3364 | { |
@@ -3459,13 +3473,17 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3459 | if (err) | 3473 | if (err) |
3460 | goto ddebug_cleanup; | 3474 | goto ddebug_cleanup; |
3461 | 3475 | ||
3476 | err = prepare_coming_module(mod); | ||
3477 | if (err) | ||
3478 | goto bug_cleanup; | ||
3479 | |||
3462 | /* Module is ready to execute: parsing args may do that. */ | 3480 | /* Module is ready to execute: parsing args may do that. */ |
3463 | after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, | 3481 | after_dashes = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, |
3464 | -32768, 32767, mod, | 3482 | -32768, 32767, mod, |
3465 | unknown_module_param_cb); | 3483 | unknown_module_param_cb); |
3466 | if (IS_ERR(after_dashes)) { | 3484 | if (IS_ERR(after_dashes)) { |
3467 | err = PTR_ERR(after_dashes); | 3485 | err = PTR_ERR(after_dashes); |
3468 | goto bug_cleanup; | 3486 | goto coming_cleanup; |
3469 | } else if (after_dashes) { | 3487 | } else if (after_dashes) { |
3470 | pr_warn("%s: parameters '%s' after `--' ignored\n", | 3488 | pr_warn("%s: parameters '%s' after `--' ignored\n", |
3471 | mod->name, after_dashes); | 3489 | mod->name, after_dashes); |
@@ -3474,7 +3492,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3474 | /* Link in to syfs. */ | 3492 | /* Link in to syfs. */ |
3475 | err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); | 3493 | err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); |
3476 | if (err < 0) | 3494 | if (err < 0) |
3477 | goto bug_cleanup; | 3495 | goto coming_cleanup; |
3478 | 3496 | ||
3479 | /* Get rid of temporary copy. */ | 3497 | /* Get rid of temporary copy. */ |
3480 | free_copy(info); | 3498 | free_copy(info); |
@@ -3484,15 +3502,17 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3484 | 3502 | ||
3485 | return do_init_module(mod); | 3503 | return do_init_module(mod); |
3486 | 3504 | ||
3505 | coming_cleanup: | ||
3506 | blocking_notifier_call_chain(&module_notify_list, | ||
3507 | MODULE_STATE_GOING, mod); | ||
3508 | klp_module_going(mod); | ||
3509 | |||
3487 | bug_cleanup: | 3510 | bug_cleanup: |
3488 | /* module_bug_cleanup needs module_mutex protection */ | 3511 | /* module_bug_cleanup needs module_mutex protection */ |
3489 | mutex_lock(&module_mutex); | 3512 | mutex_lock(&module_mutex); |
3490 | module_bug_cleanup(mod); | 3513 | module_bug_cleanup(mod); |
3491 | mutex_unlock(&module_mutex); | 3514 | mutex_unlock(&module_mutex); |
3492 | 3515 | ||
3493 | blocking_notifier_call_chain(&module_notify_list, | ||
3494 | MODULE_STATE_GOING, mod); | ||
3495 | |||
3496 | /* we can't deallocate the module until we clear memory protection */ | 3516 | /* we can't deallocate the module until we clear memory protection */ |
3497 | module_disable_ro(mod); | 3517 | module_disable_ro(mod); |
3498 | module_disable_nx(mod); | 3518 | module_disable_nx(mod); |