Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'livepatching-for-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching

Pull livepatching updates from Petr Mladek:

- Correctly handle kobjects when a livepatch init fails

- Avoid CPU hogging when searching for many livepatched symbols

- Add livepatch API page into documentation

* tag 'livepatching-for-5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching:
livepatch: Avoid CPU hogging with cond_resched
livepatch: Fix missing unlock on error in klp_enable_patch()
livepatch: Fix kobject refcount bug on klp_init_patch_early failure path
Documentation: livepatch: Add livepatch API page

+54 -23
+30
Documentation/livepatch/api.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ================= 4 + Livepatching APIs 5 + ================= 6 + 7 + Livepatch Enablement 8 + ==================== 9 + 10 + .. kernel-doc:: kernel/livepatch/core.c 11 + :export: 12 + 13 + 14 + Shadow Variables 15 + ================ 16 + 17 + .. kernel-doc:: kernel/livepatch/shadow.c 18 + :export: 19 + 20 + System State Changes 21 + ==================== 22 + 23 + .. kernel-doc:: kernel/livepatch/state.c 24 + :export: 25 + 26 + Object Types 27 + ============ 28 + 29 + .. kernel-doc:: include/linux/livepatch.h 30 + :identifiers: klp_patch klp_object klp_func klp_callbacks klp_state
+1
Documentation/livepatch/index.rst
··· 14 14 shadow-vars 15 15 system-state 16 16 reliable-stacktrace 17 + api 17 18 18 19 .. only:: subproject and html 19 20
+2 -2
Documentation/livepatch/shadow-vars.rst
··· 82 82 - call destructor function if defined 83 83 - free shadow variable 84 84 85 - * klp_shadow_free_all() - detach and free all <*, id> shadow variables 86 - - find and remove any <*, id> references from global hashtable 85 + * klp_shadow_free_all() - detach and free all <_, id> shadow variables 86 + - find and remove any <_, id> references from global hashtable 87 87 88 88 - if found 89 89
+2 -2
Documentation/livepatch/system-state.rst
··· 52 52 53 53 The state can be manipulated using two functions: 54 54 55 - - *klp_get_state(patch, id)* 55 + - klp_get_state() 56 56 57 57 - Get struct klp_state associated with the given livepatch 58 58 and state id. 59 59 60 - - *klp_get_prev_state(id)* 60 + - klp_get_prev_state() 61 61 62 62 - Get struct klp_state associated with the given feature id and 63 63 already installed livepatches.
+1
kernel/kallsyms.c
··· 243 243 ret = fn(data, namebuf, NULL, kallsyms_sym_address(i)); 244 244 if (ret != 0) 245 245 return ret; 246 + cond_resched(); 246 247 } 247 248 return 0; 248 249 }
+13 -16
kernel/livepatch/core.c
··· 862 862 list_add_tail(&obj->node, &patch->obj_list); 863 863 } 864 864 865 - static int klp_init_patch_early(struct klp_patch *patch) 865 + static void klp_init_patch_early(struct klp_patch *patch) 866 866 { 867 867 struct klp_object *obj; 868 868 struct klp_func *func; 869 - 870 - if (!patch->objs) 871 - return -EINVAL; 872 869 873 870 INIT_LIST_HEAD(&patch->list); 874 871 INIT_LIST_HEAD(&patch->obj_list); ··· 876 879 init_completion(&patch->finish); 877 880 878 881 klp_for_each_object_static(patch, obj) { 879 - if (!obj->funcs) 880 - return -EINVAL; 881 - 882 882 klp_init_object_early(patch, obj); 883 883 884 884 klp_for_each_func_static(obj, func) { 885 885 klp_init_func_early(obj, func); 886 886 } 887 887 } 888 - 889 - if (!try_module_get(patch->mod)) 890 - return -ENODEV; 891 - 892 - return 0; 893 888 } 894 889 895 890 static int klp_init_patch(struct klp_patch *patch) ··· 1013 1024 int klp_enable_patch(struct klp_patch *patch) 1014 1025 { 1015 1026 int ret; 1027 + struct klp_object *obj; 1016 1028 1017 - if (!patch || !patch->mod) 1029 + if (!patch || !patch->mod || !patch->objs) 1018 1030 return -EINVAL; 1031 + 1032 + klp_for_each_object_static(patch, obj) { 1033 + if (!obj->funcs) 1034 + return -EINVAL; 1035 + } 1036 + 1019 1037 1020 1038 if (!is_livepatch_module(patch->mod)) { 1021 1039 pr_err("module %s is not marked as a livepatch module\n", ··· 1047 1051 return -EINVAL; 1048 1052 } 1049 1053 1050 - ret = klp_init_patch_early(patch); 1051 - if (ret) { 1054 + if (!try_module_get(patch->mod)) { 1052 1055 mutex_unlock(&klp_mutex); 1053 - return ret; 1056 + return -ENODEV; 1054 1057 } 1058 + 1059 + klp_init_patch_early(patch); 1055 1060 1056 1061 ret = klp_init_patch(patch); 1057 1062 if (ret)
+3 -3
kernel/livepatch/shadow.c
··· 272 272 EXPORT_SYMBOL_GPL(klp_shadow_free); 273 273 274 274 /** 275 - * klp_shadow_free_all() - detach and free all <*, id> shadow variables 275 + * klp_shadow_free_all() - detach and free all <_, id> shadow variables 276 276 * @id: data identifier 277 277 * @dtor: custom callback that can be used to unregister the variable 278 278 * and/or free data that the shadow variable points to (optional) 279 279 * 280 - * This function releases the memory for all <*, id> shadow variable 280 + * This function releases the memory for all <_, id> shadow variable 281 281 * instances, callers should stop referencing them accordingly. 282 282 */ 283 283 void klp_shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor) ··· 288 288 289 289 spin_lock_irqsave(&klp_shadow_lock, flags); 290 290 291 - /* Delete all <*, id> from hash */ 291 + /* Delete all <_, id> from hash */ 292 292 hash_for_each(klp_shadow_hash, i, shadow, node) { 293 293 if (klp_shadow_match(shadow, shadow->obj, id)) 294 294 klp_shadow_free_struct(shadow, dtor);
+2
kernel/module.c
··· 4499 4499 mod, kallsyms_symbol_value(sym)); 4500 4500 if (ret != 0) 4501 4501 goto out; 4502 + 4503 + cond_resched(); 4502 4504 } 4503 4505 } 4504 4506 out: