提交 4773e57d 编写于 作者: C Cheng Jian 提交者: Zheng Zengkai

livepatch/core: Supprt load and unload hooks

euler inclusion
category: feature
bugzilla: 51921
CVE: N/A

----------------------------------------

The front-tools kpatch-build support load and unload hooks
in the older version and already changed to use pre/post
callbacks after commit 93862e38 ("livepatch: add (un)patch
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: NCheng Jian <cj.chengjian@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NWang ShaoBo <bobo.shaobowang@huawei.com>
Signed-off-by: NDong Kai <dongkai11@huawei.com>
Signed-off-by: NYe Weihua <yeweihua4@huawei.com>
Reviewed-by: NYang Jihong <yangjihong1@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 086c4b46
...@@ -82,6 +82,12 @@ struct klp_func { ...@@ -82,6 +82,12 @@ struct klp_func {
struct klp_object; struct klp_object;
#ifdef CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY
struct klp_hook {
void (*hook)(void);
};
#endif
/** /**
* struct klp_callbacks - pre/post live-(un)patch callback structure * struct klp_callbacks - pre/post live-(un)patch callback structure
* @pre_patch: executed before code patching * @pre_patch: executed before code patching
...@@ -121,6 +127,10 @@ struct klp_object { ...@@ -121,6 +127,10 @@ struct klp_object {
/* external */ /* external */
const char *name; const char *name;
struct klp_func *funcs; struct klp_func *funcs;
#ifdef CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY
struct klp_hook *hooks_load;
struct klp_hook *hooks_unload;
#endif
struct klp_callbacks callbacks; struct klp_callbacks callbacks;
/* internal */ /* internal */
......
...@@ -790,6 +790,34 @@ static void klp_free_patch_start(struct klp_patch *patch) ...@@ -790,6 +790,34 @@ static void klp_free_patch_start(struct klp_patch *patch)
klp_free_objects(patch); klp_free_objects(patch);
} }
#ifdef CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY
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;
}
#endif
/* /*
* This function implements the free part that must be called outside * This function implements the free part that must be called outside
* klp_mutex. * klp_mutex.
...@@ -800,6 +828,12 @@ static void klp_free_patch_start(struct klp_patch *patch) ...@@ -800,6 +828,12 @@ static void klp_free_patch_start(struct klp_patch *patch)
*/ */
static void klp_free_patch_finish(struct klp_patch *patch) static void klp_free_patch_finish(struct klp_patch *patch)
{ {
#ifdef CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY
struct klp_object *obj;
klp_for_each_object(patch, obj)
klp_unload_hook(obj);
#endif
/* /*
* Avoid deadlock with enabled_store() sysfs callback by * Avoid deadlock with enabled_store() sysfs callback by
* calling this outside klp_mutex. It is safe because * calling this outside klp_mutex. It is safe because
...@@ -1074,6 +1108,11 @@ static int klp_init_patch(struct klp_patch *patch) ...@@ -1074,6 +1108,11 @@ static int klp_init_patch(struct klp_patch *patch)
goto out; goto out;
} }
#ifdef CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY
klp_for_each_object(patch, obj)
klp_load_hook(obj);
#endif
list_add_tail(&patch->list, &klp_patches); list_add_tail(&patch->list, &klp_patches);
return 0; return 0;
......
...@@ -23,6 +23,7 @@ static inline bool klp_is_object_loaded(struct klp_object *obj) ...@@ -23,6 +23,7 @@ static inline bool klp_is_object_loaded(struct klp_object *obj)
return !obj->name || obj->mod; return !obj->name || obj->mod;
} }
#ifdef CONFIG_LIVEPATCH_PER_TASK_CONSISTENCY
static inline int klp_pre_patch_callback(struct klp_object *obj) static inline int klp_pre_patch_callback(struct klp_object *obj)
{ {
int ret = 0; int ret = 0;
...@@ -55,5 +56,5 @@ static inline void klp_post_unpatch_callback(struct klp_object *obj) ...@@ -55,5 +56,5 @@ static inline void klp_post_unpatch_callback(struct klp_object *obj)
obj->callbacks.post_unpatch_enabled = false; obj->callbacks.post_unpatch_enabled = false;
} }
#endif /* CONFIG_LIVEPATCH_PER_TASK_CONSISTENCY */
#endif /* _LIVEPATCH_CORE_H */ #endif /* _LIVEPATCH_CORE_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册