mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-23 23:21:46 +00:00
livepatch: add (un)patch callbacks
Provide livepatch modules a klp_object (un)patching notification mechanism. Pre and post-(un)patch callbacks allow livepatch modules to setup or synchronize changes that would be difficult to support in only patched-or-unpatched code contexts. Callbacks can be registered for target module or vmlinux klp_objects, but each implementation is klp_object specific. - Pre-(un)patch callbacks run before any (un)patching transition starts. - Post-(un)patch callbacks run once an object has been (un)patched and the klp_patch fully transitioned to its target state. Example use cases include modification of global data and registration of newly available services/handlers. See Documentation/livepatch/callbacks.txt for details and samples/livepatch/ for examples. Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Acked-by: Miroslav Benes <mbenes@suse.cz> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
19205da6a0
commit
93862e385d
10 changed files with 1091 additions and 13 deletions
|
@ -54,11 +54,6 @@ static bool klp_is_module(struct klp_object *obj)
|
|||
return obj->name;
|
||||
}
|
||||
|
||||
static bool klp_is_object_loaded(struct klp_object *obj)
|
||||
{
|
||||
return !obj->name || obj->mod;
|
||||
}
|
||||
|
||||
/* sets obj->mod if object is not vmlinux and module is found */
|
||||
static void klp_find_object_module(struct klp_object *obj)
|
||||
{
|
||||
|
@ -285,6 +280,8 @@ static int klp_write_object_relocations(struct module *pmod,
|
|||
|
||||
static int __klp_disable_patch(struct klp_patch *patch)
|
||||
{
|
||||
struct klp_object *obj;
|
||||
|
||||
if (klp_transition_patch)
|
||||
return -EBUSY;
|
||||
|
||||
|
@ -295,6 +292,10 @@ static int __klp_disable_patch(struct klp_patch *patch)
|
|||
|
||||
klp_init_transition(patch, KLP_UNPATCHED);
|
||||
|
||||
klp_for_each_object(patch, obj)
|
||||
if (patch->enabled && obj->patched)
|
||||
klp_pre_unpatch_callback(obj);
|
||||
|
||||
/*
|
||||
* Enforce the order of the func->transition writes in
|
||||
* klp_init_transition() and the TIF_PATCH_PENDING writes in
|
||||
|
@ -388,13 +389,18 @@ static int __klp_enable_patch(struct klp_patch *patch)
|
|||
if (!klp_is_object_loaded(obj))
|
||||
continue;
|
||||
|
||||
ret = klp_pre_patch_callback(obj);
|
||||
if (ret) {
|
||||
pr_warn("pre-patch callback failed for object '%s'\n",
|
||||
klp_is_module(obj) ? obj->name : "vmlinux");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = klp_patch_object(obj);
|
||||
if (ret) {
|
||||
pr_warn("failed to enable patch '%s'\n",
|
||||
patch->mod->name);
|
||||
|
||||
klp_cancel_transition();
|
||||
return ret;
|
||||
pr_warn("failed to patch object '%s'\n",
|
||||
klp_is_module(obj) ? obj->name : "vmlinux");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,6 +409,11 @@ static int __klp_enable_patch(struct klp_patch *patch)
|
|||
patch->enabled = true;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
pr_warn("failed to enable patch '%s'\n", patch->mod->name);
|
||||
|
||||
klp_cancel_transition();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -871,13 +882,27 @@ int klp_module_coming(struct module *mod)
|
|||
pr_notice("applying patch '%s' to loading module '%s'\n",
|
||||
patch->mod->name, obj->mod->name);
|
||||
|
||||
ret = klp_pre_patch_callback(obj);
|
||||
if (ret) {
|
||||
pr_warn("pre-patch callback failed for object '%s'\n",
|
||||
obj->name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = klp_patch_object(obj);
|
||||
if (ret) {
|
||||
pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
|
||||
patch->mod->name, obj->mod->name, ret);
|
||||
|
||||
if (patch != klp_transition_patch)
|
||||
klp_post_unpatch_callback(obj);
|
||||
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (patch != klp_transition_patch)
|
||||
klp_post_patch_callback(obj);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -927,9 +952,15 @@ void klp_module_going(struct module *mod)
|
|||
* is in transition.
|
||||
*/
|
||||
if (patch->enabled || patch == klp_transition_patch) {
|
||||
|
||||
if (patch != klp_transition_patch)
|
||||
klp_pre_unpatch_callback(obj);
|
||||
|
||||
pr_notice("reverting patch '%s' on unloading module '%s'\n",
|
||||
patch->mod->name, obj->mod->name);
|
||||
klp_unpatch_object(obj);
|
||||
|
||||
klp_post_unpatch_callback(obj);
|
||||
}
|
||||
|
||||
klp_free_object_loaded(obj);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue