File: kpatch-macros.h

package info (click to toggle)
kpatch 0.9.10-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,716 kB
  • sloc: ansic: 9,716; sh: 2,592; makefile: 260; asm: 35
file content (155 lines) | stat: -rw-r--r-- 5,337 bytes parent folder | download
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifndef __KPATCH_MACROS_H_
#define __KPATCH_MACROS_H_

#include <linux/compiler.h>
#include <linux/jiffies.h>
#include <linux/version.h>
#include "kpatch-syscall.h"

/* upstream 33def8498fdd "treewide: Convert macro and uses of __section(foo) to __section("foo")" */
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
# define __kpatch_section(section) __section(section)
#else
# define __kpatch_section(section) __section(#section)
#endif

/*
 * KPATCH_IGNORE_SECTION macro
 *
 * This macro is for ignoring sections that may change as a side effect of
 * another change or might be a non-bundlable section; that is one that does
 * not honor -ffunction-section and create a one-to-one relation from function
 * symbol to section.
 */
#define KPATCH_IGNORE_SECTION(_sec) \
	char *__UNIQUE_ID(kpatch_ignore_section_) __kpatch_section(.kpatch.ignore.sections) = _sec;

/*
 * KPATCH_IGNORE_FUNCTION macro
 *
 * This macro is for ignoring functions that may change as a side effect of a
 * change in another function.  The WARN class of macros, for example, embed
 * the line number in an instruction, which will cause the function to be
 * detected as changed when, in fact, there has been no functional change.
 */
#define KPATCH_IGNORE_FUNCTION(_fn) \
	void *__kpatch_ignore_func_##_fn __kpatch_section(.kpatch.ignore.functions) = _fn;


/* Support for livepatch callbacks */
#if IS_ENABLED(CONFIG_LIVEPATCH)
# ifdef RHEL_RELEASE_CODE
#  if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 5)
#   define HAS_LIVEPATCH_CALLBACKS
#  endif
# elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
#  define HAS_LIVEPATCH_CALLBACKS
# endif
#endif

#ifdef HAS_LIVEPATCH_CALLBACKS
# include <linux/livepatch.h>
typedef struct klp_object patch_object;
#else
# include "kpatch.h"
typedef struct kpatch_object patch_object;
#endif /* HAS_LIVEPATCH_CALLBACKS */

typedef int (*kpatch_pre_patch_call_t)(patch_object *obj);
typedef void (*kpatch_post_patch_call_t)(patch_object *obj);
typedef void (*kpatch_pre_unpatch_call_t)(patch_object *obj);
typedef void (*kpatch_post_unpatch_call_t)(patch_object *obj);

struct kpatch_pre_patch_callback {
	kpatch_pre_patch_call_t fn;
	char *objname; /* filled in by create-diff-object */
};

struct kpatch_post_patch_callback {
	kpatch_post_patch_call_t fn;
	char *objname; /* filled in by create-diff-object */
};

struct kpatch_pre_unpatch_callback {
	kpatch_pre_unpatch_call_t fn;
	char *objname; /* filled in by create-diff-object */
};

struct kpatch_post_unpatch_callback {
	kpatch_post_unpatch_call_t fn;
	char *objname; /* filled in by create-diff-object */
};


#define KPATCH_PRE_PATCH_CALLBACK(_fn) \
	static inline kpatch_pre_patch_call_t __pre_patchtest(void) { return _fn; } \
	static struct kpatch_pre_patch_callback kpatch_pre_patch_data __kpatch_section(.kpatch.callbacks.pre_patch) __used = { \
		.fn = _fn, \
		.objname = NULL \
	};
#define KPATCH_POST_PATCH_CALLBACK(_fn) \
	static inline kpatch_post_patch_call_t __post_patchtest(void) { return _fn; } \
	static struct kpatch_post_patch_callback kpatch_post_patch_data __kpatch_section(.kpatch.callbacks.post_patch) __used = { \
		.fn = _fn, \
		.objname = NULL \
	};
#define KPATCH_PRE_UNPATCH_CALLBACK(_fn) \
	static inline kpatch_pre_unpatch_call_t __pre_unpatchtest(void) { return _fn; } \
	static struct kpatch_pre_unpatch_callback kpatch_pre_unpatch_data __kpatch_section(.kpatch.callbacks.pre_unpatch) __used = { \
		.fn = _fn, \
		.objname = NULL \
	};
#define KPATCH_POST_UNPATCH_CALLBACK(_fn) \
	static inline kpatch_post_unpatch_call_t __post_unpatchtest(void) { return _fn; } \
	static struct kpatch_post_unpatch_callback kpatch_post_unpatch_data __kpatch_section(.kpatch.callbacks.post_unpatch) __used = { \
		.fn = _fn, \
		.objname = NULL \
	};

/*
 * KPATCH_FORCE_UNSAFE macro
 *
 * USE WITH EXTREME CAUTION!
 *
 * Allows patch authors to bypass the activeness safety check at patch load
 * time. Do this ONLY IF 1) the patch application will always/likely fail due
 * to the function being on the stack of at least one thread at all times and
 * 2) it is safe for both the original and patched versions of the function to
 * run concurrently.
 */
#define KPATCH_FORCE_UNSAFE(_fn) \
	void *__kpatch_force_func_##_fn __kpatch_section(.kpatch.force) = _fn;

/*
 * KPATCH_PRINTK macro
 *
 * Use this instead of calling printk to avoid unwanted compiler optimizations
 * which cause kpatch-build errors.
 *
 * The printk function is annotated with the __cold attribute, which tells gcc
 * that the function is unlikely to be called.  A side effect of this is that
 * code paths containing calls to printk might also be marked cold, leading to
 * other functions called in those code paths getting moved into .text.unlikely
 * or being uninlined.
 *
 * This macro places printk in its own code path so as not to make the
 * surrounding code path cold.
 */
#define KPATCH_PRINTK(_fmt, ...) \
({ \
	if (jiffies) \
		printk(_fmt, ## __VA_ARGS__); \
})

/*
 * KPATCH_STATIC_CALL macro
 *
 * Replace usages of static_call() with this macro, when create-diff-object
 * recommends it due to the original static call key living in a module.
 *
 * This converts the static call to a regular indirect call.
 */
#define KPATCH_STATIC_CALL(name) \
	((typeof(STATIC_CALL_TRAMP(name))*)(STATIC_CALL_KEY(name).func))

#endif /* __KPATCH_MACROS_H_ */