aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/include/linux/livepatch.h
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2019-01-09 13:43:23 +0100
committerJiri Kosina <jkosina@suse.cz>2019-01-11 20:51:24 +0100
commit958ef1e39d24d6cb8bf2a7406130a98c9564230f (patch)
tree07694df3fe9ac15dbfc1130ed5151f85f0d6a87c /include/linux/livepatch.h
parentlivepatch: Don't block the removal of patches loaded after a forced transition (diff)
downloadwireguard-linux-958ef1e39d24d6cb8bf2a7406130a98c9564230f.tar.xz
wireguard-linux-958ef1e39d24d6cb8bf2a7406130a98c9564230f.zip
livepatch: Simplify API by removing registration step
The possibility to re-enable a registered patch was useful for immediate patches where the livepatch module had to stay until the system reboot. The improved consistency model allows to achieve the same result by unloading and loading the livepatch module again. Also we are going to add a feature called atomic replace. It will allow to create a patch that would replace all already registered patches. The aim is to handle dependent patches more securely. It will obsolete the stack of patches that helped to handle the dependencies so far. Then it might be unclear when a cumulative patch re-enabling is safe. It would be complicated to support the many modes. Instead we could actually make the API and code easier to understand. Therefore, remove the two step public API. All the checks and init calls are moved from klp_register_patch() to klp_enabled_patch(). Also the patch is automatically freed, including the sysfs interface when the transition to the disabled state is completed. As a result, there is never a disabled patch on the top of the stack. Therefore we do not need to check the stack in __klp_enable_patch(). And we could simplify the check in __klp_disable_patch(). Also the API and logic is much easier. It is enough to call klp_enable_patch() in module_init() call. The patch can be disabled by writing '0' into /sys/kernel/livepatch/<patch>/enabled. Then the module can be removed once the transition finishes and sysfs interface is freed. The only problem is how to free the structures and kobjects safely. The operation is triggered from the sysfs interface. We could not put the related kobject from there because it would cause lock inversion between klp_mutex and kernfs locks, see kn->count lockdep map. Therefore, offload the free task to a workqueue. It is perfectly fine: + The patch can no longer be used in the livepatch operations. + The module could not be removed until the free operation finishes and module_put() is called. + The operation is asynchronous already when the first klp_try_complete_transition() fails and another call is queued with a delay. Suggested-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Petr Mladek <pmladek@suse.com> Acked-by: Miroslav Benes <mbenes@suse.cz> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'include/linux/livepatch.h')
-rw-r--r--include/linux/livepatch.h7
1 files changed, 3 insertions, 4 deletions
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 6a9165d9b090..8f9c19c69744 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -139,11 +139,12 @@ struct klp_object {
* struct klp_patch - patch structure for live patching
* @mod: reference to the live patch module
* @objs: object entries for kernel objects to be patched
- * @list: list node for global list of registered patches
+ * @list: list node for global list of actively used patches
* @kobj: kobject for sysfs resources
* @kobj_added: @kobj has been added and needs freeing
* @enabled: the patch is enabled (but operation may be incomplete)
* @forced: was involved in a forced transition
+ * @free_work: patch cleanup from workqueue-context
* @finish: for waiting till it is safe to remove the patch module
*/
struct klp_patch {
@@ -157,6 +158,7 @@ struct klp_patch {
bool kobj_added;
bool enabled;
bool forced;
+ struct work_struct free_work;
struct completion finish;
};
@@ -168,10 +170,7 @@ struct klp_patch {
func->old_name || func->new_func || func->old_sympos; \
func++)
-int klp_register_patch(struct klp_patch *);
-int klp_unregister_patch(struct klp_patch *);
int klp_enable_patch(struct klp_patch *);
-int klp_disable_patch(struct klp_patch *);
void arch_klp_init_object_loaded(struct klp_patch *patch,
struct klp_object *obj);