diff options
author | David S. Miller <davem@davemloft.net> | 2017-10-22 08:36:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-10-22 08:39:14 -0400 |
commit | f8ddadc4db6c7b7029b6d0e0d9af24f74ad27ca2 (patch) | |
tree | 0a6432aba336bae42313613f4c891bcfce02bd4e /kernel/livepatch/core.c | |
parent | bdd091bab8c631bd2801af838e344fad34566410 (diff) | |
parent | b5ac3beb5a9f0ef0ea64cd85faf94c0dc4de0e42 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
There were quite a few overlapping sets of changes here.
Daniel's bug fix for off-by-ones in the new BPF branch instructions,
along with the added allowances for "data_end > ptr + x" forms
collided with the metadata additions.
Along with those three changes came veritifer test cases, which in
their final form I tried to group together properly. If I had just
trimmed GIT's conflict tags as-is, this would have split up the
meta tests unnecessarily.
In the socketmap code, a set of preemption disabling changes
overlapped with the rename of bpf_compute_data_end() to
bpf_compute_data_pointers().
Changes were made to the mv88e6060.c driver set addr method
which got removed in net-next.
The hyperv transport socket layer had a locking change in 'net'
which overlapped with a change of socket state macro usage
in 'net-next'.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/livepatch/core.c')
-rw-r--r-- | kernel/livepatch/core.c | 60 |
1 files changed, 37 insertions, 23 deletions
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index b9628e43c78f..bf8c8fd72589 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c | |||
@@ -830,6 +830,41 @@ int klp_register_patch(struct klp_patch *patch) | |||
830 | } | 830 | } |
831 | EXPORT_SYMBOL_GPL(klp_register_patch); | 831 | EXPORT_SYMBOL_GPL(klp_register_patch); |
832 | 832 | ||
833 | /* | ||
834 | * Remove parts of patches that touch a given kernel module. The list of | ||
835 | * patches processed might be limited. When limit is NULL, all patches | ||
836 | * will be handled. | ||
837 | */ | ||
838 | static void klp_cleanup_module_patches_limited(struct module *mod, | ||
839 | struct klp_patch *limit) | ||
840 | { | ||
841 | struct klp_patch *patch; | ||
842 | struct klp_object *obj; | ||
843 | |||
844 | list_for_each_entry(patch, &klp_patches, list) { | ||
845 | if (patch == limit) | ||
846 | break; | ||
847 | |||
848 | klp_for_each_object(patch, obj) { | ||
849 | if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) | ||
850 | continue; | ||
851 | |||
852 | /* | ||
853 | * Only unpatch the module if the patch is enabled or | ||
854 | * is in transition. | ||
855 | */ | ||
856 | if (patch->enabled || patch == klp_transition_patch) { | ||
857 | pr_notice("reverting patch '%s' on unloading module '%s'\n", | ||
858 | patch->mod->name, obj->mod->name); | ||
859 | klp_unpatch_object(obj); | ||
860 | } | ||
861 | |||
862 | klp_free_object_loaded(obj); | ||
863 | break; | ||
864 | } | ||
865 | } | ||
866 | } | ||
867 | |||
833 | int klp_module_coming(struct module *mod) | 868 | int klp_module_coming(struct module *mod) |
834 | { | 869 | { |
835 | int ret; | 870 | int ret; |
@@ -894,7 +929,7 @@ err: | |||
894 | pr_warn("patch '%s' failed for module '%s', refusing to load module '%s'\n", | 929 | pr_warn("patch '%s' failed for module '%s', refusing to load module '%s'\n", |
895 | patch->mod->name, obj->mod->name, obj->mod->name); | 930 | patch->mod->name, obj->mod->name, obj->mod->name); |
896 | mod->klp_alive = false; | 931 | mod->klp_alive = false; |
897 | klp_free_object_loaded(obj); | 932 | klp_cleanup_module_patches_limited(mod, patch); |
898 | mutex_unlock(&klp_mutex); | 933 | mutex_unlock(&klp_mutex); |
899 | 934 | ||
900 | return ret; | 935 | return ret; |
@@ -902,9 +937,6 @@ err: | |||
902 | 937 | ||
903 | void klp_module_going(struct module *mod) | 938 | void klp_module_going(struct module *mod) |
904 | { | 939 | { |
905 | struct klp_patch *patch; | ||
906 | struct klp_object *obj; | ||
907 | |||
908 | if (WARN_ON(mod->state != MODULE_STATE_GOING && | 940 | if (WARN_ON(mod->state != MODULE_STATE_GOING && |
909 | mod->state != MODULE_STATE_COMING)) | 941 | mod->state != MODULE_STATE_COMING)) |
910 | return; | 942 | return; |
@@ -917,25 +949,7 @@ void klp_module_going(struct module *mod) | |||
917 | */ | 949 | */ |
918 | mod->klp_alive = false; | 950 | mod->klp_alive = false; |
919 | 951 | ||
920 | list_for_each_entry(patch, &klp_patches, list) { | 952 | klp_cleanup_module_patches_limited(mod, NULL); |
921 | klp_for_each_object(patch, obj) { | ||
922 | if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) | ||
923 | continue; | ||
924 | |||
925 | /* | ||
926 | * Only unpatch the module if the patch is enabled or | ||
927 | * is in transition. | ||
928 | */ | ||
929 | if (patch->enabled || patch == klp_transition_patch) { | ||
930 | pr_notice("reverting patch '%s' on unloading module '%s'\n", | ||
931 | patch->mod->name, obj->mod->name); | ||
932 | klp_unpatch_object(obj); | ||
933 | } | ||
934 | |||
935 | klp_free_object_loaded(obj); | ||
936 | break; | ||
937 | } | ||
938 | } | ||
939 | 953 | ||
940 | mutex_unlock(&klp_mutex); | 954 | mutex_unlock(&klp_mutex); |
941 | } | 955 | } |