168 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| ====================
 | |
| 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.
 |