aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2019-01-09 07:43:21 -0500
committerJiri Kosina <jkosina@suse.cz>2019-01-11 14:51:23 -0500
commit0430f78bf38f9972f0cf0522709cc63d49fa164c (patch)
tree365e431896c99c4a10b3d3db72cc261796587be6 /kernel
parent26c3e98e2f8e44e856cd36c12b3eaefcc6eafb16 (diff)
livepatch: Consolidate klp_free functions
The code for freeing livepatch structures is a bit scattered and tricky: + direct calls to klp_free_*_limited() and kobject_put() are used to release partially initialized objects + klp_free_patch() removes the patch from the public list and releases all objects except for patch->kobj + object_put(&patch->kobj) and the related wait_for_completion() are called directly outside klp_mutex; this code is duplicated; Now, we are going to remove the registration stage to simplify the API and the code. This would require handling more situations in klp_enable_patch() error paths. More importantly, we are going to add a feature called atomic replace. It will need to dynamically create func and object structures. We will want to reuse the existing init() and free() functions. This would create even more error path scenarios. This patch implements more straightforward free functions: + checks kobj_added flag instead of @limit[*] + initializes patch->list early so that the check for empty list always works + The action(s) that has to be done outside klp_mutex are done in separate klp_free_patch_finish() function. It waits only when patch->kobj was really released via the _start() part. The patch does not change the existing behavior. [*] We need our own flag to track that the kobject was successfully added to the hierarchy. Note that kobj.state_initialized only indicates that kobject has been initialized, not whether is has been added (and needs to be removed on cleanup). Signed-off-by: Petr Mladek <pmladek@suse.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Miroslav Benes <mbenes@suse.cz> Cc: Jessica Yu <jeyu@kernel.org> Cc: Jiri Kosina <jikos@kernel.org> Cc: Jason Baron <jbaron@akamai.com> Acked-by: Miroslav Benes <mbenes@suse.cz> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/livepatch/core.c137
1 files changed, 92 insertions, 45 deletions
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 20589da35194..6f0d9095f662 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -465,17 +465,15 @@ static struct kobj_type klp_ktype_func = {
465 .sysfs_ops = &kobj_sysfs_ops, 465 .sysfs_ops = &kobj_sysfs_ops,
466}; 466};
467 467
468/* 468static void klp_free_funcs(struct klp_object *obj)
469 * Free all functions' kobjects in the array up to some limit. When limit is
470 * NULL, all kobjects are freed.
471 */
472static void klp_free_funcs_limited(struct klp_object *obj,
473 struct klp_func *limit)
474{ 469{
475 struct klp_func *func; 470 struct klp_func *func;
476 471
477 for (func = obj->funcs; func->old_name && func != limit; func++) 472 klp_for_each_func(obj, func) {
478 kobject_put(&func->kobj); 473 /* Might be called from klp_init_patch() error path. */
474 if (func->kobj_added)
475 kobject_put(&func->kobj);
476 }
479} 477}
480 478
481/* Clean up when a patched object is unloaded */ 479/* Clean up when a patched object is unloaded */
@@ -489,30 +487,60 @@ static void klp_free_object_loaded(struct klp_object *obj)
489 func->old_func = NULL; 487 func->old_func = NULL;
490} 488}
491 489
492/* 490static void klp_free_objects(struct klp_patch *patch)
493 * Free all objects' kobjects in the array up to some limit. When limit is
494 * NULL, all kobjects are freed.
495 */
496static void klp_free_objects_limited(struct klp_patch *patch,
497 struct klp_object *limit)
498{ 491{
499 struct klp_object *obj; 492 struct klp_object *obj;
500 493
501 for (obj = patch->objs; obj->funcs && obj != limit; obj++) { 494 klp_for_each_object(patch, obj) {
502 klp_free_funcs_limited(obj, NULL); 495 klp_free_funcs(obj);
503 kobject_put(&obj->kobj); 496
497 /* Might be called from klp_init_patch() error path. */
498 if (obj->kobj_added)
499 kobject_put(&obj->kobj);
504 } 500 }
505} 501}
506 502
507static void klp_free_patch(struct klp_patch *patch) 503/*
504 * This function implements the free operations that can be called safely
505 * under klp_mutex.
506 *
507 * The operation must be completed by calling klp_free_patch_finish()
508 * outside klp_mutex.
509 */
510static void klp_free_patch_start(struct klp_patch *patch)
508{ 511{
509 klp_free_objects_limited(patch, NULL);
510 if (!list_empty(&patch->list)) 512 if (!list_empty(&patch->list))
511 list_del(&patch->list); 513 list_del(&patch->list);
514
515 klp_free_objects(patch);
516}
517
518/*
519 * This function implements the free part that must be called outside
520 * klp_mutex.
521 *
522 * It must be called after klp_free_patch_start(). And it has to be
523 * the last function accessing the livepatch structures when the patch
524 * gets disabled.
525 */
526static void klp_free_patch_finish(struct klp_patch *patch)
527{
528 /*
529 * Avoid deadlock with enabled_store() sysfs callback by
530 * calling this outside klp_mutex. It is safe because
531 * this is called when the patch gets disabled and it
532 * cannot get enabled again.
533 */
534 if (patch->kobj_added) {
535 kobject_put(&patch->kobj);
536 wait_for_completion(&patch->finish);
537 }
512} 538}
513 539
514static int klp_init_func(struct klp_object *obj, struct klp_func *func) 540static int klp_init_func(struct klp_object *obj, struct klp_func *func)
515{ 541{
542 int ret;
543
516 if (!func->old_name || !func->new_func) 544 if (!func->old_name || !func->new_func)
517 return -EINVAL; 545 return -EINVAL;
518 546
@@ -528,9 +556,13 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
528 * object. If the user selects 0 for old_sympos, then 1 will be used 556 * object. If the user selects 0 for old_sympos, then 1 will be used
529 * since a unique symbol will be the first occurrence. 557 * since a unique symbol will be the first occurrence.
530 */ 558 */
531 return kobject_init_and_add(&func->kobj, &klp_ktype_func, 559 ret = kobject_init_and_add(&func->kobj, &klp_ktype_func,
532 &obj->kobj, "%s,%lu", func->old_name, 560 &obj->kobj, "%s,%lu", func->old_name,
533 func->old_sympos ? func->old_sympos : 1); 561 func->old_sympos ? func->old_sympos : 1);
562 if (!ret)
563 func->kobj_added = true;
564
565 return ret;
534} 566}
535 567
536/* Arches may override this to finish any remaining arch-specific tasks */ 568/* Arches may override this to finish any remaining arch-specific tasks */
@@ -589,9 +621,6 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
589 int ret; 621 int ret;
590 const char *name; 622 const char *name;
591 623
592 if (!obj->funcs)
593 return -EINVAL;
594
595 if (klp_is_module(obj) && strlen(obj->name) >= MODULE_NAME_LEN) 624 if (klp_is_module(obj) && strlen(obj->name) >= MODULE_NAME_LEN)
596 return -EINVAL; 625 return -EINVAL;
597 626
@@ -605,46 +634,66 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
605 &patch->kobj, "%s", name); 634 &patch->kobj, "%s", name);
606 if (ret) 635 if (ret)
607 return ret; 636 return ret;
637 obj->kobj_added = true;
608 638
609 klp_for_each_func(obj, func) { 639 klp_for_each_func(obj, func) {
610 ret = klp_init_func(obj, func); 640 ret = klp_init_func(obj, func);
611 if (ret) 641 if (ret)
612 goto free; 642 return ret;
613 } 643 }
614 644
615 if (klp_is_object_loaded(obj)) { 645 if (klp_is_object_loaded(obj))
616 ret = klp_init_object_loaded(patch, obj); 646 ret = klp_init_object_loaded(patch, obj);
617 if (ret)
618 goto free;
619 }
620
621 return 0;
622 647
623free:
624 klp_free_funcs_limited(obj, func);
625 kobject_put(&obj->kobj);
626 return ret; 648 return ret;
627} 649}
628 650
629static int klp_init_patch(struct klp_patch *patch) 651static int klp_init_patch_early(struct klp_patch *patch)
630{ 652{
631 struct klp_object *obj; 653 struct klp_object *obj;
632 int ret; 654 struct klp_func *func;
633 655
634 if (!patch->objs) 656 if (!patch->objs)
635 return -EINVAL; 657 return -EINVAL;
636 658
637 mutex_lock(&klp_mutex); 659 INIT_LIST_HEAD(&patch->list);
638 660 patch->kobj_added = false;
639 patch->enabled = false; 661 patch->enabled = false;
640 init_completion(&patch->finish); 662 init_completion(&patch->finish);
641 663
664 klp_for_each_object(patch, obj) {
665 if (!obj->funcs)
666 return -EINVAL;
667
668 obj->kobj_added = false;
669
670 klp_for_each_func(obj, func)
671 func->kobj_added = false;
672 }
673
674 return 0;
675}
676
677static int klp_init_patch(struct klp_patch *patch)
678{
679 struct klp_object *obj;
680 int ret;
681
682 mutex_lock(&klp_mutex);
683
684 ret = klp_init_patch_early(patch);
685 if (ret) {
686 mutex_unlock(&klp_mutex);
687 return ret;
688 }
689
642 ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch, 690 ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch,
643 klp_root_kobj, "%s", patch->mod->name); 691 klp_root_kobj, "%s", patch->mod->name);
644 if (ret) { 692 if (ret) {
645 mutex_unlock(&klp_mutex); 693 mutex_unlock(&klp_mutex);
646 return ret; 694 return ret;
647 } 695 }
696 patch->kobj_added = true;
648 697
649 klp_for_each_object(patch, obj) { 698 klp_for_each_object(patch, obj) {
650 ret = klp_init_object(patch, obj); 699 ret = klp_init_object(patch, obj);
@@ -659,12 +708,11 @@ static int klp_init_patch(struct klp_patch *patch)
659 return 0; 708 return 0;
660 709
661free: 710free:
662 klp_free_objects_limited(patch, obj); 711 klp_free_patch_start(patch);
663 712
664 mutex_unlock(&klp_mutex); 713 mutex_unlock(&klp_mutex);
665 714
666 kobject_put(&patch->kobj); 715 klp_free_patch_finish(patch);
667 wait_for_completion(&patch->finish);
668 716
669 return ret; 717 return ret;
670} 718}
@@ -693,12 +741,11 @@ int klp_unregister_patch(struct klp_patch *patch)
693 goto err; 741 goto err;
694 } 742 }
695 743
696 klp_free_patch(patch); 744 klp_free_patch_start(patch);
697 745
698 mutex_unlock(&klp_mutex); 746 mutex_unlock(&klp_mutex);
699 747
700 kobject_put(&patch->kobj); 748 klp_free_patch_finish(patch);
701 wait_for_completion(&patch->finish);
702 749
703 return 0; 750 return 0;
704err: 751err: