|  | =================================== | 
|  | Atomic Replace & Cumulative Patches | 
|  | =================================== | 
|  |  | 
|  | There might be dependencies between livepatches. If multiple patches need | 
|  | to do different changes to the same function(s) then we need to define | 
|  | an order in which the patches will be installed. And function implementations | 
|  | from any newer livepatch must be done on top of the older ones. | 
|  |  | 
|  | This might become a maintenance nightmare. Especially when more patches | 
|  | modified the same function in different ways. | 
|  |  | 
|  | An elegant solution comes with the feature called "Atomic Replace". It allows | 
|  | creation of so called "Cumulative Patches". They include all wanted changes | 
|  | from all older livepatches and completely replace them in one transition. | 
|  |  | 
|  | Usage | 
|  | ----- | 
|  |  | 
|  | The atomic replace can be enabled by setting "replace" flag in struct klp_patch, | 
|  | for example:: | 
|  |  | 
|  | static struct klp_patch patch = { | 
|  | .mod = THIS_MODULE, | 
|  | .objs = objs, | 
|  | .replace = true, | 
|  | }; | 
|  |  | 
|  | All processes are then migrated to use the code only from the new patch. | 
|  | Once the transition is finished, all older patches are automatically | 
|  | disabled. | 
|  |  | 
|  | Ftrace handlers are transparently removed from functions that are no | 
|  | longer modified by the new cumulative patch. | 
|  |  | 
|  | As a result, the livepatch authors might maintain sources only for one | 
|  | cumulative patch. It helps to keep the patch consistent while adding or | 
|  | removing various fixes or features. | 
|  |  | 
|  | Users could keep only the last patch installed on the system after | 
|  | the transition to has finished. It helps to clearly see what code is | 
|  | actually in use. Also the livepatch might then be seen as a "normal" | 
|  | module that modifies the kernel behavior. The only difference is that | 
|  | it can be updated at runtime without breaking its functionality. | 
|  |  | 
|  |  | 
|  | Features | 
|  | -------- | 
|  |  | 
|  | The atomic replace allows: | 
|  |  | 
|  | - Atomically revert some functions in a previous patch while | 
|  | upgrading other functions. | 
|  |  | 
|  | - Remove eventual performance impact caused by core redirection | 
|  | for functions that are no longer patched. | 
|  |  | 
|  | - Decrease user confusion about dependencies between livepatches. | 
|  |  | 
|  |  | 
|  | Limitations: | 
|  | ------------ | 
|  |  | 
|  | - Once the operation finishes, there is no straightforward way | 
|  | to reverse it and restore the replaced patches atomically. | 
|  |  | 
|  | A good practice is to set .replace flag in any released livepatch. | 
|  | Then re-adding an older livepatch is equivalent to downgrading | 
|  | to that patch. This is safe as long as the livepatches do _not_ do | 
|  | extra modifications in (un)patching callbacks or in the module_init() | 
|  | or module_exit() functions, see below. | 
|  |  | 
|  | Also note that the replaced patch can be removed and loaded again | 
|  | only when the transition was not forced. | 
|  |  | 
|  |  | 
|  | - Only the (un)patching callbacks from the _new_ cumulative livepatch are | 
|  | executed. Any callbacks from the replaced patches are ignored. | 
|  |  | 
|  | In other words, the cumulative patch is responsible for doing any actions | 
|  | that are necessary to properly replace any older patch. | 
|  |  | 
|  | As a result, it might be dangerous to replace newer cumulative patches by | 
|  | older ones. The old livepatches might not provide the necessary callbacks. | 
|  |  | 
|  | This might be seen as a limitation in some scenarios. But it makes life | 
|  | easier in many others. Only the new cumulative livepatch knows what | 
|  | fixes/features are added/removed and what special actions are necessary | 
|  | for a smooth transition. | 
|  |  | 
|  | In any case, it would be a nightmare to think about the order of | 
|  | the various callbacks and their interactions if the callbacks from all | 
|  | enabled patches were called. | 
|  |  | 
|  |  | 
|  | - There is no special handling of shadow variables. Livepatch authors | 
|  | must create their own rules how to pass them from one cumulative | 
|  | patch to the other. Especially that they should not blindly remove | 
|  | them in module_exit() functions. | 
|  |  | 
|  | A good practice might be to remove shadow variables in the post-unpatch | 
|  | callback. It is called only when the livepatch is properly disabled. |