From: Li Huafei lihuafei1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5CJ7X
--------------------------------
klp_find_func_node() is used to traverse the klp_func_list linked list. Currently, klp_find_func_node() is used only when the klp_mutex lock is held. In the subsequent submission, we need to access the klp_func_list linked list in the exception handling process and cannot hold the klp_mutex lock.
We change the traversal of klp_func_list to use the rcu interface and perform rcu synchronization when deleting nodes.
Signed-off-by: Li Huafei lihuafei1@huawei.com Reviewed-by: Xu Kuohai xukuohai@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- kernel/livepatch/core.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 957f16f6c6c4..47d8661ee5e4 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -1273,11 +1273,16 @@ int __weak klp_check_calltrace(struct klp_patch *patch, int enable)
static LIST_HEAD(klp_func_list);
+/* + * The caller must ensure that the klp_mutex lock is held or is in the rcu read + * critical area. + */ struct klp_func_node *klp_find_func_node(const void *old_func) { struct klp_func_node *func_node;
- list_for_each_entry(func_node, &klp_func_list, node) { + list_for_each_entry_rcu(func_node, &klp_func_list, node, + lockdep_is_held(&klp_mutex)) { if (func_node->old_func == old_func) return func_node; } @@ -1403,6 +1408,7 @@ static void func_node_free(struct klp_func *func) func->func_node = NULL; if (list_empty(&func_node->func_stack)) { klp_del_func_node(func_node); + synchronize_rcu(); arch_klp_mem_free(func_node); } }