aboutsummaryrefslogtreecommitdiff
path: root/include/linux/livepatch.h
blob: 95023fd8b00dd8343896524b31a31a7f1e9451a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * livepatch.h - Kernel Live Patching Core
 *
 * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
 * Copyright (C) 2014 SUSE
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _LINUX_LIVEPATCH_H_
#define _LINUX_LIVEPATCH_H_

#include <linux/module.h>
#include <linux/ftrace.h>

#if IS_ENABLED(CONFIG_LIVEPATCH)

#include <asm/livepatch.h>

enum klp_state {
	KLP_DISABLED,
	KLP_ENABLED
};

/**
 * 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
 * @old_addr:	a hint conveying at what address the old function
 *		can be found (optional, vmlinux patches only)
 * @kobj:	kobject for sysfs resources
 * @state:	tracks function-level patch application state
 * @stack_node:	list node for klp_ops func_stack list
 */
struct klp_func {
	/* external */
	const char *old_name;
	void *new_func;
	/*
	 * The old_addr field is optional and can be used to resolve
	 * duplicate symbol names in the vmlinux object.  If this
	 * information is not present, the symbol is located by name
	 * with kallsyms. If the name is not unique and old_addr is
	 * not provided, the patch application fails as there is no
	 * way to resolve the ambiguity.
	 */
	unsigned long old_addr;

	/* internal */
	struct kobject kobj;
	enum klp_state state;
	struct list_head stack_node;
};

/**
 * struct klp_reloc - relocation structure for live patching
 * @loc:	address where the relocation will be written
 * @val:	address of the referenced symbol (optional,
 *		vmlinux	patches only)
 * @type:	ELF relocation type
 * @name:	name of the referenced symbol (for lookup/verification)
 * @addend:	offset from the referenced symbol
 * @external:	symbol is either exported or within the live patch module itself
 */
struct klp_reloc {
	unsigned long loc;
	unsigned long val;
	unsigned long type;
	const char *name;
	int addend;
	int external;
};

/**
 * struct klp_object - kernel object structure for live patching
 * @name:	module name (or NULL for vmlinux)
 * @relocs:	relocation entries to be applied at load time
 * @funcs:	function entries for functions to be patched in the object
 * @kobj:	kobject for sysfs resources
 * @mod:	kernel module associated with the patched object
 * 		(NULL for vmlinux)
 * @state:	tracks object-level patch application state
 */
struct klp_object {
	/* external */
	const char *name;
	struct klp_reloc *relocs;
	struct klp_func *funcs;

	/* internal */
	struct kobject *kobj;
	struct module *mod;
	enum klp_state state;
};

/**
 * struct klp_patch - patch structure for live patching
 * @mod:	reference to the live patch module
 * @objs:	object entries for kernel objects to be patched
 * @list:	list node for global list of registered patches
 * @kobj:	kobject for sysfs resources
 * @state:	tracks patch-level application state
 */
struct klp_patch {
	/* external */
	struct module *mod;
	struct klp_object *objs;

	/* internal */
	struct list_head list;
	struct kobject kobj;
	enum klp_state state;
};

extern int klp_register_patch(struct klp_patch *);
extern int klp_unregister_patch(struct klp_patch *);
extern int klp_enable_patch(struct klp_patch *);
extern int klp_disable_patch(struct klp_patch *);

#endif /* CONFIG_LIVEPATCH */

#endif /* _LINUX_LIVEPATCH_H_ */