Blame view

include/linux/livepatch.h 8.22 KB
1ccea77e2   Thomas Gleixner   treewide: Replace...
1
  /* SPDX-License-Identifier: GPL-2.0-or-later */
b700e7f03   Seth Jennings   livepatch: kernel...
2
3
4
5
6
  /*
   * livepatch.h - Kernel Live Patching Core
   *
   * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
   * Copyright (C) 2014 SUSE
b700e7f03   Seth Jennings   livepatch: kernel...
7
8
9
10
11
12
13
   */
  
  #ifndef _LINUX_LIVEPATCH_H_
  #define _LINUX_LIVEPATCH_H_
  
  #include <linux/module.h>
  #include <linux/ftrace.h>
3ec24776b   Josh Poimboeuf   livepatch: allow ...
14
  #include <linux/completion.h>
20e550259   Jason Baron   livepatch: Use li...
15
  #include <linux/list.h>
b700e7f03   Seth Jennings   livepatch: kernel...
16

7e545d6ec   Jessica Yu   livepatch/module:...
17
  #if IS_ENABLED(CONFIG_LIVEPATCH)
b700e7f03   Seth Jennings   livepatch: kernel...
18
  #include <asm/livepatch.h>
d83a7cb37   Josh Poimboeuf   livepatch: change...
19
20
21
22
  /* task patch states */
  #define KLP_UNDEFINED	-1
  #define KLP_UNPATCHED	 0
  #define KLP_PATCHED	 1
b700e7f03   Seth Jennings   livepatch: kernel...
23
24
25
26
  /**
   * struct klp_func - function structure for live patching
   * @old_name:	name of the function to be patched
   * @new_func:	pointer to the patched function code
b2b018ef4   Chris J Arges   livepatch: add ol...
27
28
   * @old_sympos: a hint indicating which symbol position the old function
   *		can be found (optional)
19514910d   Petr Mladek   livepatch: Change...
29
   * @old_func:	pointer to the function being patched
b700e7f03   Seth Jennings   livepatch: kernel...
30
   * @kobj:	kobject for sysfs resources
20e550259   Jason Baron   livepatch: Use li...
31
   * @node:	list node for klp_object func_list
3c33f5b99   Josh Poimboeuf   livepatch: suppor...
32
   * @stack_node:	list node for klp_ops func_stack list
f5e547f4a   Josh Poimboeuf   livepatch: store ...
33
34
   * @old_size:	size of the old function
   * @new_size:	size of the new function
e1452b607   Jason Baron   livepatch: Add at...
35
   * @nop:        temporary patch to use the original code again; dyn. allocated
0dade9f37   Josh Poimboeuf   livepatch: separa...
36
   * @patched:	the func has been added to the klp_ops list
d83a7cb37   Josh Poimboeuf   livepatch: change...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
   * @transition:	the func is currently being applied or reverted
   *
   * The patched and transition variables define the func's patching state.  When
   * patching, a func is always in one of the following states:
   *
   *   patched=0 transition=0: unpatched
   *   patched=0 transition=1: unpatched, temporary starting state
   *   patched=1 transition=1: patched, may be visible to some tasks
   *   patched=1 transition=0: patched, visible to all tasks
   *
   * And when unpatching, it goes in the reverse order:
   *
   *   patched=1 transition=0: patched, visible to all tasks
   *   patched=1 transition=1: patched, may be visible to some tasks
   *   patched=0 transition=1: unpatched, temporary ending state
   *   patched=0 transition=0: unpatched
b700e7f03   Seth Jennings   livepatch: kernel...
53
54
55
56
57
58
   */
  struct klp_func {
  	/* external */
  	const char *old_name;
  	void *new_func;
  	/*
b2b018ef4   Chris J Arges   livepatch: add ol...
59
60
61
62
63
  	 * The old_sympos field is optional and can be used to resolve
  	 * duplicate symbol names in livepatch objects. If this field is zero,
  	 * it is expected the symbol is unique, otherwise patching fails. If
  	 * this value is greater than zero then that occurrence of the symbol
  	 * in kallsyms for the given object is used.
b700e7f03   Seth Jennings   livepatch: kernel...
64
  	 */
b2b018ef4   Chris J Arges   livepatch: add ol...
65
  	unsigned long old_sympos;
b700e7f03   Seth Jennings   livepatch: kernel...
66
67
  
  	/* internal */
19514910d   Petr Mladek   livepatch: Change...
68
  	void *old_func;
b700e7f03   Seth Jennings   livepatch: kernel...
69
  	struct kobject kobj;
20e550259   Jason Baron   livepatch: Use li...
70
  	struct list_head node;
3c33f5b99   Josh Poimboeuf   livepatch: suppor...
71
  	struct list_head stack_node;
f5e547f4a   Josh Poimboeuf   livepatch: store ...
72
  	unsigned long old_size, new_size;
e1452b607   Jason Baron   livepatch: Add at...
73
  	bool nop;
0dade9f37   Josh Poimboeuf   livepatch: separa...
74
  	bool patched;
d83a7cb37   Josh Poimboeuf   livepatch: change...
75
  	bool transition;
b700e7f03   Seth Jennings   livepatch: kernel...
76
  };
93862e385   Joe Lawrence   livepatch: add (u...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  struct klp_object;
  
  /**
   * struct klp_callbacks - pre/post live-(un)patch callback structure
   * @pre_patch:		executed before code patching
   * @post_patch:		executed after code patching
   * @pre_unpatch:	executed before code unpatching
   * @post_unpatch:	executed after code unpatching
   * @post_unpatch_enabled:	flag indicating if post-unpatch callback
   * 				should run
   *
   * All callbacks are optional.  Only the pre-patch callback, if provided,
   * will be unconditionally executed.  If the parent klp_object fails to
   * patch for any reason, including a non-zero error status returned from
   * the pre-patch callback, no further callbacks will be executed.
   */
  struct klp_callbacks {
  	int (*pre_patch)(struct klp_object *obj);
  	void (*post_patch)(struct klp_object *obj);
  	void (*pre_unpatch)(struct klp_object *obj);
  	void (*post_unpatch)(struct klp_object *obj);
  	bool post_unpatch_enabled;
  };
b700e7f03   Seth Jennings   livepatch: kernel...
100
  /**
b700e7f03   Seth Jennings   livepatch: kernel...
101
102
   * struct klp_object - kernel object structure for live patching
   * @name:	module name (or NULL for vmlinux)
b700e7f03   Seth Jennings   livepatch: kernel...
103
   * @funcs:	function entries for functions to be patched in the object
93862e385   Joe Lawrence   livepatch: add (u...
104
   * @callbacks:	functions to be executed pre/post (un)patching
b700e7f03   Seth Jennings   livepatch: kernel...
105
   * @kobj:	kobject for sysfs resources
20e550259   Jason Baron   livepatch: Use li...
106
107
   * @func_list:	dynamic list of the function entries
   * @node:	list node for klp_patch obj_list
b700e7f03   Seth Jennings   livepatch: kernel...
108
   * @mod:	kernel module associated with the patched object
d83a7cb37   Josh Poimboeuf   livepatch: change...
109
   *		(NULL for vmlinux)
e1452b607   Jason Baron   livepatch: Add at...
110
   * @dynamic:    temporary object for nop functions; dynamically allocated
0dade9f37   Josh Poimboeuf   livepatch: separa...
111
   * @patched:	the object's funcs have been added to the klp_ops list
b700e7f03   Seth Jennings   livepatch: kernel...
112
113
114
115
   */
  struct klp_object {
  	/* external */
  	const char *name;
b700e7f03   Seth Jennings   livepatch: kernel...
116
  	struct klp_func *funcs;
93862e385   Joe Lawrence   livepatch: add (u...
117
  	struct klp_callbacks callbacks;
b700e7f03   Seth Jennings   livepatch: kernel...
118
119
  
  	/* internal */
cad706df7   Miroslav Benes   livepatch: make k...
120
  	struct kobject kobj;
20e550259   Jason Baron   livepatch: Use li...
121
122
  	struct list_head func_list;
  	struct list_head node;
b700e7f03   Seth Jennings   livepatch: kernel...
123
  	struct module *mod;
e1452b607   Jason Baron   livepatch: Add at...
124
  	bool dynamic;
0dade9f37   Josh Poimboeuf   livepatch: separa...
125
  	bool patched;
b700e7f03   Seth Jennings   livepatch: kernel...
126
127
128
  };
  
  /**
73727f4da   Petr Mladek   livepatch: Basic ...
129
130
   * struct klp_state - state of the system modified by the livepatch
   * @id:		system state identifier (non-zero)
92c9abf5e   Petr Mladek   livepatch: Allow ...
131
   * @version:	version of the change
73727f4da   Petr Mladek   livepatch: Basic ...
132
133
134
135
   * @data:	custom data
   */
  struct klp_state {
  	unsigned long id;
92c9abf5e   Petr Mladek   livepatch: Allow ...
136
  	unsigned int version;
73727f4da   Petr Mladek   livepatch: Basic ...
137
138
139
140
  	void *data;
  };
  
  /**
b700e7f03   Seth Jennings   livepatch: kernel...
141
142
143
   * struct klp_patch - patch structure for live patching
   * @mod:	reference to the live patch module
   * @objs:	object entries for kernel objects to be patched
73727f4da   Petr Mladek   livepatch: Basic ...
144
   * @states:	system states that can get modified
e1452b607   Jason Baron   livepatch: Add at...
145
   * @replace:	replace all actively used patches
958ef1e39   Petr Mladek   livepatch: Simpli...
146
   * @list:	list node for global list of actively used patches
b700e7f03   Seth Jennings   livepatch: kernel...
147
   * @kobj:	kobject for sysfs resources
20e550259   Jason Baron   livepatch: Use li...
148
   * @obj_list:	dynamic list of the object entries
0dade9f37   Josh Poimboeuf   livepatch: separa...
149
   * @enabled:	the patch is enabled (but operation may be incomplete)
68007289b   Petr Mladek   livepatch: Don't ...
150
   * @forced:	was involved in a forced transition
958ef1e39   Petr Mladek   livepatch: Simpli...
151
   * @free_work:	patch cleanup from workqueue-context
3ec24776b   Josh Poimboeuf   livepatch: allow ...
152
   * @finish:	for waiting till it is safe to remove the patch module
b700e7f03   Seth Jennings   livepatch: kernel...
153
154
155
156
157
   */
  struct klp_patch {
  	/* external */
  	struct module *mod;
  	struct klp_object *objs;
73727f4da   Petr Mladek   livepatch: Basic ...
158
  	struct klp_state *states;
e1452b607   Jason Baron   livepatch: Add at...
159
  	bool replace;
b700e7f03   Seth Jennings   livepatch: kernel...
160
161
162
163
  
  	/* internal */
  	struct list_head list;
  	struct kobject kobj;
20e550259   Jason Baron   livepatch: Use li...
164
  	struct list_head obj_list;
0dade9f37   Josh Poimboeuf   livepatch: separa...
165
  	bool enabled;
68007289b   Petr Mladek   livepatch: Don't ...
166
  	bool forced;
958ef1e39   Petr Mladek   livepatch: Simpli...
167
  	struct work_struct free_work;
3ec24776b   Josh Poimboeuf   livepatch: allow ...
168
  	struct completion finish;
b700e7f03   Seth Jennings   livepatch: kernel...
169
  };
20e550259   Jason Baron   livepatch: Use li...
170
  #define klp_for_each_object_static(patch, obj) \
f09d90864   Miroslav Benes   livepatch: make o...
171
  	for (obj = patch->objs; obj->funcs || obj->name; obj++)
8cdd043ab   Jiri Slaby   livepatch: introd...
172

e1452b607   Jason Baron   livepatch: Add at...
173
174
  #define klp_for_each_object_safe(patch, obj, tmp_obj)		\
  	list_for_each_entry_safe(obj, tmp_obj, &patch->obj_list, node)
20e550259   Jason Baron   livepatch: Use li...
175
176
177
178
  #define klp_for_each_object(patch, obj)	\
  	list_for_each_entry(obj, &patch->obj_list, node)
  
  #define klp_for_each_func_static(obj, func) \
f09d90864   Miroslav Benes   livepatch: make o...
179
180
181
  	for (func = obj->funcs; \
  	     func->old_name || func->new_func || func->old_sympos; \
  	     func++)
8cdd043ab   Jiri Slaby   livepatch: introd...
182

e1452b607   Jason Baron   livepatch: Add at...
183
184
  #define klp_for_each_func_safe(obj, func, tmp_func)			\
  	list_for_each_entry_safe(func, tmp_func, &obj->func_list, node)
20e550259   Jason Baron   livepatch: Use li...
185
186
  #define klp_for_each_func(obj, func)	\
  	list_for_each_entry(func, &obj->func_list, node)
4421f8f0f   Miroslav Benes   livepatch: remove...
187
  int klp_enable_patch(struct klp_patch *);
b700e7f03   Seth Jennings   livepatch: kernel...
188

7e545d6ec   Jessica Yu   livepatch/module:...
189
190
191
  /* Called from the module loader during module coming/going states */
  int klp_module_coming(struct module *mod);
  void klp_module_going(struct module *mod);
d83a7cb37   Josh Poimboeuf   livepatch: change...
192
  void klp_copy_process(struct task_struct *child);
46c5a0113   Josh Poimboeuf   livepatch: create...
193
  void klp_update_patch_state(struct task_struct *task);
d83a7cb37   Josh Poimboeuf   livepatch: change...
194
195
196
197
198
199
200
201
202
203
  static inline bool klp_patch_pending(struct task_struct *task)
  {
  	return test_tsk_thread_flag(task, TIF_PATCH_PENDING);
  }
  
  static inline bool klp_have_reliable_stack(void)
  {
  	return IS_ENABLED(CONFIG_STACKTRACE) &&
  	       IS_ENABLED(CONFIG_HAVE_RELIABLE_STACKTRACE);
  }
e91c2518a   Petr Mladek   livepatch: Initia...
204
205
206
  typedef int (*klp_shadow_ctor_t)(void *obj,
  				 void *shadow_data,
  				 void *ctor_data);
3b2c77d00   Petr Mladek   livepatch: Allow ...
207
  typedef void (*klp_shadow_dtor_t)(void *obj, void *shadow_data);
e91c2518a   Petr Mladek   livepatch: Initia...
208

439e7271d   Joe Lawrence   livepatch: introd...
209
  void *klp_shadow_get(void *obj, unsigned long id);
e91c2518a   Petr Mladek   livepatch: Initia...
210
211
212
213
214
215
  void *klp_shadow_alloc(void *obj, unsigned long id,
  		       size_t size, gfp_t gfp_flags,
  		       klp_shadow_ctor_t ctor, void *ctor_data);
  void *klp_shadow_get_or_alloc(void *obj, unsigned long id,
  			      size_t size, gfp_t gfp_flags,
  			      klp_shadow_ctor_t ctor, void *ctor_data);
3b2c77d00   Petr Mladek   livepatch: Allow ...
216
217
  void klp_shadow_free(void *obj, unsigned long id, klp_shadow_dtor_t dtor);
  void klp_shadow_free_all(unsigned long id, klp_shadow_dtor_t dtor);
439e7271d   Joe Lawrence   livepatch: introd...
218

73727f4da   Petr Mladek   livepatch: Basic ...
219
220
  struct klp_state *klp_get_state(struct klp_patch *patch, unsigned long id);
  struct klp_state *klp_get_prev_state(unsigned long id);
7c8e2bdd5   Josh Poimboeuf   livepatch: Apply ...
221
222
223
224
  int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
  			     const char *shstrtab, const char *strtab,
  			     unsigned int symindex, unsigned int secindex,
  			     const char *objname);
7e545d6ec   Jessica Yu   livepatch/module:...
225
226
227
  #else /* !CONFIG_LIVEPATCH */
  
  static inline int klp_module_coming(struct module *mod) { return 0; }
46c5a0113   Josh Poimboeuf   livepatch: create...
228
  static inline void klp_module_going(struct module *mod) {}
d83a7cb37   Josh Poimboeuf   livepatch: change...
229
  static inline bool klp_patch_pending(struct task_struct *task) { return false; }
46c5a0113   Josh Poimboeuf   livepatch: create...
230
  static inline void klp_update_patch_state(struct task_struct *task) {}
d83a7cb37   Josh Poimboeuf   livepatch: change...
231
  static inline void klp_copy_process(struct task_struct *child) {}
7e545d6ec   Jessica Yu   livepatch/module:...
232

7c8e2bdd5   Josh Poimboeuf   livepatch: Apply ...
233
234
235
236
237
238
239
240
  static inline
  int klp_apply_section_relocs(struct module *pmod, Elf_Shdr *sechdrs,
  			     const char *shstrtab, const char *strtab,
  			     unsigned int symindex, unsigned int secindex,
  			     const char *objname)
  {
  	return 0;
  }
7e545d6ec   Jessica Yu   livepatch/module:...
241
  #endif /* CONFIG_LIVEPATCH */
b700e7f03   Seth Jennings   livepatch: kernel...
242
  #endif /* _LINUX_LIVEPATCH_H_ */