Skip to content

Commit 0ef7687

Browse files
committed
Merge branch 'for-linus' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching
Pull livepatching updates from Jiri Kosina: - shadow variables support, allowing livepatches to associate new "shadow" fields to existing data structures, from Joe Lawrence - pre/post patch callbacks API, allowing livepatch writers to register callbacks to be called before and after patch application, from Joe Lawrence * 'for-linus' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching: livepatch: __klp_disable_patch() should never be called for disabled patches livepatch: Correctly call klp_post_unpatch_callback() in error paths livepatch: add transition notices livepatch: move transition "complete" notice into klp_complete_transition() livepatch: add (un)patch callbacks livepatch: Small shadow variable documentation fixes livepatch: __klp_shadow_get_or_alloc() is local to shadow.c livepatch: introduce shadow variable API
2 parents 9682b3d + fc41efc commit 0ef7687

17 files changed

+2162
-21
lines changed

Documentation/livepatch/callbacks.txt

Lines changed: 605 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
================
2+
Shadow Variables
3+
================
4+
5+
Shadow variables are a simple way for livepatch modules to associate
6+
additional "shadow" data with existing data structures. Shadow data is
7+
allocated separately from parent data structures, which are left
8+
unmodified. The shadow variable API described in this document is used
9+
to allocate/add and remove/free shadow variables to/from their parents.
10+
11+
The implementation introduces a global, in-kernel hashtable that
12+
associates pointers to parent objects and a numeric identifier of the
13+
shadow data. The numeric identifier is a simple enumeration that may be
14+
used to describe shadow variable version, class or type, etc. More
15+
specifically, the parent pointer serves as the hashtable key while the
16+
numeric id subsequently filters hashtable queries. Multiple shadow
17+
variables may attach to the same parent object, but their numeric
18+
identifier distinguishes between them.
19+
20+
21+
1. Brief API summary
22+
====================
23+
24+
(See the full API usage docbook notes in livepatch/shadow.c.)
25+
26+
A hashtable references all shadow variables. These references are
27+
stored and retrieved through a <obj, id> pair.
28+
29+
* The klp_shadow variable data structure encapsulates both tracking
30+
meta-data and shadow-data:
31+
- meta-data
32+
- obj - pointer to parent object
33+
- id - data identifier
34+
- data[] - storage for shadow data
35+
36+
It is important to note that the klp_shadow_alloc() and
37+
klp_shadow_get_or_alloc() calls, described below, store a *copy* of the
38+
data that the functions are provided. Callers should provide whatever
39+
mutual exclusion is required of the shadow data.
40+
41+
* klp_shadow_get() - retrieve a shadow variable data pointer
42+
- search hashtable for <obj, id> pair
43+
44+
* klp_shadow_alloc() - allocate and add a new shadow variable
45+
- search hashtable for <obj, id> pair
46+
- if exists
47+
- WARN and return NULL
48+
- if <obj, id> doesn't already exist
49+
- allocate a new shadow variable
50+
- copy data into the new shadow variable
51+
- add <obj, id> to the global hashtable
52+
53+
* klp_shadow_get_or_alloc() - get existing or alloc a new shadow variable
54+
- search hashtable for <obj, id> pair
55+
- if exists
56+
- return existing shadow variable
57+
- if <obj, id> doesn't already exist
58+
- allocate a new shadow variable
59+
- copy data into the new shadow variable
60+
- add <obj, id> pair to the global hashtable
61+
62+
* klp_shadow_free() - detach and free a <obj, id> shadow variable
63+
- find and remove a <obj, id> reference from global hashtable
64+
- if found, free shadow variable
65+
66+
* klp_shadow_free_all() - detach and free all <*, id> shadow variables
67+
- find and remove any <*, id> references from global hashtable
68+
- if found, free shadow variable
69+
70+
71+
2. Use cases
72+
============
73+
74+
(See the example shadow variable livepatch modules in samples/livepatch/
75+
for full working demonstrations.)
76+
77+
For the following use-case examples, consider commit 1d147bfa6429
78+
("mac80211: fix AP powersave TX vs. wakeup race"), which added a
79+
spinlock to net/mac80211/sta_info.h :: struct sta_info. Each use-case
80+
example can be considered a stand-alone livepatch implementation of this
81+
fix.
82+
83+
84+
Matching parent's lifecycle
85+
---------------------------
86+
87+
If parent data structures are frequently created and destroyed, it may
88+
be easiest to align their shadow variables lifetimes to the same
89+
allocation and release functions. In this case, the parent data
90+
structure is typically allocated, initialized, then registered in some
91+
manner. Shadow variable allocation and setup can then be considered
92+
part of the parent's initialization and should be completed before the
93+
parent "goes live" (ie, any shadow variable get-API requests are made
94+
for this <obj, id> pair.)
95+
96+
For commit 1d147bfa6429, when a parent sta_info structure is allocated,
97+
allocate a shadow copy of the ps_lock pointer, then initialize it:
98+
99+
#define PS_LOCK 1
100+
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
101+
const u8 *addr, gfp_t gfp)
102+
{
103+
struct sta_info *sta;
104+
spinlock_t *ps_lock;
105+
106+
/* Parent structure is created */
107+
sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
108+
109+
/* Attach a corresponding shadow variable, then initialize it */
110+
ps_lock = klp_shadow_alloc(sta, PS_LOCK, NULL, sizeof(*ps_lock), gfp);
111+
if (!ps_lock)
112+
goto shadow_fail;
113+
spin_lock_init(ps_lock);
114+
...
115+
116+
When requiring a ps_lock, query the shadow variable API to retrieve one
117+
for a specific struct sta_info:
118+
119+
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
120+
{
121+
spinlock_t *ps_lock;
122+
123+
/* sync with ieee80211_tx_h_unicast_ps_buf */
124+
ps_lock = klp_shadow_get(sta, PS_LOCK);
125+
if (ps_lock)
126+
spin_lock(ps_lock);
127+
...
128+
129+
When the parent sta_info structure is freed, first free the shadow
130+
variable:
131+
132+
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
133+
{
134+
klp_shadow_free(sta, PS_LOCK);
135+
kfree(sta);
136+
...
137+
138+
139+
In-flight parent objects
140+
------------------------
141+
142+
Sometimes it may not be convenient or possible to allocate shadow
143+
variables alongside their parent objects. Or a livepatch fix may
144+
require shadow varibles to only a subset of parent object instances. In
145+
these cases, the klp_shadow_get_or_alloc() call can be used to attach
146+
shadow variables to parents already in-flight.
147+
148+
For commit 1d147bfa6429, a good spot to allocate a shadow spinlock is
149+
inside ieee80211_sta_ps_deliver_wakeup():
150+
151+
#define PS_LOCK 1
152+
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
153+
{
154+
DEFINE_SPINLOCK(ps_lock_fallback);
155+
spinlock_t *ps_lock;
156+
157+
/* sync with ieee80211_tx_h_unicast_ps_buf */
158+
ps_lock = klp_shadow_get_or_alloc(sta, PS_LOCK,
159+
&ps_lock_fallback, sizeof(ps_lock_fallback),
160+
GFP_ATOMIC);
161+
if (ps_lock)
162+
spin_lock(ps_lock);
163+
...
164+
165+
This usage will create a shadow variable, only if needed, otherwise it
166+
will use one that was already created for this <obj, id> pair.
167+
168+
Like the previous use-case, the shadow spinlock needs to be cleaned up.
169+
A shadow variable can be freed just before its parent object is freed,
170+
or even when the shadow variable itself is no longer required.
171+
172+
173+
Other use-cases
174+
---------------
175+
176+
Shadow variables can also be used as a flag indicating that a data
177+
structure was allocated by new, livepatched code. In this case, it
178+
doesn't matter what data value the shadow variable holds, its existence
179+
suggests how to handle the parent object.
180+
181+
182+
3. References
183+
=============
184+
185+
* https://github.com/dynup/kpatch
186+
The livepatch implementation is based on the kpatch version of shadow
187+
variables.
188+
189+
* http://files.mkgnu.net/files/dynamos/doc/papers/dynamos_eurosys_07.pdf
190+
Dynamic and Adaptive Updates of Non-Quiescent Subsystems in Commodity
191+
Operating System Kernels (Kritis Makris, Kyung Dong Ryu 2007) presented
192+
a datatype update technique called "shadow data structures".

include/linux/livepatch.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,35 @@ struct klp_func {
8787
bool transition;
8888
};
8989

90+
struct klp_object;
91+
92+
/**
93+
* struct klp_callbacks - pre/post live-(un)patch callback structure
94+
* @pre_patch: executed before code patching
95+
* @post_patch: executed after code patching
96+
* @pre_unpatch: executed before code unpatching
97+
* @post_unpatch: executed after code unpatching
98+
* @post_unpatch_enabled: flag indicating if post-unpatch callback
99+
* should run
100+
*
101+
* All callbacks are optional. Only the pre-patch callback, if provided,
102+
* will be unconditionally executed. If the parent klp_object fails to
103+
* patch for any reason, including a non-zero error status returned from
104+
* the pre-patch callback, no further callbacks will be executed.
105+
*/
106+
struct klp_callbacks {
107+
int (*pre_patch)(struct klp_object *obj);
108+
void (*post_patch)(struct klp_object *obj);
109+
void (*pre_unpatch)(struct klp_object *obj);
110+
void (*post_unpatch)(struct klp_object *obj);
111+
bool post_unpatch_enabled;
112+
};
113+
90114
/**
91115
* struct klp_object - kernel object structure for live patching
92116
* @name: module name (or NULL for vmlinux)
93117
* @funcs: function entries for functions to be patched in the object
118+
* @callbacks: functions to be executed pre/post (un)patching
94119
* @kobj: kobject for sysfs resources
95120
* @mod: kernel module associated with the patched object
96121
* (NULL for vmlinux)
@@ -100,6 +125,7 @@ struct klp_object {
100125
/* external */
101126
const char *name;
102127
struct klp_func *funcs;
128+
struct klp_callbacks callbacks;
103129

104130
/* internal */
105131
struct kobject kobj;
@@ -164,6 +190,14 @@ static inline bool klp_have_reliable_stack(void)
164190
IS_ENABLED(CONFIG_HAVE_RELIABLE_STACKTRACE);
165191
}
166192

193+
void *klp_shadow_get(void *obj, unsigned long id);
194+
void *klp_shadow_alloc(void *obj, unsigned long id, void *data,
195+
size_t size, gfp_t gfp_flags);
196+
void *klp_shadow_get_or_alloc(void *obj, unsigned long id, void *data,
197+
size_t size, gfp_t gfp_flags);
198+
void klp_shadow_free(void *obj, unsigned long id);
199+
void klp_shadow_free_all(unsigned long id);
200+
167201
#else /* !CONFIG_LIVEPATCH */
168202

169203
static inline int klp_module_coming(struct module *mod) { return 0; }

kernel/livepatch/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
obj-$(CONFIG_LIVEPATCH) += livepatch.o
22

3-
livepatch-objs := core.o patch.o transition.o
3+
livepatch-objs := core.o patch.o shadow.o transition.o

kernel/livepatch/core.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,6 @@ static bool klp_is_module(struct klp_object *obj)
5454
return obj->name;
5555
}
5656

57-
static bool klp_is_object_loaded(struct klp_object *obj)
58-
{
59-
return !obj->name || obj->mod;
60-
}
61-
6257
/* sets obj->mod if object is not vmlinux and module is found */
6358
static void klp_find_object_module(struct klp_object *obj)
6459
{
@@ -285,6 +280,11 @@ static int klp_write_object_relocations(struct module *pmod,
285280

286281
static int __klp_disable_patch(struct klp_patch *patch)
287282
{
283+
struct klp_object *obj;
284+
285+
if (WARN_ON(!patch->enabled))
286+
return -EINVAL;
287+
288288
if (klp_transition_patch)
289289
return -EBUSY;
290290

@@ -295,6 +295,10 @@ static int __klp_disable_patch(struct klp_patch *patch)
295295

296296
klp_init_transition(patch, KLP_UNPATCHED);
297297

298+
klp_for_each_object(patch, obj)
299+
if (obj->patched)
300+
klp_pre_unpatch_callback(obj);
301+
298302
/*
299303
* Enforce the order of the func->transition writes in
300304
* klp_init_transition() and the TIF_PATCH_PENDING writes in
@@ -388,13 +392,18 @@ static int __klp_enable_patch(struct klp_patch *patch)
388392
if (!klp_is_object_loaded(obj))
389393
continue;
390394

391-
ret = klp_patch_object(obj);
395+
ret = klp_pre_patch_callback(obj);
392396
if (ret) {
393-
pr_warn("failed to enable patch '%s'\n",
394-
patch->mod->name);
397+
pr_warn("pre-patch callback failed for object '%s'\n",
398+
klp_is_module(obj) ? obj->name : "vmlinux");
399+
goto err;
400+
}
395401

396-
klp_cancel_transition();
397-
return ret;
402+
ret = klp_patch_object(obj);
403+
if (ret) {
404+
pr_warn("failed to patch object '%s'\n",
405+
klp_is_module(obj) ? obj->name : "vmlinux");
406+
goto err;
398407
}
399408
}
400409

@@ -403,6 +412,11 @@ static int __klp_enable_patch(struct klp_patch *patch)
403412
patch->enabled = true;
404413

405414
return 0;
415+
err:
416+
pr_warn("failed to enable patch '%s'\n", patch->mod->name);
417+
418+
klp_cancel_transition();
419+
return ret;
406420
}
407421

408422
/**
@@ -854,9 +868,15 @@ static void klp_cleanup_module_patches_limited(struct module *mod,
854868
* is in transition.
855869
*/
856870
if (patch->enabled || patch == klp_transition_patch) {
871+
872+
if (patch != klp_transition_patch)
873+
klp_pre_unpatch_callback(obj);
874+
857875
pr_notice("reverting patch '%s' on unloading module '%s'\n",
858876
patch->mod->name, obj->mod->name);
859877
klp_unpatch_object(obj);
878+
879+
klp_post_unpatch_callback(obj);
860880
}
861881

862882
klp_free_object_loaded(obj);
@@ -906,13 +926,25 @@ int klp_module_coming(struct module *mod)
906926
pr_notice("applying patch '%s' to loading module '%s'\n",
907927
patch->mod->name, obj->mod->name);
908928

929+
ret = klp_pre_patch_callback(obj);
930+
if (ret) {
931+
pr_warn("pre-patch callback failed for object '%s'\n",
932+
obj->name);
933+
goto err;
934+
}
935+
909936
ret = klp_patch_object(obj);
910937
if (ret) {
911938
pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
912939
patch->mod->name, obj->mod->name, ret);
940+
941+
klp_post_unpatch_callback(obj);
913942
goto err;
914943
}
915944

945+
if (patch != klp_transition_patch)
946+
klp_post_patch_callback(obj);
947+
916948
break;
917949
}
918950
}

0 commit comments

Comments
 (0)