| ==================== | |
| System State Changes | |
| ==================== | |
| Some users are really reluctant to reboot a system. This brings the need | |
| to provide more livepatches and maintain some compatibility between them. | |
| Maintaining more livepatches is much easier with cumulative livepatches. | |
| Each new livepatch completely replaces any older one. It can keep, | |
| add, and even remove fixes. And it is typically safe to replace any version | |
| of the livepatch with any other one thanks to the atomic replace feature. | |
| The problems might come with shadow variables and callbacks. They might | |
| change the system behavior or state so that it is no longer safe to | |
| go back and use an older livepatch or the original kernel code. Also | |
| any new livepatch must be able to detect what changes have already been | |
| done by the already installed livepatches. | |
| This is where the livepatch system state tracking gets useful. It | |
| allows to: | |
| - store data needed to manipulate and restore the system state | |
| - define compatibility between livepatches using a change id | |
| and version | |
| 1. Livepatch system state API | |
| ============================= | |
| The state of the system might get modified either by several livepatch callbacks | |
| or by the newly used code. Also it must be possible to find changes done by | |
| already installed livepatches. | |
| Each modified state is described by struct klp_state, see | |
| include/linux/livepatch.h. | |
| Each livepatch defines an array of struct klp_states. They mention | |
| all states that the livepatch modifies. | |
| The livepatch author must define the following two fields for each | |
| struct klp_state: | |
| - *id* | |
| - Non-zero number used to identify the affected system state. | |
| - *version* | |
| - Number describing the variant of the system state change that | |
| is supported by the given livepatch. | |
| The state can be manipulated using two functions: | |
| - *klp_get_state(patch, id)* | |
| - Get struct klp_state associated with the given livepatch | |
| and state id. | |
| - *klp_get_prev_state(id)* | |
| - Get struct klp_state associated with the given feature id and | |
| already installed livepatches. | |
| 2. Livepatch compatibility | |
| ========================== | |
| The system state version is used to prevent loading incompatible livepatches. | |
| The check is done when the livepatch is enabled. The rules are: | |
| - Any completely new system state modification is allowed. | |
| - System state modifications with the same or higher version are allowed | |
| for already modified system states. | |
| - Cumulative livepatches must handle all system state modifications from | |
| already installed livepatches. | |
| - Non-cumulative livepatches are allowed to touch already modified | |
| system states. | |
| 3. Supported scenarios | |
| ====================== | |
| Livepatches have their life-cycle and the same is true for the system | |
| state changes. Every compatible livepatch has to support the following | |
| scenarios: | |
| - Modify the system state when the livepatch gets enabled and the state | |
| has not been already modified by a livepatches that are being | |
| replaced. | |
| - Take over or update the system state modification when is has already | |
| been done by a livepatch that is being replaced. | |
| - Restore the original state when the livepatch is disabled. | |
| - Restore the previous state when the transition is reverted. | |
| It might be the original system state or the state modification | |
| done by livepatches that were being replaced. | |
| - Remove any already made changes when error occurs and the livepatch | |
| cannot get enabled. | |
| 4. Expected usage | |
| ================= | |
| System states are usually modified by livepatch callbacks. The expected | |
| role of each callback is as follows: | |
| *pre_patch()* | |
| - Allocate *state->data* when necessary. The allocation might fail | |
| and *pre_patch()* is the only callback that could stop loading | |
| of the livepatch. The allocation is not needed when the data | |
| are already provided by previously installed livepatches. | |
| - Do any other preparatory action that is needed by | |
| the new code even before the transition gets finished. | |
| For example, initialize *state->data*. | |
| The system state itself is typically modified in *post_patch()* | |
| when the entire system is able to handle it. | |
| - Clean up its own mess in case of error. It might be done by a custom | |
| code or by calling *post_unpatch()* explicitly. | |
| *post_patch()* | |
| - Copy *state->data* from the previous livepatch when they are | |
| compatible. | |
| - Do the actual system state modification. Eventually allow | |
| the new code to use it. | |
| - Make sure that *state->data* has all necessary information. | |
| - Free *state->data* from replaces livepatches when they are | |
| not longer needed. | |
| *pre_unpatch()* | |
| - Prevent the code, added by the livepatch, relying on the system | |
| state change. | |
| - Revert the system state modification.. | |
| *post_unpatch()* | |
| - Distinguish transition reverse and livepatch disabling by | |
| checking *klp_get_prev_state()*. | |
| - In case of transition reverse, restore the previous system | |
| state. It might mean doing nothing. | |
| - Remove any not longer needed setting or data. | |
| .. note:: | |
| *pre_unpatch()* typically does symmetric operations to *post_patch()*. | |
| Except that it is called only when the livepatch is being disabled. | |
| Therefore it does not need to care about any previously installed | |
| livepatch. | |
| *post_unpatch()* typically does symmetric operations to *pre_patch()*. | |
| It might be called also during the transition reverse. Therefore it | |
| has to handle the state of the previously installed livepatches. |