aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/livepatch/core.c
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2019-05-03 09:26:24 -0400
committerJiri Kosina <jkosina@suse.cz>2019-05-03 15:11:22 -0400
commit4d141ab3416d90f87775f5dee725efdf40110a8f (patch)
tree656f94323db25996373b1bd775147f709f2cb836 /kernel/livepatch/core.c
parent31adf2308f33dcae59009019675224be0978bc70 (diff)
livepatch: Remove custom kobject state handling
kobject_init() always succeeds and sets the reference count to 1. It allows to always free the structures via kobject_put() and the related release callback. Note that the custom kobject state handling was used only because we did not know that kobject_put() can and actually should get called even when kobject_init_and_add() fails. The patch should not change the existing behavior. Suggested-by: "Tobin C. Harding" <tobin@kernel.org> Signed-off-by: Petr Mladek <pmladek@suse.com> Reviewed-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> Acked-by: Joe Lawrence <joe.lawrence@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'kernel/livepatch/core.c')
-rw-r--r--kernel/livepatch/core.c56
1 files changed, 17 insertions, 39 deletions
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 14f33ab6c583..42385f23252a 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -426,6 +426,9 @@ static void klp_free_object_dynamic(struct klp_object *obj)
426 kfree(obj); 426 kfree(obj);
427} 427}
428 428
429static struct kobj_type klp_ktype_object;
430static struct kobj_type klp_ktype_func;
431
429static struct klp_object *klp_alloc_object_dynamic(const char *name) 432static struct klp_object *klp_alloc_object_dynamic(const char *name)
430{ 433{
431 struct klp_object *obj; 434 struct klp_object *obj;
@@ -443,6 +446,7 @@ static struct klp_object *klp_alloc_object_dynamic(const char *name)
443 } 446 }
444 447
445 INIT_LIST_HEAD(&obj->func_list); 448 INIT_LIST_HEAD(&obj->func_list);
449 kobject_init(&obj->kobj, &klp_ktype_object);
446 obj->dynamic = true; 450 obj->dynamic = true;
447 451
448 return obj; 452 return obj;
@@ -471,6 +475,7 @@ static struct klp_func *klp_alloc_func_nop(struct klp_func *old_func,
471 } 475 }
472 } 476 }
473 477
478 kobject_init(&func->kobj, &klp_ktype_func);
474 /* 479 /*
475 * func->new_func is same as func->old_func. These addresses are 480 * func->new_func is same as func->old_func. These addresses are
476 * set when the object is loaded, see klp_init_object_loaded(). 481 * set when the object is loaded, see klp_init_object_loaded().
@@ -588,13 +593,7 @@ static void __klp_free_funcs(struct klp_object *obj, bool nops_only)
588 continue; 593 continue;
589 594
590 list_del(&func->node); 595 list_del(&func->node);
591 596 kobject_put(&func->kobj);
592 /* Might be called from klp_init_patch() error path. */
593 if (func->kobj_added) {
594 kobject_put(&func->kobj);
595 } else if (func->nop) {
596 klp_free_func_nop(func);
597 }
598 } 597 }
599} 598}
600 599
@@ -624,13 +623,7 @@ static void __klp_free_objects(struct klp_patch *patch, bool nops_only)
624 continue; 623 continue;
625 624
626 list_del(&obj->node); 625 list_del(&obj->node);
627 626 kobject_put(&obj->kobj);
628 /* Might be called from klp_init_patch() error path. */
629 if (obj->kobj_added) {
630 kobject_put(&obj->kobj);
631 } else if (obj->dynamic) {
632 klp_free_object_dynamic(obj);
633 }
634 } 627 }
635} 628}
636 629
@@ -675,10 +668,8 @@ static void klp_free_patch_finish(struct klp_patch *patch)
675 * this is called when the patch gets disabled and it 668 * this is called when the patch gets disabled and it
676 * cannot get enabled again. 669 * cannot get enabled again.
677 */ 670 */
678 if (patch->kobj_added) { 671 kobject_put(&patch->kobj);
679 kobject_put(&patch->kobj); 672 wait_for_completion(&patch->finish);
680 wait_for_completion(&patch->finish);
681 }
682 673
683 /* Put the module after the last access to struct klp_patch. */ 674 /* Put the module after the last access to struct klp_patch. */
684 if (!patch->forced) 675 if (!patch->forced)
@@ -700,8 +691,6 @@ static void klp_free_patch_work_fn(struct work_struct *work)
700 691
701static int klp_init_func(struct klp_object *obj, struct klp_func *func) 692static int klp_init_func(struct klp_object *obj, struct klp_func *func)
702{ 693{
703 int ret;
704
705 if (!func->old_name) 694 if (!func->old_name)
706 return -EINVAL; 695 return -EINVAL;
707 696
@@ -724,13 +713,9 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
724 * object. If the user selects 0 for old_sympos, then 1 will be used 713 * object. If the user selects 0 for old_sympos, then 1 will be used
725 * since a unique symbol will be the first occurrence. 714 * since a unique symbol will be the first occurrence.
726 */ 715 */
727 ret = kobject_init_and_add(&func->kobj, &klp_ktype_func, 716 return kobject_add(&func->kobj, &obj->kobj, "%s,%lu",
728 &obj->kobj, "%s,%lu", func->old_name, 717 func->old_name,
729 func->old_sympos ? func->old_sympos : 1); 718 func->old_sympos ? func->old_sympos : 1);
730 if (!ret)
731 func->kobj_added = true;
732
733 return ret;
734} 719}
735 720
736/* Arches may override this to finish any remaining arch-specific tasks */ 721/* Arches may override this to finish any remaining arch-specific tasks */
@@ -801,11 +786,9 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
801 klp_find_object_module(obj); 786 klp_find_object_module(obj);
802 787
803 name = klp_is_module(obj) ? obj->name : "vmlinux"; 788 name = klp_is_module(obj) ? obj->name : "vmlinux";
804 ret = kobject_init_and_add(&obj->kobj, &klp_ktype_object, 789 ret = kobject_add(&obj->kobj, &patch->kobj, "%s", name);
805 &patch->kobj, "%s", name);
806 if (ret) 790 if (ret)
807 return ret; 791 return ret;
808 obj->kobj_added = true;
809 792
810 klp_for_each_func(obj, func) { 793 klp_for_each_func(obj, func) {
811 ret = klp_init_func(obj, func); 794 ret = klp_init_func(obj, func);
@@ -829,7 +812,7 @@ static int klp_init_patch_early(struct klp_patch *patch)
829 812
830 INIT_LIST_HEAD(&patch->list); 813 INIT_LIST_HEAD(&patch->list);
831 INIT_LIST_HEAD(&patch->obj_list); 814 INIT_LIST_HEAD(&patch->obj_list);
832 patch->kobj_added = false; 815 kobject_init(&patch->kobj, &klp_ktype_patch);
833 patch->enabled = false; 816 patch->enabled = false;
834 patch->forced = false; 817 patch->forced = false;
835 INIT_WORK(&patch->free_work, klp_free_patch_work_fn); 818 INIT_WORK(&patch->free_work, klp_free_patch_work_fn);
@@ -840,11 +823,11 @@ static int klp_init_patch_early(struct klp_patch *patch)
840 return -EINVAL; 823 return -EINVAL;
841 824
842 INIT_LIST_HEAD(&obj->func_list); 825 INIT_LIST_HEAD(&obj->func_list);
843 obj->kobj_added = false; 826 kobject_init(&obj->kobj, &klp_ktype_object);
844 list_add_tail(&obj->node, &patch->obj_list); 827 list_add_tail(&obj->node, &patch->obj_list);
845 828
846 klp_for_each_func_static(obj, func) { 829 klp_for_each_func_static(obj, func) {
847 func->kobj_added = false; 830 kobject_init(&func->kobj, &klp_ktype_func);
848 list_add_tail(&func->node, &obj->func_list); 831 list_add_tail(&func->node, &obj->func_list);
849 } 832 }
850 } 833 }
@@ -860,11 +843,9 @@ static int klp_init_patch(struct klp_patch *patch)
860 struct klp_object *obj; 843 struct klp_object *obj;
861 int ret; 844 int ret;
862 845
863 ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch, 846 ret = kobject_add(&patch->kobj, klp_root_kobj, "%s", patch->mod->name);
864 klp_root_kobj, "%s", patch->mod->name);
865 if (ret) 847 if (ret)
866 return ret; 848 return ret;
867 patch->kobj_added = true;
868 849
869 if (patch->replace) { 850 if (patch->replace) {
870 ret = klp_add_nops(patch); 851 ret = klp_add_nops(patch);
@@ -926,9 +907,6 @@ static int __klp_enable_patch(struct klp_patch *patch)
926 if (WARN_ON(patch->enabled)) 907 if (WARN_ON(patch->enabled))
927 return -EINVAL; 908 return -EINVAL;
928 909
929 if (!patch->kobj_added)
930 return -EINVAL;
931
932 pr_notice("enabling patch '%s'\n", patch->mod->name); 910 pr_notice("enabling patch '%s'\n", patch->mod->name);
933 911
934 klp_init_transition(patch, KLP_PATCHED); 912 klp_init_transition(patch, KLP_PATCHED);