diff options
Diffstat (limited to 'kernel/livepatch/core.c')
| -rw-r--r-- | kernel/livepatch/core.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 01ca08804f51..3f9f1d6b4c2e 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c | |||
| @@ -89,16 +89,28 @@ static bool klp_is_object_loaded(struct klp_object *obj) | |||
| 89 | /* sets obj->mod if object is not vmlinux and module is found */ | 89 | /* sets obj->mod if object is not vmlinux and module is found */ |
| 90 | static void klp_find_object_module(struct klp_object *obj) | 90 | static void klp_find_object_module(struct klp_object *obj) |
| 91 | { | 91 | { |
| 92 | struct module *mod; | ||
| 93 | |||
| 92 | if (!klp_is_module(obj)) | 94 | if (!klp_is_module(obj)) |
| 93 | return; | 95 | return; |
| 94 | 96 | ||
| 95 | mutex_lock(&module_mutex); | 97 | mutex_lock(&module_mutex); |
| 96 | /* | 98 | /* |
| 97 | * We don't need to take a reference on the module here because we have | 99 | * We do not want to block removal of patched modules and therefore |
| 98 | * the klp_mutex, which is also taken by the module notifier. This | 100 | * we do not take a reference here. The patches are removed by |
| 99 | * prevents any module from unloading until we release the klp_mutex. | 101 | * a going module handler instead. |
| 102 | */ | ||
| 103 | mod = find_module(obj->name); | ||
| 104 | /* | ||
| 105 | * Do not mess work of the module coming and going notifiers. | ||
| 106 | * Note that the patch might still be needed before the going handler | ||
| 107 | * is called. Module functions can be called even in the GOING state | ||
| 108 | * until mod->exit() finishes. This is especially important for | ||
| 109 | * patches that modify semantic of the functions. | ||
| 100 | */ | 110 | */ |
| 101 | obj->mod = find_module(obj->name); | 111 | if (mod && mod->klp_alive) |
| 112 | obj->mod = mod; | ||
| 113 | |||
| 102 | mutex_unlock(&module_mutex); | 114 | mutex_unlock(&module_mutex); |
| 103 | } | 115 | } |
| 104 | 116 | ||
| @@ -767,6 +779,7 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj) | |||
| 767 | return -EINVAL; | 779 | return -EINVAL; |
| 768 | 780 | ||
| 769 | obj->state = KLP_DISABLED; | 781 | obj->state = KLP_DISABLED; |
| 782 | obj->mod = NULL; | ||
| 770 | 783 | ||
| 771 | klp_find_object_module(obj); | 784 | klp_find_object_module(obj); |
| 772 | 785 | ||
| @@ -961,6 +974,15 @@ static int klp_module_notify(struct notifier_block *nb, unsigned long action, | |||
| 961 | 974 | ||
| 962 | mutex_lock(&klp_mutex); | 975 | mutex_lock(&klp_mutex); |
| 963 | 976 | ||
| 977 | /* | ||
| 978 | * Each module has to know that the notifier has been called. | ||
| 979 | * We never know what module will get patched by a new patch. | ||
| 980 | */ | ||
| 981 | if (action == MODULE_STATE_COMING) | ||
| 982 | mod->klp_alive = true; | ||
| 983 | else /* MODULE_STATE_GOING */ | ||
| 984 | mod->klp_alive = false; | ||
| 985 | |||
| 964 | list_for_each_entry(patch, &klp_patches, list) { | 986 | list_for_each_entry(patch, &klp_patches, list) { |
| 965 | for (obj = patch->objs; obj->funcs; obj++) { | 987 | for (obj = patch->objs; obj->funcs; obj++) { |
| 966 | if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) | 988 | if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) |
