Commit | Line | Data |
---|---|---|
c4e6874f PM |
1 | =================================== |
2 | Atomic Replace & Cumulative Patches | |
3 | =================================== | |
4 | ||
5 | There might be dependencies between livepatches. If multiple patches need | |
6 | to do different changes to the same function(s) then we need to define | |
7 | an order in which the patches will be installed. And function implementations | |
8 | from any newer livepatch must be done on top of the older ones. | |
9 | ||
10 | This might become a maintenance nightmare. Especially if anyone would want | |
11 | to remove a patch that is in the middle of the stack. | |
12 | ||
13 | An elegant solution comes with the feature called "Atomic Replace". It allows | |
14 | creation of so called "Cumulative Patches". They include all wanted changes | |
15 | from all older livepatches and completely replace them in one transition. | |
16 | ||
17 | Usage | |
18 | ----- | |
19 | ||
20 | The atomic replace can be enabled by setting "replace" flag in struct klp_patch, | |
21 | for example: | |
22 | ||
23 | static struct klp_patch patch = { | |
24 | .mod = THIS_MODULE, | |
25 | .objs = objs, | |
26 | .replace = true, | |
27 | }; | |
28 | ||
29 | Such a patch is added on top of the livepatch stack when enabled. | |
30 | ||
31 | All processes are then migrated to use the code only from the new patch. | |
32 | Once the transition is finished, all older patches are automatically | |
33 | disabled and removed from the stack of patches. | |
34 | ||
35 | Ftrace handlers are transparently removed from functions that are no | |
36 | longer modified by the new cumulative patch. | |
37 | ||
38 | As a result, the livepatch authors might maintain sources only for one | |
39 | cumulative patch. It helps to keep the patch consistent while adding or | |
40 | removing various fixes or features. | |
41 | ||
42 | Users could keep only the last patch installed on the system after | |
43 | the transition to has finished. It helps to clearly see what code is | |
44 | actually in use. Also the livepatch might then be seen as a "normal" | |
45 | module that modifies the kernel behavior. The only difference is that | |
46 | it can be updated at runtime without breaking its functionality. | |
47 | ||
48 | ||
49 | Features | |
50 | -------- | |
51 | ||
52 | The atomic replace allows: | |
53 | ||
54 | + Atomically revert some functions in a previous patch while | |
55 | upgrading other functions. | |
56 | ||
57 | + Remove eventual performance impact caused by core redirection | |
58 | for functions that are no longer patched. | |
59 | ||
60 | + Decrease user confusion about stacking order and what code | |
61 | is actually in use. | |
62 | ||
63 | ||
64 | Limitations: | |
65 | ------------ | |
66 | ||
67 | + Once the operation finishes, there is no straightforward way | |
68 | to reverse it and restore the replaced patches atomically. | |
69 | ||
70 | A good practice is to set .replace flag in any released livepatch. | |
71 | Then re-adding an older livepatch is equivalent to downgrading | |
72 | to that patch. This is safe as long as the livepatches do _not_ do | |
73 | extra modifications in (un)patching callbacks or in the module_init() | |
74 | or module_exit() functions, see below. | |
75 | ||
76 | Also note that the replaced patch can be removed and loaded again | |
77 | only when the transition was not forced. | |
78 | ||
79 | ||
80 | + Only the (un)patching callbacks from the _new_ cumulative livepatch are | |
81 | executed. Any callbacks from the replaced patches are ignored. | |
82 | ||
83 | In other words, the cumulative patch is responsible for doing any actions | |
84 | that are necessary to properly replace any older patch. | |
85 | ||
86 | As a result, it might be dangerous to replace newer cumulative patches by | |
87 | older ones. The old livepatches might not provide the necessary callbacks. | |
88 | ||
89 | This might be seen as a limitation in some scenarios. But it makes life | |
90 | easier in many others. Only the new cumulative livepatch knows what | |
91 | fixes/features are added/removed and what special actions are necessary | |
92 | for a smooth transition. | |
93 | ||
94 | In any case, it would be a nightmare to think about the order of | |
95 | the various callbacks and their interactions if the callbacks from all | |
96 | enabled patches were called. | |
97 | ||
98 | ||
99 | + There is no special handling of shadow variables. Livepatch authors | |
100 | must create their own rules how to pass them from one cumulative | |
101 | patch to the other. Especially that they should not blindly remove | |
102 | them in module_exit() functions. | |
103 | ||
104 | A good practice might be to remove shadow variables in the post-unpatch | |
105 | callback. It is called only when the livepatch is properly disabled. |