Commit a21b898d authored by Zheng Yejian's avatar Zheng Yejian
Browse files

livepatch/core: Support load and unload hooks

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8MGE6


CVE: NA

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

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: default avatarCheng Jian <cj.chengjian@huawei.com>
Signed-off-by: default avatarWang ShaoBo <bobo.shaobowang@huawei.com>
Signed-off-by: default avatarDong Kai <dongkai11@huawei.com>
Signed-off-by: default avatarYe Weihua <yeweihua4@huawei.com>
Signed-off-by: default avatarYang Jihong <yangjihong1@huawei.com>
Signed-off-by: default avatarZheng Yejian <zhengyejian1@huawei.com>
parent e7d9e2d7
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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 */
+37 −0
Original line number Diff line number Diff line
@@ -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 */

@@ -1057,6 +1059,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;
@@ -1477,6 +1484,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;
@@ -2362,6 +2395,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);

@@ -2375,6 +2409,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);