diff options
Diffstat (limited to 'kernel/livepatch/core.c')
-rw-r--r-- | kernel/livepatch/core.c | 80 |
1 files changed, 50 insertions, 30 deletions
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 3dc3c9049690..6844c1213df8 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/livepatch.h> | 29 | #include <linux/livepatch.h> |
30 | #include <linux/elf.h> | 30 | #include <linux/elf.h> |
31 | #include <linux/moduleloader.h> | 31 | #include <linux/moduleloader.h> |
32 | #include <linux/completion.h> | ||
32 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
33 | #include "patch.h" | 34 | #include "patch.h" |
34 | #include "transition.h" | 35 | #include "transition.h" |
@@ -354,6 +355,18 @@ static int __klp_enable_patch(struct klp_patch *patch) | |||
354 | !list_prev_entry(patch, list)->enabled) | 355 | !list_prev_entry(patch, list)->enabled) |
355 | return -EBUSY; | 356 | return -EBUSY; |
356 | 357 | ||
358 | /* | ||
359 | * A reference is taken on the patch module to prevent it from being | ||
360 | * unloaded. | ||
361 | * | ||
362 | * Note: For immediate (no consistency model) patches we don't allow | ||
363 | * patch modules to unload since there is no safe/sane method to | ||
364 | * determine if a thread is still running in the patched code contained | ||
365 | * in the patch module once the ftrace registration is successful. | ||
366 | */ | ||
367 | if (!try_module_get(patch->mod)) | ||
368 | return -ENODEV; | ||
369 | |||
357 | pr_notice("enabling patch '%s'\n", patch->mod->name); | 370 | pr_notice("enabling patch '%s'\n", patch->mod->name); |
358 | 371 | ||
359 | klp_init_transition(patch, KLP_PATCHED); | 372 | klp_init_transition(patch, KLP_PATCHED); |
@@ -442,6 +455,15 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr, | |||
442 | 455 | ||
443 | mutex_lock(&klp_mutex); | 456 | mutex_lock(&klp_mutex); |
444 | 457 | ||
458 | if (!klp_is_patch_registered(patch)) { | ||
459 | /* | ||
460 | * Module with the patch could either disappear meanwhile or is | ||
461 | * not properly initialized yet. | ||
462 | */ | ||
463 | ret = -EINVAL; | ||
464 | goto err; | ||
465 | } | ||
466 | |||
445 | if (patch->enabled == enabled) { | 467 | if (patch->enabled == enabled) { |
446 | /* already in requested state */ | 468 | /* already in requested state */ |
447 | ret = -EINVAL; | 469 | ret = -EINVAL; |
@@ -498,10 +520,10 @@ static struct attribute *klp_patch_attrs[] = { | |||
498 | 520 | ||
499 | static void klp_kobj_release_patch(struct kobject *kobj) | 521 | static void klp_kobj_release_patch(struct kobject *kobj) |
500 | { | 522 | { |
501 | /* | 523 | struct klp_patch *patch; |
502 | * Once we have a consistency model we'll need to module_put() the | 524 | |
503 | * patch module here. See klp_register_patch() for more details. | 525 | patch = container_of(kobj, struct klp_patch, kobj); |
504 | */ | 526 | complete(&patch->finish); |
505 | } | 527 | } |
506 | 528 | ||
507 | static struct kobj_type klp_ktype_patch = { | 529 | static struct kobj_type klp_ktype_patch = { |
@@ -572,7 +594,6 @@ static void klp_free_patch(struct klp_patch *patch) | |||
572 | klp_free_objects_limited(patch, NULL); | 594 | klp_free_objects_limited(patch, NULL); |
573 | if (!list_empty(&patch->list)) | 595 | if (!list_empty(&patch->list)) |
574 | list_del(&patch->list); | 596 | list_del(&patch->list); |
575 | kobject_put(&patch->kobj); | ||
576 | } | 597 | } |
577 | 598 | ||
578 | static int klp_init_func(struct klp_object *obj, struct klp_func *func) | 599 | static int klp_init_func(struct klp_object *obj, struct klp_func *func) |
@@ -695,11 +716,14 @@ static int klp_init_patch(struct klp_patch *patch) | |||
695 | mutex_lock(&klp_mutex); | 716 | mutex_lock(&klp_mutex); |
696 | 717 | ||
697 | patch->enabled = false; | 718 | patch->enabled = false; |
719 | init_completion(&patch->finish); | ||
698 | 720 | ||
699 | ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch, | 721 | ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch, |
700 | klp_root_kobj, "%s", patch->mod->name); | 722 | klp_root_kobj, "%s", patch->mod->name); |
701 | if (ret) | 723 | if (ret) { |
702 | goto unlock; | 724 | mutex_unlock(&klp_mutex); |
725 | return ret; | ||
726 | } | ||
703 | 727 | ||
704 | klp_for_each_object(patch, obj) { | 728 | klp_for_each_object(patch, obj) { |
705 | ret = klp_init_object(patch, obj); | 729 | ret = klp_init_object(patch, obj); |
@@ -715,9 +739,12 @@ static int klp_init_patch(struct klp_patch *patch) | |||
715 | 739 | ||
716 | free: | 740 | free: |
717 | klp_free_objects_limited(patch, obj); | 741 | klp_free_objects_limited(patch, obj); |
718 | kobject_put(&patch->kobj); | 742 | |
719 | unlock: | ||
720 | mutex_unlock(&klp_mutex); | 743 | mutex_unlock(&klp_mutex); |
744 | |||
745 | kobject_put(&patch->kobj); | ||
746 | wait_for_completion(&patch->finish); | ||
747 | |||
721 | return ret; | 748 | return ret; |
722 | } | 749 | } |
723 | 750 | ||
@@ -731,23 +758,29 @@ unlock: | |||
731 | */ | 758 | */ |
732 | int klp_unregister_patch(struct klp_patch *patch) | 759 | int klp_unregister_patch(struct klp_patch *patch) |
733 | { | 760 | { |
734 | int ret = 0; | 761 | int ret; |
735 | 762 | ||
736 | mutex_lock(&klp_mutex); | 763 | mutex_lock(&klp_mutex); |
737 | 764 | ||
738 | if (!klp_is_patch_registered(patch)) { | 765 | if (!klp_is_patch_registered(patch)) { |
739 | ret = -EINVAL; | 766 | ret = -EINVAL; |
740 | goto out; | 767 | goto err; |
741 | } | 768 | } |
742 | 769 | ||
743 | if (patch->enabled) { | 770 | if (patch->enabled) { |
744 | ret = -EBUSY; | 771 | ret = -EBUSY; |
745 | goto out; | 772 | goto err; |
746 | } | 773 | } |
747 | 774 | ||
748 | klp_free_patch(patch); | 775 | klp_free_patch(patch); |
749 | 776 | ||
750 | out: | 777 | mutex_unlock(&klp_mutex); |
778 | |||
779 | kobject_put(&patch->kobj); | ||
780 | wait_for_completion(&patch->finish); | ||
781 | |||
782 | return 0; | ||
783 | err: | ||
751 | mutex_unlock(&klp_mutex); | 784 | mutex_unlock(&klp_mutex); |
752 | return ret; | 785 | return ret; |
753 | } | 786 | } |
@@ -760,12 +793,13 @@ EXPORT_SYMBOL_GPL(klp_unregister_patch); | |||
760 | * Initializes the data structure associated with the patch and | 793 | * Initializes the data structure associated with the patch and |
761 | * creates the sysfs interface. | 794 | * creates the sysfs interface. |
762 | * | 795 | * |
796 | * There is no need to take the reference on the patch module here. It is done | ||
797 | * later when the patch is enabled. | ||
798 | * | ||
763 | * Return: 0 on success, otherwise error | 799 | * Return: 0 on success, otherwise error |
764 | */ | 800 | */ |
765 | int klp_register_patch(struct klp_patch *patch) | 801 | int klp_register_patch(struct klp_patch *patch) |
766 | { | 802 | { |
767 | int ret; | ||
768 | |||
769 | if (!patch || !patch->mod) | 803 | if (!patch || !patch->mod) |
770 | return -EINVAL; | 804 | return -EINVAL; |
771 | 805 | ||
@@ -788,21 +822,7 @@ int klp_register_patch(struct klp_patch *patch) | |||
788 | return -ENOSYS; | 822 | return -ENOSYS; |
789 | } | 823 | } |
790 | 824 | ||
791 | /* | 825 | return klp_init_patch(patch); |
792 | * A reference is taken on the patch module to prevent it from being | ||
793 | * unloaded. Right now, we don't allow patch modules to unload since | ||
794 | * there is currently no method to determine if a thread is still | ||
795 | * running in the patched code contained in the patch module once | ||
796 | * the ftrace registration is successful. | ||
797 | */ | ||
798 | if (!try_module_get(patch->mod)) | ||
799 | return -ENODEV; | ||
800 | |||
801 | ret = klp_init_patch(patch); | ||
802 | if (ret) | ||
803 | module_put(patch->mod); | ||
804 | |||
805 | return ret; | ||
806 | } | 826 | } |
807 | EXPORT_SYMBOL_GPL(klp_register_patch); | 827 | EXPORT_SYMBOL_GPL(klp_register_patch); |
808 | 828 | ||