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
Showing the changes to kernel/livepatch (2 of 8 files). Show all
Unified · Split
| @@ -862,14 +862,11 @@ static void klp_init_object_early(struct klp_patch *patch, · 861 unmodified lines | ||
| 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 | 869 | |
| 870 | − if (!patch->objs) | |
| 871 | − return -EINVAL; | |
| 872 | − | |
| 873 | 870 | INIT_LIST_HEAD(&patch->list); |
| 874 | 871 | INIT_LIST_HEAD(&patch->obj_list); |
| 875 | 872 | kobject_init(&patch->kobj, &klp_ktype_patch); |
| @@ -879,20 +876,12 @@ static int klp_init_patch_early(struct klp_patch *patch) · 3 unmodified lines | ||
| 879 | 876 | init_completion(&patch->finish); |
| 880 | 877 | |
| 881 | 878 | klp_for_each_object_static(patch, obj) { |
| 882 | − if (!obj->funcs) | |
| 883 | − return -EINVAL; | |
| 884 | − | |
| 885 | 879 | klp_init_object_early(patch, obj); |
| 886 | 880 | |
| 887 | 881 | klp_for_each_func_static(obj, func) { |
| 888 | 882 | klp_init_func_early(obj, func); |
| 889 | 883 | } |
| 890 | 884 | } |
| 891 | − | |
| 892 | − if (!try_module_get(patch->mod)) | |
| 893 | − return -ENODEV; | |
| 894 | − | |
| 895 | − return 0; | |
| 896 | 885 | } |
| 897 | 886 | |
| 898 | 887 | static int klp_init_patch(struct klp_patch *patch) |
| @@ -1024,10 +1013,17 @@ err: · 125 unmodified lines | ||
| 1024 | 1013 | int klp_enable_patch(struct klp_patch *patch) |
| 1025 | 1014 | { |
| 1026 | 1015 | int ret; |
| 1016 | + struct klp_object *obj; | |
| 1027 | 1017 | |
| 1028 | − if (!patch || !patch->mod) | |
| 1018 | + if (!patch || !patch->mod || !patch->objs) | |
| 1029 | 1019 | return -EINVAL; |
| 1030 | 1020 | |
| 1021 | + klp_for_each_object_static(patch, obj) { | |
| 1022 | + if (!obj->funcs) | |
| 1023 | + return -EINVAL; | |
| 1024 | + } | |
| 1025 | + | |
| 1026 | + | |
| 1031 | 1027 | if (!is_livepatch_module(patch->mod)) { |
| 1032 | 1028 | pr_err("module %s is not marked as a livepatch module\n", |
| 1033 | 1029 | patch->mod->name); |
| @@ -1051,12 +1047,13 @@ int klp_enable_patch(struct klp_patch *patch) · 17 unmodified lines | ||
| 1051 | 1047 | return -EINVAL; |
| 1052 | 1048 | } |
| 1053 | 1049 | |
| 1054 | − ret = klp_init_patch_early(patch); | |
| 1055 | − if (ret) { | |
| 1050 | + if (!try_module_get(patch->mod)) { | |
| 1056 | 1051 | mutex_unlock(&klp_mutex); |
| 1057 | − return ret; | |
| 1052 | + return -ENODEV; | |
| 1058 | 1053 | } |
| 1059 | 1054 | |
| 1055 | + klp_init_patch_early(patch); | |
| 1056 | + | |
| 1060 | 1057 | ret = klp_init_patch(patch); |
| 1061 | 1058 | if (ret) |
| 1062 | 1059 | goto err; |
| @@ -272,12 +272,12 @@ void klp_shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor) · 271 unmodified lines | ||
| 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,7 +288,7 @@ void klp_shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor) · 4 unmodified lines | ||
| 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); |