Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 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 | |
Petr Mladek | d67a537 | 2019-01-09 13:43:28 +0100 | [diff] [blame] | 10 | This might become a maintenance nightmare. Especially when more patches |
| 11 | modified the same function in different ways. |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 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, |
Mauro Carvalho Chehab | 89e33ea | 2019-05-03 16:30:23 +0200 | [diff] [blame] | 21 | for example:: |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 22 | |
| 23 | static struct klp_patch patch = { |
| 24 | .mod = THIS_MODULE, |
| 25 | .objs = objs, |
| 26 | .replace = true, |
| 27 | }; |
| 28 | |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 29 | All processes are then migrated to use the code only from the new patch. |
| 30 | Once the transition is finished, all older patches are automatically |
Petr Mladek | d67a537 | 2019-01-09 13:43:28 +0100 | [diff] [blame] | 31 | disabled. |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 32 | |
| 33 | Ftrace handlers are transparently removed from functions that are no |
| 34 | longer modified by the new cumulative patch. |
| 35 | |
| 36 | As a result, the livepatch authors might maintain sources only for one |
| 37 | cumulative patch. It helps to keep the patch consistent while adding or |
| 38 | removing various fixes or features. |
| 39 | |
| 40 | Users could keep only the last patch installed on the system after |
| 41 | the transition to has finished. It helps to clearly see what code is |
| 42 | actually in use. Also the livepatch might then be seen as a "normal" |
| 43 | module that modifies the kernel behavior. The only difference is that |
| 44 | it can be updated at runtime without breaking its functionality. |
| 45 | |
| 46 | |
| 47 | Features |
| 48 | -------- |
| 49 | |
| 50 | The atomic replace allows: |
| 51 | |
Mauro Carvalho Chehab | 89e33ea | 2019-05-03 16:30:23 +0200 | [diff] [blame] | 52 | - Atomically revert some functions in a previous patch while |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 53 | upgrading other functions. |
| 54 | |
Mauro Carvalho Chehab | 89e33ea | 2019-05-03 16:30:23 +0200 | [diff] [blame] | 55 | - Remove eventual performance impact caused by core redirection |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 56 | for functions that are no longer patched. |
| 57 | |
Mauro Carvalho Chehab | 89e33ea | 2019-05-03 16:30:23 +0200 | [diff] [blame] | 58 | - Decrease user confusion about dependencies between livepatches. |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 59 | |
| 60 | |
| 61 | Limitations: |
| 62 | ------------ |
| 63 | |
Mauro Carvalho Chehab | 89e33ea | 2019-05-03 16:30:23 +0200 | [diff] [blame] | 64 | - Once the operation finishes, there is no straightforward way |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 65 | to reverse it and restore the replaced patches atomically. |
| 66 | |
| 67 | A good practice is to set .replace flag in any released livepatch. |
| 68 | Then re-adding an older livepatch is equivalent to downgrading |
| 69 | to that patch. This is safe as long as the livepatches do _not_ do |
| 70 | extra modifications in (un)patching callbacks or in the module_init() |
| 71 | or module_exit() functions, see below. |
| 72 | |
| 73 | Also note that the replaced patch can be removed and loaded again |
| 74 | only when the transition was not forced. |
| 75 | |
| 76 | |
Mauro Carvalho Chehab | 89e33ea | 2019-05-03 16:30:23 +0200 | [diff] [blame] | 77 | - Only the (un)patching callbacks from the _new_ cumulative livepatch are |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 78 | executed. Any callbacks from the replaced patches are ignored. |
| 79 | |
| 80 | In other words, the cumulative patch is responsible for doing any actions |
| 81 | that are necessary to properly replace any older patch. |
| 82 | |
| 83 | As a result, it might be dangerous to replace newer cumulative patches by |
| 84 | older ones. The old livepatches might not provide the necessary callbacks. |
| 85 | |
| 86 | This might be seen as a limitation in some scenarios. But it makes life |
| 87 | easier in many others. Only the new cumulative livepatch knows what |
| 88 | fixes/features are added/removed and what special actions are necessary |
| 89 | for a smooth transition. |
| 90 | |
| 91 | In any case, it would be a nightmare to think about the order of |
| 92 | the various callbacks and their interactions if the callbacks from all |
| 93 | enabled patches were called. |
| 94 | |
| 95 | |
Mauro Carvalho Chehab | 89e33ea | 2019-05-03 16:30:23 +0200 | [diff] [blame] | 96 | - There is no special handling of shadow variables. Livepatch authors |
Petr Mladek | c4e6874 | 2019-01-09 13:43:27 +0100 | [diff] [blame] | 97 | must create their own rules how to pass them from one cumulative |
| 98 | patch to the other. Especially that they should not blindly remove |
| 99 | them in module_exit() functions. |
| 100 | |
| 101 | A good practice might be to remove shadow variables in the post-unpatch |
| 102 | callback. It is called only when the livepatch is properly disabled. |