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: Zheng Yejian zhengyejian1@huawei.com --- arch/arm/kernel/livepatch.c | 23 ++++++++++++++++++++--- arch/arm64/kernel/livepatch.c | 23 ++++++++++++++++++++--- arch/powerpc/kernel/livepatch_32.c | 22 +++++++++++++++++++--- arch/x86/kernel/livepatch.c | 23 +++++++++++++++++++---- 4 files changed, 78 insertions(+), 13 deletions(-)
diff --git a/arch/arm/kernel/livepatch.c b/arch/arm/kernel/livepatch.c index b4d26474ba33..5415de07c8f7 100644 --- a/arch/arm/kernel/livepatch.c +++ b/arch/arm/kernel/livepatch.c @@ -134,11 +134,14 @@ 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) { if (func->patched || func->force == KLP_ENFORCEMENT) continue; @@ -153,7 +156,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 +187,13 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable, func->old_name, func->force); 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, func->force); + if (ret) + return ret; + } } } else { /* @@ -203,7 +213,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 +229,13 @@ 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; diff --git a/arch/arm64/kernel/livepatch.c b/arch/arm64/kernel/livepatch.c index 6b5bcb491125..d1a1dd4fb87a 100644 --- a/arch/arm64/kernel/livepatch.c +++ b/arch/arm64/kernel/livepatch.c @@ -126,12 +126,15 @@ 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) { if (func->patched || func->force == KLP_ENFORCEMENT) continue; @@ -142,7 +145,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 +176,13 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable, func->old_name, func->force); 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, func->force); + if (ret) + return ret; + } } } else { /* @@ -193,7 +203,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 +219,13 @@ 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; diff --git a/arch/powerpc/kernel/livepatch_32.c b/arch/powerpc/kernel/livepatch_32.c index 7b4ed23bf2ca..d5bbc58739e1 100644 --- a/arch/powerpc/kernel/livepatch_32.c +++ b/arch/powerpc/kernel/livepatch_32.c @@ -123,12 +123,15 @@ 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) { if (func->patched || func->force == KLP_ENFORCEMENT) continue; @@ -143,7 +146,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 +177,13 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable, func->old_name, func->force); 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, func->force); + if (ret) + return ret; + } } } else { /* @@ -193,7 +203,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 +218,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; diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c index 0241e560bd2e..d6e10df5e622 100644 --- a/arch/x86/kernel/livepatch.c +++ b/arch/x86/kernel/livepatch.c @@ -120,14 +120,16 @@ 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) { if (func->patched || func->force == KLP_ENFORCEMENT) @@ -138,7 +140,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 +171,13 @@ static int klp_check_activeness_func(struct klp_patch *patch, int enable, func->old_name, func->force); 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, func->force); + if (ret) + return ret; + } } } else { /* @@ -186,7 +195,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 +210,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;
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/2073 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/3...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/2073 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/3...