.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
---|
1 | 2 | /* |
---|
2 | 3 | * livepatch.h - Kernel Live Patching Core |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com> |
---|
5 | 6 | * Copyright (C) 2014 SUSE |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation; either version 2 |
---|
10 | | - * of the License, or (at your option) any later version. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, |
---|
13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | | - * GNU General Public License for more details. |
---|
16 | | - * |
---|
17 | | - * You should have received a copy of the GNU General Public License |
---|
18 | | - * along with this program; if not, see <http://www.gnu.org/licenses/>. |
---|
19 | 7 | */ |
---|
20 | 8 | |
---|
21 | 9 | #ifndef _LINUX_LIVEPATCH_H_ |
---|
.. | .. |
---|
24 | 12 | #include <linux/module.h> |
---|
25 | 13 | #include <linux/ftrace.h> |
---|
26 | 14 | #include <linux/completion.h> |
---|
| 15 | +#include <linux/list.h> |
---|
27 | 16 | |
---|
28 | 17 | #if IS_ENABLED(CONFIG_LIVEPATCH) |
---|
29 | 18 | |
---|
.. | .. |
---|
40 | 29 | * @new_func: pointer to the patched function code |
---|
41 | 30 | * @old_sympos: a hint indicating which symbol position the old function |
---|
42 | 31 | * can be found (optional) |
---|
43 | | - * @old_addr: the address of the function being patched |
---|
| 32 | + * @old_func: pointer to the function being patched |
---|
44 | 33 | * @kobj: kobject for sysfs resources |
---|
| 34 | + * @node: list node for klp_object func_list |
---|
45 | 35 | * @stack_node: list node for klp_ops func_stack list |
---|
46 | 36 | * @old_size: size of the old function |
---|
47 | 37 | * @new_size: size of the new function |
---|
| 38 | + * @nop: temporary patch to use the original code again; dyn. allocated |
---|
48 | 39 | * @patched: the func has been added to the klp_ops list |
---|
49 | 40 | * @transition: the func is currently being applied or reverted |
---|
50 | 41 | * |
---|
.. | .. |
---|
77 | 68 | unsigned long old_sympos; |
---|
78 | 69 | |
---|
79 | 70 | /* internal */ |
---|
80 | | - unsigned long old_addr; |
---|
| 71 | + void *old_func; |
---|
81 | 72 | struct kobject kobj; |
---|
| 73 | + struct list_head node; |
---|
82 | 74 | struct list_head stack_node; |
---|
83 | 75 | unsigned long old_size, new_size; |
---|
| 76 | + bool nop; |
---|
84 | 77 | bool patched; |
---|
85 | 78 | bool transition; |
---|
86 | 79 | }; |
---|
.. | .. |
---|
115 | 108 | * @funcs: function entries for functions to be patched in the object |
---|
116 | 109 | * @callbacks: functions to be executed pre/post (un)patching |
---|
117 | 110 | * @kobj: kobject for sysfs resources |
---|
| 111 | + * @func_list: dynamic list of the function entries |
---|
| 112 | + * @node: list node for klp_patch obj_list |
---|
118 | 113 | * @mod: kernel module associated with the patched object |
---|
119 | 114 | * (NULL for vmlinux) |
---|
| 115 | + * @dynamic: temporary object for nop functions; dynamically allocated |
---|
120 | 116 | * @patched: the object's funcs have been added to the klp_ops list |
---|
121 | 117 | */ |
---|
122 | 118 | struct klp_object { |
---|
.. | .. |
---|
127 | 123 | |
---|
128 | 124 | /* internal */ |
---|
129 | 125 | struct kobject kobj; |
---|
| 126 | + struct list_head func_list; |
---|
| 127 | + struct list_head node; |
---|
130 | 128 | struct module *mod; |
---|
| 129 | + bool dynamic; |
---|
131 | 130 | bool patched; |
---|
| 131 | +}; |
---|
| 132 | + |
---|
| 133 | +/** |
---|
| 134 | + * struct klp_state - state of the system modified by the livepatch |
---|
| 135 | + * @id: system state identifier (non-zero) |
---|
| 136 | + * @version: version of the change |
---|
| 137 | + * @data: custom data |
---|
| 138 | + */ |
---|
| 139 | +struct klp_state { |
---|
| 140 | + unsigned long id; |
---|
| 141 | + unsigned int version; |
---|
| 142 | + void *data; |
---|
132 | 143 | }; |
---|
133 | 144 | |
---|
134 | 145 | /** |
---|
135 | 146 | * struct klp_patch - patch structure for live patching |
---|
136 | 147 | * @mod: reference to the live patch module |
---|
137 | 148 | * @objs: object entries for kernel objects to be patched |
---|
138 | | - * @list: list node for global list of registered patches |
---|
| 149 | + * @states: system states that can get modified |
---|
| 150 | + * @replace: replace all actively used patches |
---|
| 151 | + * @list: list node for global list of actively used patches |
---|
139 | 152 | * @kobj: kobject for sysfs resources |
---|
| 153 | + * @obj_list: dynamic list of the object entries |
---|
140 | 154 | * @enabled: the patch is enabled (but operation may be incomplete) |
---|
| 155 | + * @forced: was involved in a forced transition |
---|
| 156 | + * @free_work: patch cleanup from workqueue-context |
---|
141 | 157 | * @finish: for waiting till it is safe to remove the patch module |
---|
142 | 158 | */ |
---|
143 | 159 | struct klp_patch { |
---|
144 | 160 | /* external */ |
---|
145 | 161 | struct module *mod; |
---|
146 | 162 | struct klp_object *objs; |
---|
| 163 | + struct klp_state *states; |
---|
| 164 | + bool replace; |
---|
147 | 165 | |
---|
148 | 166 | /* internal */ |
---|
149 | 167 | struct list_head list; |
---|
150 | 168 | struct kobject kobj; |
---|
| 169 | + struct list_head obj_list; |
---|
151 | 170 | bool enabled; |
---|
| 171 | + bool forced; |
---|
| 172 | + struct work_struct free_work; |
---|
152 | 173 | struct completion finish; |
---|
153 | 174 | }; |
---|
154 | 175 | |
---|
155 | | -#define klp_for_each_object(patch, obj) \ |
---|
| 176 | +#define klp_for_each_object_static(patch, obj) \ |
---|
156 | 177 | for (obj = patch->objs; obj->funcs || obj->name; obj++) |
---|
157 | 178 | |
---|
158 | | -#define klp_for_each_func(obj, func) \ |
---|
| 179 | +#define klp_for_each_object_safe(patch, obj, tmp_obj) \ |
---|
| 180 | + list_for_each_entry_safe(obj, tmp_obj, &patch->obj_list, node) |
---|
| 181 | + |
---|
| 182 | +#define klp_for_each_object(patch, obj) \ |
---|
| 183 | + list_for_each_entry(obj, &patch->obj_list, node) |
---|
| 184 | + |
---|
| 185 | +#define klp_for_each_func_static(obj, func) \ |
---|
159 | 186 | for (func = obj->funcs; \ |
---|
160 | 187 | func->old_name || func->new_func || func->old_sympos; \ |
---|
161 | 188 | func++) |
---|
162 | 189 | |
---|
163 | | -int klp_register_patch(struct klp_patch *); |
---|
164 | | -int klp_unregister_patch(struct klp_patch *); |
---|
165 | | -int klp_enable_patch(struct klp_patch *); |
---|
166 | | -int klp_disable_patch(struct klp_patch *); |
---|
| 190 | +#define klp_for_each_func_safe(obj, func, tmp_func) \ |
---|
| 191 | + list_for_each_entry_safe(func, tmp_func, &obj->func_list, node) |
---|
167 | 192 | |
---|
168 | | -void arch_klp_init_object_loaded(struct klp_patch *patch, |
---|
169 | | - struct klp_object *obj); |
---|
| 193 | +#define klp_for_each_func(obj, func) \ |
---|
| 194 | + list_for_each_entry(func, &obj->func_list, node) |
---|
| 195 | + |
---|
| 196 | +int klp_enable_patch(struct klp_patch *); |
---|
170 | 197 | |
---|
171 | 198 | /* Called from the module loader during module coming/going states */ |
---|
172 | 199 | int klp_module_coming(struct module *mod); |
---|
.. | .. |
---|
201 | 228 | void klp_shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor); |
---|
202 | 229 | void klp_shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor); |
---|
203 | 230 | |
---|
| 231 | +struct klp_state *klp_get_state(struct klp_patch *patch, unsigned long id); |
---|
| 232 | +struct klp_state *klp_get_prev_state(unsigned long id); |
---|
| 233 | + |
---|
| 234 | +int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, |
---|
| 235 | + const char *shstrtab, const char *strtab, |
---|
| 236 | + unsigned int symindex, unsigned int secindex, |
---|
| 237 | + const char *objname); |
---|
| 238 | + |
---|
204 | 239 | #else /* !CONFIG_LIVEPATCH */ |
---|
205 | 240 | |
---|
206 | 241 | static inline int klp_module_coming(struct module *mod) { return 0; } |
---|
.. | .. |
---|
209 | 244 | static inline void klp_update_patch_state(struct task_struct *task) {} |
---|
210 | 245 | static inline void klp_copy_process(struct task_struct *child) {} |
---|
211 | 246 | |
---|
| 247 | +static inline |
---|
| 248 | +int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs, |
---|
| 249 | + const char *shstrtab, const char *strtab, |
---|
| 250 | + unsigned int symindex, unsigned int secindex, |
---|
| 251 | + const char *objname) |
---|
| 252 | +{ |
---|
| 253 | + return 0; |
---|
| 254 | +} |
---|
| 255 | + |
---|
212 | 256 | #endif /* CONFIG_LIVEPATCH */ |
---|
213 | 257 | |
---|
214 | 258 | #endif /* _LINUX_LIVEPATCH_H_ */ |
---|