diff options
author | Jessica Yu <jeyu@redhat.com> | 2016-03-16 20:55:39 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2016-03-17 04:45:10 -0400 |
commit | 7e545d6eca20ce8ef7f66a63146cbff82b2ba760 (patch) | |
tree | f8c4366009b357842b8b17b3bfddbfc3b634ff40 | |
parent | 4c973d1620ae08f5cbe27644c5f5b974c8f594ec (diff) |
livepatch/module: remove livepatch module notifier
Remove the livepatch module notifier in favor of directly enabling and
disabling patches to modules in the module loader. Hard-coding the
function calls ensures that ftrace_module_enable() is run before
klp_module_coming() during module load, and that klp_module_going() is
run before ftrace_release_mod() during module unload. This way, ftrace
and livepatch code is run in the correct order during the module
load/unload sequence without dependence on the module notifier call chain.
Signed-off-by: Jessica Yu <jeyu@redhat.com>
Reviewed-by: Petr Mladek <pmladek@suse.cz>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Acked-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | include/linux/livepatch.h | 13 | ||||
-rw-r--r-- | kernel/livepatch/core.c | 147 | ||||
-rw-r--r-- | kernel/module.c | 10 |
3 files changed, 94 insertions, 76 deletions
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h index c05679701e10..bd830d590465 100644 --- a/include/linux/livepatch.h +++ b/include/linux/livepatch.h | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/ftrace.h> | 25 | #include <linux/ftrace.h> |
26 | 26 | ||
27 | #if IS_ENABLED(CONFIG_LIVEPATCH) | ||
28 | |||
27 | #include <asm/livepatch.h> | 29 | #include <asm/livepatch.h> |
28 | 30 | ||
29 | enum klp_state { | 31 | enum klp_state { |
@@ -132,4 +134,15 @@ int klp_unregister_patch(struct klp_patch *); | |||
132 | int klp_enable_patch(struct klp_patch *); | 134 | int klp_enable_patch(struct klp_patch *); |
133 | int klp_disable_patch(struct klp_patch *); | 135 | int klp_disable_patch(struct klp_patch *); |
134 | 136 | ||
137 | /* Called from the module loader during module coming/going states */ | ||
138 | int klp_module_coming(struct module *mod); | ||
139 | void klp_module_going(struct module *mod); | ||
140 | |||
141 | #else /* !CONFIG_LIVEPATCH */ | ||
142 | |||
143 | static inline int klp_module_coming(struct module *mod) { return 0; } | ||
144 | static inline void klp_module_going(struct module *mod) { } | ||
145 | |||
146 | #endif /* CONFIG_LIVEPATCH */ | ||
147 | |||
135 | #endif /* _LINUX_LIVEPATCH_H_ */ | 148 | #endif /* _LINUX_LIVEPATCH_H_ */ |
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 780f00cdb7e5..d68fbf63b083 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c | |||
@@ -99,12 +99,12 @@ static void klp_find_object_module(struct klp_object *obj) | |||
99 | /* | 99 | /* |
100 | * We do not want to block removal of patched modules and therefore | 100 | * We do not want to block removal of patched modules and therefore |
101 | * we do not take a reference here. The patches are removed by | 101 | * we do not take a reference here. The patches are removed by |
102 | * a going module handler instead. | 102 | * klp_module_going() instead. |
103 | */ | 103 | */ |
104 | mod = find_module(obj->name); | 104 | mod = find_module(obj->name); |
105 | /* | 105 | /* |
106 | * Do not mess work of the module coming and going notifiers. | 106 | * Do not mess work of klp_module_coming() and klp_module_going(). |
107 | * Note that the patch might still be needed before the going handler | 107 | * Note that the patch might still be needed before klp_module_going() |
108 | * is called. Module functions can be called even in the GOING state | 108 | * is called. Module functions can be called even in the GOING state |
109 | * until mod->exit() finishes. This is especially important for | 109 | * until mod->exit() finishes. This is especially important for |
110 | * patches that modify semantic of the functions. | 110 | * patches that modify semantic of the functions. |
@@ -866,103 +866,108 @@ int klp_register_patch(struct klp_patch *patch) | |||
866 | } | 866 | } |
867 | EXPORT_SYMBOL_GPL(klp_register_patch); | 867 | EXPORT_SYMBOL_GPL(klp_register_patch); |
868 | 868 | ||
869 | static int klp_module_notify_coming(struct klp_patch *patch, | 869 | int klp_module_coming(struct module *mod) |
870 | struct klp_object *obj) | ||
871 | { | 870 | { |
872 | struct module *pmod = patch->mod; | ||
873 | struct module *mod = obj->mod; | ||
874 | int ret; | 871 | int ret; |
872 | struct klp_patch *patch; | ||
873 | struct klp_object *obj; | ||
875 | 874 | ||
876 | ret = klp_init_object_loaded(patch, obj); | 875 | if (WARN_ON(mod->state != MODULE_STATE_COMING)) |
877 | if (ret) { | 876 | return -EINVAL; |
878 | pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n", | ||
879 | pmod->name, mod->name, ret); | ||
880 | return ret; | ||
881 | } | ||
882 | 877 | ||
883 | if (patch->state == KLP_DISABLED) | 878 | mutex_lock(&klp_mutex); |
884 | return 0; | 879 | /* |
880 | * Each module has to know that klp_module_coming() | ||
881 | * has been called. We never know what module will | ||
882 | * get patched by a new patch. | ||
883 | */ | ||
884 | mod->klp_alive = true; | ||
885 | 885 | ||
886 | pr_notice("applying patch '%s' to loading module '%s'\n", | 886 | list_for_each_entry(patch, &klp_patches, list) { |
887 | pmod->name, mod->name); | 887 | klp_for_each_object(patch, obj) { |
888 | if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) | ||
889 | continue; | ||
888 | 890 | ||
889 | ret = klp_enable_object(obj); | 891 | obj->mod = mod; |
890 | if (ret) | ||
891 | pr_warn("failed to apply patch '%s' to module '%s' (%d)\n", | ||
892 | pmod->name, mod->name, ret); | ||
893 | return ret; | ||
894 | } | ||
895 | 892 | ||
896 | static void klp_module_notify_going(struct klp_patch *patch, | 893 | ret = klp_init_object_loaded(patch, obj); |
897 | struct klp_object *obj) | 894 | if (ret) { |
898 | { | 895 | pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n", |
899 | struct module *pmod = patch->mod; | 896 | patch->mod->name, obj->mod->name, ret); |
900 | struct module *mod = obj->mod; | 897 | goto err; |
898 | } | ||
901 | 899 | ||
902 | if (patch->state == KLP_DISABLED) | 900 | if (patch->state == KLP_DISABLED) |
903 | goto disabled; | 901 | break; |
902 | |||
903 | pr_notice("applying patch '%s' to loading module '%s'\n", | ||
904 | patch->mod->name, obj->mod->name); | ||
905 | |||
906 | ret = klp_enable_object(obj); | ||
907 | if (ret) { | ||
908 | pr_warn("failed to apply patch '%s' to module '%s' (%d)\n", | ||
909 | patch->mod->name, obj->mod->name, ret); | ||
910 | goto err; | ||
911 | } | ||
912 | |||
913 | break; | ||
914 | } | ||
915 | } | ||
904 | 916 | ||
905 | pr_notice("reverting patch '%s' on unloading module '%s'\n", | 917 | mutex_unlock(&klp_mutex); |
906 | pmod->name, mod->name); | ||
907 | 918 | ||
908 | klp_disable_object(obj); | 919 | return 0; |
909 | 920 | ||
910 | disabled: | 921 | err: |
922 | /* | ||
923 | * If a patch is unsuccessfully applied, return | ||
924 | * error to the module loader. | ||
925 | */ | ||
926 | pr_warn("patch '%s' failed for module '%s', refusing to load module '%s'\n", | ||
927 | patch->mod->name, obj->mod->name, obj->mod->name); | ||
928 | mod->klp_alive = false; | ||
911 | klp_free_object_loaded(obj); | 929 | klp_free_object_loaded(obj); |
930 | mutex_unlock(&klp_mutex); | ||
931 | |||
932 | return ret; | ||
912 | } | 933 | } |
913 | 934 | ||
914 | static int klp_module_notify(struct notifier_block *nb, unsigned long action, | 935 | void klp_module_going(struct module *mod) |
915 | void *data) | ||
916 | { | 936 | { |
917 | int ret; | ||
918 | struct module *mod = data; | ||
919 | struct klp_patch *patch; | 937 | struct klp_patch *patch; |
920 | struct klp_object *obj; | 938 | struct klp_object *obj; |
921 | 939 | ||
922 | if (action != MODULE_STATE_COMING && action != MODULE_STATE_GOING) | 940 | if (WARN_ON(mod->state != MODULE_STATE_GOING && |
923 | return 0; | 941 | mod->state != MODULE_STATE_COMING)) |
942 | return; | ||
924 | 943 | ||
925 | mutex_lock(&klp_mutex); | 944 | mutex_lock(&klp_mutex); |
926 | |||
927 | /* | 945 | /* |
928 | * Each module has to know that the notifier has been called. | 946 | * Each module has to know that klp_module_going() |
929 | * We never know what module will get patched by a new patch. | 947 | * has been called. We never know what module will |
948 | * get patched by a new patch. | ||
930 | */ | 949 | */ |
931 | if (action == MODULE_STATE_COMING) | 950 | mod->klp_alive = false; |
932 | mod->klp_alive = true; | ||
933 | else /* MODULE_STATE_GOING */ | ||
934 | mod->klp_alive = false; | ||
935 | 951 | ||
936 | list_for_each_entry(patch, &klp_patches, list) { | 952 | list_for_each_entry(patch, &klp_patches, list) { |
937 | klp_for_each_object(patch, obj) { | 953 | klp_for_each_object(patch, obj) { |
938 | if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) | 954 | if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) |
939 | continue; | 955 | continue; |
940 | 956 | ||
941 | if (action == MODULE_STATE_COMING) { | 957 | if (patch->state != KLP_DISABLED) { |
942 | obj->mod = mod; | 958 | pr_notice("reverting patch '%s' on unloading module '%s'\n", |
943 | ret = klp_module_notify_coming(patch, obj); | 959 | patch->mod->name, obj->mod->name); |
944 | if (ret) { | 960 | klp_disable_object(obj); |
945 | obj->mod = NULL; | 961 | } |
946 | pr_warn("patch '%s' is in an inconsistent state!\n", | ||
947 | patch->mod->name); | ||
948 | } | ||
949 | } else /* MODULE_STATE_GOING */ | ||
950 | klp_module_notify_going(patch, obj); | ||
951 | 962 | ||
963 | klp_free_object_loaded(obj); | ||
952 | break; | 964 | break; |
953 | } | 965 | } |
954 | } | 966 | } |
955 | 967 | ||
956 | mutex_unlock(&klp_mutex); | 968 | mutex_unlock(&klp_mutex); |
957 | |||
958 | return 0; | ||
959 | } | 969 | } |
960 | 970 | ||
961 | static struct notifier_block klp_module_nb = { | ||
962 | .notifier_call = klp_module_notify, | ||
963 | .priority = INT_MIN+1, /* called late but before ftrace notifier */ | ||
964 | }; | ||
965 | |||
966 | static int __init klp_init(void) | 971 | static int __init klp_init(void) |
967 | { | 972 | { |
968 | int ret; | 973 | int ret; |
@@ -973,21 +978,11 @@ static int __init klp_init(void) | |||
973 | return -EINVAL; | 978 | return -EINVAL; |
974 | } | 979 | } |
975 | 980 | ||
976 | ret = register_module_notifier(&klp_module_nb); | ||
977 | if (ret) | ||
978 | return ret; | ||
979 | |||
980 | klp_root_kobj = kobject_create_and_add("livepatch", kernel_kobj); | 981 | klp_root_kobj = kobject_create_and_add("livepatch", kernel_kobj); |
981 | if (!klp_root_kobj) { | 982 | if (!klp_root_kobj) |
982 | ret = -ENOMEM; | 983 | return -ENOMEM; |
983 | goto unregister; | ||
984 | } | ||
985 | 984 | ||
986 | return 0; | 985 | return 0; |
987 | |||
988 | unregister: | ||
989 | unregister_module_notifier(&klp_module_nb); | ||
990 | return ret; | ||
991 | } | 986 | } |
992 | 987 | ||
993 | module_init(klp_init); | 988 | module_init(klp_init); |
diff --git a/kernel/module.c b/kernel/module.c index 6dbfad415d51..4b65fbb10bdc 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(); |
@@ -3315,6 +3317,7 @@ fail: | |||
3315 | module_put(mod); | 3317 | module_put(mod); |
3316 | blocking_notifier_call_chain(&module_notify_list, | 3318 | blocking_notifier_call_chain(&module_notify_list, |
3317 | MODULE_STATE_GOING, mod); | 3319 | MODULE_STATE_GOING, mod); |
3320 | klp_module_going(mod); | ||
3318 | ftrace_release_mod(mod); | 3321 | ftrace_release_mod(mod); |
3319 | free_module(mod); | 3322 | free_module(mod); |
3320 | wake_up_all(&module_wq); | 3323 | wake_up_all(&module_wq); |
@@ -3401,7 +3404,13 @@ out: | |||
3401 | 3404 | ||
3402 | static int prepare_coming_module(struct module *mod) | 3405 | static int prepare_coming_module(struct module *mod) |
3403 | { | 3406 | { |
3407 | int err; | ||
3408 | |||
3404 | ftrace_module_enable(mod); | 3409 | ftrace_module_enable(mod); |
3410 | err = klp_module_coming(mod); | ||
3411 | if (err) | ||
3412 | return err; | ||
3413 | |||
3405 | blocking_notifier_call_chain(&module_notify_list, | 3414 | blocking_notifier_call_chain(&module_notify_list, |
3406 | MODULE_STATE_COMING, mod); | 3415 | MODULE_STATE_COMING, mod); |
3407 | return 0; | 3416 | return 0; |
@@ -3553,6 +3562,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3553 | coming_cleanup: | 3562 | coming_cleanup: |
3554 | blocking_notifier_call_chain(&module_notify_list, | 3563 | blocking_notifier_call_chain(&module_notify_list, |
3555 | MODULE_STATE_GOING, mod); | 3564 | MODULE_STATE_GOING, mod); |
3565 | klp_module_going(mod); | ||
3556 | 3566 | ||
3557 | bug_cleanup: | 3567 | bug_cleanup: |
3558 | /* module_bug_cleanup needs module_mutex protection */ | 3568 | /* module_bug_cleanup needs module_mutex protection */ |