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

livepatch/core: Fix possible issue that old function is not checked

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I7ZH67


CVE: NA

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

After patch being enabled, the first few instructions would be
modified to jump to the new function, then callers of old function
would jump to new function but always through the old function.

Therefore when enabling a new patch or disable a patch on the old
function, we should always consider that old function is running.
Otherwise, there may be situations where old functions are being
modified before jumping to new function and cause issues.

Signed-off-by: default avatarZheng Yejian <zhengyejian1@huawei.com>
parent 8545e9cf
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -134,12 +134,17 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
	struct klp_object *obj;
	struct klp_func_node *func_node;
	struct klp_func *func;
	unsigned long func_addr, func_size;
	unsigned long func_addr = 0;
	unsigned long func_size;
	struct klp_func_list *pcheck = NULL;

	for (obj = patch->objs; obj->funcs; obj++) {
		for (func = obj->funcs; func->old_name; func++) {
			unsigned long old_func = (unsigned long)func->old_func;

			if (enable) {
				bool need_check_old = false;

				if (func->patched || func->force == KLP_ENFORCEMENT)
					continue;
				/*
@@ -153,7 +158,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
					 * No patched on this function
					 * [ the origin one ]
					 */
					func_addr = (unsigned long)func->old_func;
					func_addr = old_func;
					func_size = func->old_size;
				} else {
					/*
@@ -184,6 +189,13 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
							func->old_name, func->force);
					if (ret)
						return ret;
					need_check_old = (func_addr != old_func);
				}
				if (need_check_old) {
					ret = add_func_to_list(check_funcs, &pcheck, old_func,
						func->old_size, func->old_name, func->force);
					if (ret)
						return ret;
				}
			} else {
				/*
@@ -203,7 +215,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
				 * the stack.
				 */
				if (list_is_singular(&func_node->func_stack)) {
					func_addr = (unsigned long)func->old_func;
					func_addr = old_func;
					func_size = func->old_size;
				} else {
					struct klp_func *prev;
@@ -219,6 +231,12 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
						func->old_name, 0);
				if (ret)
					return ret;
				if (func_addr != old_func) {
					ret = add_func_to_list(check_funcs, &pcheck, old_func,
						func->old_size, func->old_name, 0);
					if (ret)
						return ret;
				}
#endif
				func_addr = (unsigned long)func->new_func;
				func_size = func->new_size;
+21 −3
Original line number Diff line number Diff line
@@ -126,13 +126,18 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
	int ret;
	struct klp_object *obj;
	struct klp_func *func;
	unsigned long func_addr, func_size;
	unsigned long func_addr = 0;
	unsigned long func_size;
	struct klp_func_node *func_node;
	struct klp_func_list *pcheck = NULL;

	for (obj = patch->objs; obj->funcs; obj++) {
		for (func = obj->funcs; func->old_name; func++) {
			unsigned long old_func = (unsigned long)func->old_func;

			if (enable) {
				bool need_check_old = false;

				if (func->patched || func->force == KLP_ENFORCEMENT)
					continue;
				/*
@@ -142,7 +147,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
				func_node = klp_find_func_node(func->old_func);
				if (!func_node ||
				    list_empty(&func_node->func_stack)) {
					func_addr = (unsigned long)func->old_func;
					func_addr = old_func;
					func_size = func->old_size;
				} else {
					/*
@@ -173,6 +178,13 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
							func->old_name, func->force);
					if (ret)
						return ret;
					need_check_old = (func_addr != old_func);
				}
				if (need_check_old) {
					ret = add_func_to_list(check_funcs, &pcheck, old_func,
						func->old_size, func->old_name, func->force);
					if (ret)
						return ret;
				}
			} else {
				/*
@@ -193,7 +205,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
				 * the stack.
				 */
				if (list_is_singular(&func_node->func_stack)) {
					func_addr = (unsigned long)func->old_func;
					func_addr = old_func;
					func_size = func->old_size;
				} else {
					struct klp_func *prev;
@@ -209,6 +221,12 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
						func->old_name, 0);
				if (ret)
					return ret;
				if (func_addr != old_func) {
					ret = add_func_to_list(check_funcs, &pcheck, old_func,
						func->old_size, func->old_name, 0);
					if (ret)
						return ret;
				}
#endif

				func_addr = (unsigned long)func->new_func;
+21 −3
Original line number Diff line number Diff line
@@ -123,13 +123,18 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
	int ret;
	struct klp_object *obj;
	struct klp_func *func;
	unsigned long func_addr, func_size;
	unsigned long func_addr = 0;
	unsigned long func_size;
	struct klp_func_node *func_node;
	struct klp_func_list *pcheck = NULL;

	for (obj = patch->objs; obj->funcs; obj++) {
		for (func = obj->funcs; func->old_name; func++) {
			unsigned long old_func = (unsigned long)func->old_func;

			if (enable) {
				bool need_check_old = false;

				if (func->patched || func->force == KLP_ENFORCEMENT)
					continue;
				/*
@@ -143,7 +148,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
					 * No patched on this function
					 * [ the origin one ]
					 */
					func_addr = (unsigned long)func->old_func;
					func_addr = old_func;
					func_size = func->old_size;
				} else {
					/*
@@ -174,6 +179,13 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
							func->old_name, func->force);
					if (ret)
						return ret;
					need_check_old = (func_addr != old_func);
				}
				if (need_check_old) {
					ret = add_func_to_list(check_funcs, &pcheck, old_func,
						func->old_size, func->old_name, func->force);
					if (ret)
						return ret;
				}
			} else {
				/*
@@ -193,7 +205,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
				 * the stack.
				 */
				if (list_is_singular(&func_node->func_stack)) {
					func_addr = (unsigned long)func->old_func;
					func_addr = old_func;
					func_size = func->old_size;
				} else {
					struct klp_func *prev;
@@ -208,6 +220,12 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
						func_size, func->old_name, 0);
				if (ret)
					return ret;
				if (func_addr != old_func) {
					ret = add_func_to_list(check_funcs, &pcheck, old_func,
							func->old_size, func->old_name, 0);
					if (ret)
						return ret;
				}
#endif
				func_addr = (unsigned long)func->new_func;
				func_size = func->new_size;
+21 −4
Original line number Diff line number Diff line
@@ -120,16 +120,20 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
	int ret;
	struct klp_object *obj;
	struct klp_func *func;
	unsigned long func_addr, func_size;
	unsigned long func_addr = 0;
	unsigned long func_size;
	struct klp_func_node *func_node = NULL;
	struct klp_func_list *pcheck = NULL;

	for (obj = patch->objs; obj->funcs; obj++) {
		for (func = obj->funcs; func->old_name; func++) {
			func_node = klp_find_func_node(func->old_func);
			unsigned long old_func = (unsigned long)func->old_func;

			func_node = klp_find_func_node(func->old_func);
			/* Check func address in stack */
			if (enable) {
				bool need_check_old = false;

				if (func->patched || func->force == KLP_ENFORCEMENT)
					continue;
				/*
@@ -138,7 +142,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
				 */
				if (!func_node ||
				    list_empty(&func_node->func_stack)) {
					func_addr = (unsigned long)func->old_func;
					func_addr = old_func;
					func_size = func->old_size;
				} else {
					/*
@@ -169,6 +173,13 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
							func->old_name, func->force);
					if (ret)
						return ret;
					need_check_old = (func_addr != old_func);
				}
				if (need_check_old) {
					ret = add_func_to_list(check_funcs, &pcheck, old_func,
						func->old_size, func->old_name, func->force);
					if (ret)
						return ret;
				}
			} else {
				/*
@@ -186,7 +197,7 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
				 * the stack.
				 */
				if (list_is_singular(&func_node->func_stack)) {
					func_addr = (unsigned long)func->old_func;
					func_addr = old_func;
					func_size = func->old_size;
				} else {
					struct klp_func *prev;
@@ -201,6 +212,12 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable,
						func_size, func->old_name, 0);
				if (ret)
					return ret;
				if (func_addr != old_func) {
					ret = add_func_to_list(check_funcs, &pcheck, old_func,
							func->old_size, func->old_name, 0);
					if (ret)
						return ret;
				}
#endif

				func_addr = (unsigned long)func->new_func;