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 | list_add_tail(&obj->node, &patch->obj_list); | 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 | struct klp_object *obj; | 867 | struct klp_object *obj; |
| 868 | struct klp_func *func; | 868 | struct klp_func *func; |
| 869 | 869 | ||
| 870 | if (!patch->objs) | ||
| 871 | return -EINVAL; | ||
| 872 | |||
| 873 | INIT_LIST_HEAD(&patch->list); | 870 | INIT_LIST_HEAD(&patch->list); |
| 874 | INIT_LIST_HEAD(&patch->obj_list); | 871 | INIT_LIST_HEAD(&patch->obj_list); |
| 875 | kobject_init(&patch->kobj, &klp_ktype_patch); | 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 | init_completion(&patch->finish); | 876 | init_completion(&patch->finish); |
| 880 | 877 | ||
| 881 | klp_for_each_object_static(patch, obj) { | 878 | klp_for_each_object_static(patch, obj) { |
| 882 | if (!obj->funcs) | ||
| 883 | return -EINVAL; | ||
| 884 | |||
| 885 | klp_init_object_early(patch, obj); | 879 | klp_init_object_early(patch, obj); |
| 886 | 880 | ||
| 887 | klp_for_each_func_static(obj, func) { | 881 | klp_for_each_func_static(obj, func) { |
| 888 | klp_init_func_early(obj, func); | 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 | static int klp_init_patch(struct klp_patch *patch) | 887 | static int klp_init_patch(struct klp_patch *patch) |
| @@ -1024,10 +1013,17 @@ err: · 125 unmodified lines | |||
| 1024 | int klp_enable_patch(struct klp_patch *patch) | 1013 | int klp_enable_patch(struct klp_patch *patch) |
| 1025 | { | 1014 | { |
| 1026 | int ret; | 1015 | int ret; |
| 1016 | struct klp_object *obj; | ||
| 1027 | 1017 | ||
| 1028 | if (!patch || !patch->mod) | 1018 | if (!patch || !patch->mod || !patch->objs) |
| 1029 | return -EINVAL; | 1019 | return -EINVAL; |
| 1030 | 1020 | ||
| 1021 | klp_for_each_object_static(patch, obj) { | ||
| 1022 | if (!obj->funcs) | ||
| 1023 | return -EINVAL; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | |||
| 1031 | if (!is_livepatch_module(patch->mod)) { | 1027 | if (!is_livepatch_module(patch->mod)) { |
| 1032 | pr_err("module %s is not marked as a livepatch module\n", | 1028 | pr_err("module %s is not marked as a livepatch module\n", |
| 1033 | patch->mod->name); | 1029 | patch->mod->name); |
| @@ -1051,12 +1047,13 @@ int klp_enable_patch(struct klp_patch *patch) · 17 unmodified lines | |||
| 1051 | return -EINVAL; | 1047 | return -EINVAL; |
| 1052 | } | 1048 | } |
| 1053 | 1049 | ||
| 1054 | ret = klp_init_patch_early(patch); | 1050 | if (!try_module_get(patch->mod)) { |
| 1055 | if (ret) { | ||
| 1056 | mutex_unlock(&klp_mutex); | 1051 | mutex_unlock(&klp_mutex); |
| 1057 | return ret; | 1052 | return -ENODEV; |
| 1058 | } | 1053 | } |
| 1059 | 1054 | ||
| 1055 | klp_init_patch_early(patch); | ||
| 1056 | |||
| 1060 | ret = klp_init_patch(patch); | 1057 | ret = klp_init_patch(patch); |
| 1061 | if (ret) | 1058 | if (ret) |
| 1062 | goto err; | 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 | EXPORT_SYMBOL_GPL(klp_shadow_free); | 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 | * @id: data identifier | 276 | * @id: data identifier |
| 277 | * @dtor: custom callback that can be used to unregister the variable | 277 | * @dtor: custom callback that can be used to unregister the variable |
| 278 | * and/or free data that the shadow variable points to (optional) | 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 | * instances, callers should stop referencing them accordingly. | 281 | * instances, callers should stop referencing them accordingly. |
| 282 | */ | 282 | */ |
| 283 | void klp_shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor) | 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 | spin_lock_irqsave(&klp_shadow_lock, flags); | 289 | spin_lock_irqsave(&klp_shadow_lock, flags); |
| 290 | 290 | ||
| 291 | /* Delete all <*, id> from hash */ | 291 | /* Delete all <_, id> from hash */ |
| 292 | hash_for_each(klp_shadow_hash, i, shadow, node) { | 292 | hash_for_each(klp_shadow_hash, i, shadow, node) { |
| 293 | if (klp_shadow_match(shadow, shadow->obj, id)) | 293 | if (klp_shadow_match(shadow, shadow->obj, id)) |
| 294 | klp_shadow_free_struct(shadow, dtor); | 294 | klp_shadow_free_struct(shadow, dtor); |