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
This commit is contained in:
@@ -862,14 +862,11 @@ static void klp_init_object_early(struct klp_patch *patch,
|
||||
list_add_tail(&obj->node, &patch->obj_list);
|
||||
}
|
||||
|
||||
static int klp_init_patch_early(struct klp_patch *patch)
|
||||
static void klp_init_patch_early(struct klp_patch *patch)
|
||||
{
|
||||
struct klp_object *obj;
|
||||
struct klp_func *func;
|
||||
|
||||
if (!patch->objs)
|
||||
return -EINVAL;
|
||||
|
||||
INIT_LIST_HEAD(&patch->list);
|
||||
INIT_LIST_HEAD(&patch->obj_list);
|
||||
kobject_init(&patch->kobj, &klp_ktype_patch);
|
||||
@@ -879,20 +876,12 @@ static int klp_init_patch_early(struct klp_patch *patch)
|
||||
init_completion(&patch->finish);
|
||||
|
||||
klp_for_each_object_static(patch, obj) {
|
||||
if (!obj->funcs)
|
||||
return -EINVAL;
|
||||
|
||||
klp_init_object_early(patch, obj);
|
||||
|
||||
klp_for_each_func_static(obj, func) {
|
||||
klp_init_func_early(obj, func);
|
||||
}
|
||||
}
|
||||
|
||||
if (!try_module_get(patch->mod))
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int klp_init_patch(struct klp_patch *patch)
|
||||
@@ -1024,10 +1013,17 @@ err:
|
||||
int klp_enable_patch(struct klp_patch *patch)
|
||||
{
|
||||
int ret;
|
||||
struct klp_object *obj;
|
||||
|
||||
if (!patch || !patch->mod)
|
||||
if (!patch || !patch->mod || !patch->objs)
|
||||
return -EINVAL;
|
||||
|
||||
klp_for_each_object_static(patch, obj) {
|
||||
if (!obj->funcs)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
if (!is_livepatch_module(patch->mod)) {
|
||||
pr_err("module %s is not marked as a livepatch module\n",
|
||||
patch->mod->name);
|
||||
@@ -1051,12 +1047,13 @@ int klp_enable_patch(struct klp_patch *patch)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = klp_init_patch_early(patch);
|
||||
if (ret) {
|
||||
if (!try_module_get(patch->mod)) {
|
||||
mutex_unlock(&klp_mutex);
|
||||
return ret;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
klp_init_patch_early(patch);
|
||||
|
||||
ret = klp_init_patch(patch);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@@ -272,12 +272,12 @@ void klp_shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor)
|
||||
EXPORT_SYMBOL_GPL(klp_shadow_free);
|
||||
|
||||
/**
|
||||
* klp_shadow_free_all() - detach and free all <*, id> shadow variables
|
||||
* klp_shadow_free_all() - detach and free all <_, id> shadow variables
|
||||
* @id: data identifier
|
||||
* @dtor: custom callback that can be used to unregister the variable
|
||||
* and/or free data that the shadow variable points to (optional)
|
||||
*
|
||||
* This function releases the memory for all <*, id> shadow variable
|
||||
* This function releases the memory for all <_, id> shadow variable
|
||||
* instances, callers should stop referencing them accordingly.
|
||||
*/
|
||||
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)
|
||||
|
||||
spin_lock_irqsave(&klp_shadow_lock, flags);
|
||||
|
||||
/* Delete all <*, id> from hash */
|
||||
/* Delete all <_, id> from hash */
|
||||
hash_for_each(klp_shadow_hash, i, shadow, node) {
|
||||
if (klp_shadow_match(shadow, shadow->obj, id))
|
||||
klp_shadow_free_struct(shadow, dtor);
|
||||
|
||||
Reference in New Issue
Block a user