forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.4 KiB
167 lines
5.4 KiB
==================== |
|
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() |
|
|
|
- Get struct klp_state associated with the given livepatch |
|
and state id. |
|
|
|
- klp_get_prev_state() |
|
|
|
- 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.
|
|
|