0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/livepatch.h>
0011 #include "core.h"
0012 #include "state.h"
0013 #include "transition.h"
0014
0015 #define klp_for_each_state(patch, state) \
0016 for (state = patch->states; state && state->id; state++)
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 struct klp_state *klp_get_state(struct klp_patch *patch, unsigned long id)
0032 {
0033 struct klp_state *state;
0034
0035 klp_for_each_state(patch, state) {
0036 if (state->id == id)
0037 return state;
0038 }
0039
0040 return NULL;
0041 }
0042 EXPORT_SYMBOL_GPL(klp_get_state);
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 struct klp_state *klp_get_prev_state(unsigned long id)
0065 {
0066 struct klp_patch *patch;
0067 struct klp_state *state, *last_state = NULL;
0068
0069 if (WARN_ON_ONCE(!klp_transition_patch))
0070 return NULL;
0071
0072 klp_for_each_patch(patch) {
0073 if (patch == klp_transition_patch)
0074 goto out;
0075
0076 state = klp_get_state(patch, id);
0077 if (state)
0078 last_state = state;
0079 }
0080
0081 out:
0082 return last_state;
0083 }
0084 EXPORT_SYMBOL_GPL(klp_get_prev_state);
0085
0086
0087 static bool klp_is_state_compatible(struct klp_patch *patch,
0088 struct klp_state *old_state)
0089 {
0090 struct klp_state *state;
0091
0092 state = klp_get_state(patch, old_state->id);
0093
0094
0095 if (!state)
0096 return !patch->replace;
0097
0098 return state->version >= old_state->version;
0099 }
0100
0101
0102
0103
0104
0105
0106 bool klp_is_patch_compatible(struct klp_patch *patch)
0107 {
0108 struct klp_patch *old_patch;
0109 struct klp_state *old_state;
0110
0111 klp_for_each_patch(old_patch) {
0112 klp_for_each_state(old_patch, old_state) {
0113 if (!klp_is_state_compatible(patch, old_state))
0114 return false;
0115 }
0116 }
0117
0118 return true;
0119 }