History

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.

Jessica Yu committed 10 years ago

Commit 7e545d61 parent 4c973d13 files · +94 −76Browse files

Unified · Split

3 files
  1. include/linux/livepatch.h +13 −0
  2. kernel/livepatch/core.c +71 −76
  3. kernel/module.c +10 −0
include/linux/livepatch.h+13−0
@@ -24,6 +24,8 @@ · 23 unmodified lines
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
29enum klp_state {31enum klp_state {
@@ -132,4 +134,15 @@ int klp_unregister_patch(struct klp_patch *); · 102 unmodified lines
132int klp_enable_patch(struct klp_patch *);134int klp_enable_patch(struct klp_patch *);
133int klp_disable_patch(struct klp_patch *);135int klp_disable_patch(struct klp_patch *);
134 136
137/* Called from the module loader during module coming/going states */
138int klp_module_coming(struct module *mod);
139void klp_module_going(struct module *mod);
140
141#else /* !CONFIG_LIVEPATCH */
142
143static inline int klp_module_coming(struct module *mod) { return 0; }
144static inline void klp_module_going(struct module *mod) { }
145
146#endif /* CONFIG_LIVEPATCH */
147
135#endif /* _LINUX_LIVEPATCH_H_ */148#endif /* _LINUX_LIVEPATCH_H_ */
kernel/livepatch/core.c+71−76
@@ -99,12 +99,12 @@ static void klp_find_object_module(struct klp_object *obj) · 98 unmodified lines
99 /*99 /*
100 * We do not want to block removal of patched modules and therefore100 * We do not want to block removal of patched modules and therefore
101 * we do not take a reference here. The patches are removed by101 * 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 handler107 * Note that the patch might still be needed before klp_module_going()
108 * is called. Module functions can be called even in the GOING state108 * is called. Module functions can be called even in the GOING state
109 * until mod->exit() finishes. This is especially important for109 * 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) · 755 unmodified lines
866}866}
867EXPORT_SYMBOL_GPL(klp_register_patch);867EXPORT_SYMBOL_GPL(klp_register_patch);
868 868
869static int klp_module_notify_coming(struct klp_patch *patch,869int 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
896static 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
910disabled:921err:
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
914static int klp_module_notify(struct notifier_block *nb, unsigned long action,935void 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
961static 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
966static int __init klp_init(void)971static int __init klp_init(void)
967{972{
968 int ret;973 int ret;
@@ -973,21 +978,11 @@ static int __init klp_init(void) · 4 unmodified lines
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
988unregister:
989 unregister_module_notifier(&klp_module_nb);
990 return ret;
991}986}
992 987
993module_init(klp_init);988module_init(klp_init);
kernel/module.c+10−0
@@ -53,6 +53,7 @@ · 52 unmodified lines
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, · 925 unmodified lines
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: · 2325 unmodified lines
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: · 80 unmodified lines
3401 3404
3402static int prepare_coming_module(struct module *mod)3405static 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, · 145 unmodified lines
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 */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t