| .. | .. | 
|---|
|  | 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_ */ | 
|---|