diff options
author | Petr Mladek <pmladek@suse.com> | 2019-01-09 07:43:27 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2019-01-11 14:51:24 -0500 |
commit | c4e6874f2a2965e932f4a5cf2631bc6024e55021 (patch) | |
tree | 650290f6af88ef38999a26574d287d3af14b8576 /Documentation/livepatch | |
parent | d697bad588eb4e76311193e6eaacc7c7aaa5a4ba (diff) |
livepatch: Atomic replace and cumulative patches documentation
User documentation for the atomic replace feature. It makes it easier
to maintain livepatches using so-called cumulative patches.
Signed-off-by: Petr Mladek <pmladek@suse.com>
Acked-by: Miroslav Benes <mbenes@suse.cz>
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'Documentation/livepatch')
-rw-r--r-- | Documentation/livepatch/cumulative-patches.txt | 105 | ||||
-rw-r--r-- | Documentation/livepatch/livepatch.txt | 2 |
2 files changed, 107 insertions, 0 deletions
diff --git a/Documentation/livepatch/cumulative-patches.txt b/Documentation/livepatch/cumulative-patches.txt new file mode 100644 index 000000000000..e7cf5be69f23 --- /dev/null +++ b/Documentation/livepatch/cumulative-patches.txt | |||
@@ -0,0 +1,105 @@ | |||
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. | ||
diff --git a/Documentation/livepatch/livepatch.txt b/Documentation/livepatch/livepatch.txt index 2a70f43166f6..6f32d6ea2fcb 100644 --- a/Documentation/livepatch/livepatch.txt +++ b/Documentation/livepatch/livepatch.txt | |||
@@ -365,6 +365,8 @@ the ftrace handler is unregistered and the struct klp_ops is | |||
365 | freed when the related function is not modified by the new patch | 365 | freed when the related function is not modified by the new patch |
366 | and func_stack list becomes empty. | 366 | and func_stack list becomes empty. |
367 | 367 | ||
368 | See Documentation/livepatch/cumulative-patches.txt for more details. | ||
369 | |||
368 | 370 | ||
369 | 5.4. Disabling | 371 | 5.4. Disabling |
370 | -------------- | 372 | -------------- |