hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I7W46D
--------------------------------
The front-tools kpatch-build support load and unload hooks in the older version and already changed to use pre/post callbacks.
However, for livepatch based on stop machine consistency, this callbacks will be called within stop_machine context if we using it. This is dangerous because we can't known what the user will do in the callbacks. It may trigger system crash if using any function which internally might sleep.
Here we use the old load/unload hooks to allow user-defined hooks. Although it's not good enough compared to pre/post callbacks, it can meets user needs to some extent. Of cource, this requires cooperation of kpatch-build tools.
Signed-off-by: Cheng Jian cj.chengjian@huawei.com Signed-off-by: Wang ShaoBo bobo.shaobowang@huawei.com Signed-off-by: Dong Kai dongkai11@huawei.com Signed-off-by: Ye Weihua yeweihua4@huawei.com Signed-off-by: Yang Jihong yangjihong1@huawei.com Signed-off-by: Zheng Yejian zhengyejian1@huawei.com --- include/linux/livepatch.h | 10 ++++++++++ kernel/livepatch/core.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+)
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h index 5610b56ff74e..408a2065386e 100644 --- a/include/linux/livepatch.h +++ b/include/linux/livepatch.h @@ -87,6 +87,12 @@ struct klp_func { void *func_node; /* Only used in the solution without ftrace */ };
+#ifdef CONFIG_LIVEPATCH_WO_FTRACE +struct klp_hook { + void (*hook)(void); +}; +#endif /* CONFIG_LIVEPATCH_WO_FTRACE */ + struct klp_object;
/** @@ -128,6 +134,10 @@ struct klp_object { /* external */ const char *name; struct klp_func *funcs; +#ifdef CONFIG_LIVEPATCH_WO_FTRACE + struct klp_hook *hooks_load; + struct klp_hook *hooks_unload; +#endif struct klp_callbacks callbacks; /* Not used in the solution without ftrace */
/* internal */ diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index f1163a4bad28..bc71a0c95d2c 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -421,6 +421,8 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); +static inline int klp_load_hook(struct klp_object *obj); +static inline int klp_unload_hook(struct klp_object *obj);
#endif /* CONFIG_LIVEPATCH_FTRACE */
@@ -1058,6 +1060,11 @@ static int klp_init_patch(struct klp_patch *patch) return ret; }
+#ifdef CONFIG_LIVEPATCH_WO_FTRACE + klp_for_each_object(patch, obj) + klp_load_hook(obj); +#endif + list_add_tail(&patch->list, &klp_patches);
return 0; @@ -1480,6 +1487,32 @@ static const struct proc_ops proc_klpstate_operations = { .proc_release = single_release, };
+static inline int klp_load_hook(struct klp_object *obj) +{ + struct klp_hook *hook; + + if (!obj->hooks_load) + return 0; + + for (hook = obj->hooks_load; hook->hook; hook++) + (*hook->hook)(); + + return 0; +} + +static inline int klp_unload_hook(struct klp_object *obj) +{ + struct klp_hook *hook; + + if (!obj->hooks_unload) + return 0; + + for (hook = obj->hooks_unload; hook->hook; hook++) + (*hook->hook)(); + + return 0; +} + static int klp_find_object_module(struct klp_object *obj) { struct module *mod; @@ -2351,6 +2384,7 @@ EXPORT_SYMBOL_GPL(klp_register_patch); int klp_unregister_patch(struct klp_patch *patch) { int ret = 0; + struct klp_object *obj;
mutex_lock(&klp_mutex);
@@ -2364,6 +2398,9 @@ int klp_unregister_patch(struct klp_patch *patch) goto out; }
+ klp_for_each_object(patch, obj) + klp_unload_hook(obj); + klp_free_patch_start(patch);
mutex_unlock(&klp_mutex);