aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/livepatch/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/livepatch/core.c')
-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: