요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
====================
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.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
누적 패치와 system state 추적
1-27재부팅을 꺼리는 사용자를 지원하려면 더 많은 라이브패치를 제공하고 패치 사이의 호환성을 유지해야 합니다. Cumulative livepatch는 새 패치가 이전 패치를 완전히 대체하면서 fix를 유지·추가·제거할 수 있게 해 이 관리를 단순화합니다.
Atomic replace 기능 덕분에 보통은 한 livepatch version을 다른 version으로 안전하게 교체할 수 있습니다. 하지만 shadow variable과 callback은 system behavior나 state를 바꿀 수 있어, 이전 livepatch 또는 원래 kernel code로 돌아가는 것이 더 이상 안전하지 않을 수 있습니다.
또한 새 livepatch는 이미 설치된 패치가 어떤 변경을 수행했는지 알아야 합니다. Livepatch system state tracking은 상태를 조작하고 복원하는 데 필요한 data를 저장하고, change id와 version으로 livepatch 사이의 호환성을 정의합니다.
Code 교체를 넘어 지속되는 상태 변경을 버전별로 인계합니다.
====================
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
System state API
28-64System state는 여러 livepatch callback이나 새로 사용되는 code가 변경할 수 있습니다. 이미 설치된 livepatch가 수행한 변경도 찾아야 하므로 각 변경 상태를 `include/linux/livepatch.h`에 정의된 `struct klp_state`로 설명합니다.
각 livepatch는 자신이 수정하는 모든 상태를 열거한 `struct klp_states` array를 정의합니다. 각 `struct klp_state`에는 작성자가 `id`와 `version` 두 field를 지정해야 합니다.
`id`는 영향을 받는 system state를 식별하는 0이 아닌 숫자입니다. `version`은 해당 livepatch가 지원하는 system state 변경 variant를 나타내는 숫자입니다.
`klp_get_state()`는 주어진 livepatch와 state id에 연결된 `struct klp_state`를 얻습니다. `klp_get_prev_state()`는 같은 feature id를 가진 이미 설치된 livepatch의 `struct klp_state`를 찾습니다.
Id는 상태의 종류를, version은 그 상태 표현의 호환 단계를 나타냅니다.
새 patch는 자신의 상태 정의와 설치된 이전 상태를 함께 조회합니다.
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.
Livepatch 호환성 규칙
65-81System state version은 호환되지 않는 livepatch의 적재를 막는 데 사용하며, 검사는 livepatch를 enable할 때 수행합니다.
완전히 새로운 system state modification은 허용됩니다. 이미 수정된 state에 대해서는 같은 version 또는 더 높은 version의 변경을 허용합니다.
Cumulative livepatch는 이미 설치된 livepatch가 수행한 모든 system state modification을 처리해야 합니다. 반면 non-cumulative livepatch도 이미 수정된 system state를 건드리는 것이 허용됩니다.
이전 state가 있는지와 새 patch의 version으로 호환성을 판단합니다.
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.
지원해야 하는 lifecycle 시나리오
82-104Livepatch에 lifecycle이 있듯 system state 변경에도 lifecycle이 있습니다. 호환 가능한 모든 livepatch는 enable, replace, disable, transition reverse, enable 실패 상황을 처리해야 합니다.
Enable할 때 교체 대상 livepatch가 아직 해당 state를 수정하지 않았다면 새 patch가 system state를 변경합니다. 이미 변경했다면 새 patch가 그 변경을 takeover하거나 최신 version으로 update해야 합니다.
Livepatch를 disable하면 원래 state를 복원해야 합니다. 진행 중 transition을 되돌리면 이전 state를 복원해야 하는데, 이는 원래 kernel state일 수도 있고 교체되던 livepatch가 만든 state일 수도 있습니다.
오류로 livepatch를 enable할 수 없다면 그때까지 수행한 변경을 모두 제거해야 합니다. Enable 실패는 반쯤 적용된 state를 남기지 않아야 합니다.
각 전환의 목표 상태와 복구 대상을 구분합니다.
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.
Callback별 예상 역할
105-167System state는 보통 livepatch callback에서 변경합니다. `pre_patch()`는 필요한 경우 `state->data`를 할당합니다. Allocation은 실패할 수 있으며, livepatch 적재를 중단할 수 있는 callback은 `pre_patch()`뿐입니다. 이전 livepatch가 이미 data를 제공했다면 다시 할당할 필요가 없습니다.
`pre_patch()`는 transition이 끝나기 전에도 새 code가 요구하는 준비 작업을 수행하고 `state->data`를 초기화할 수 있습니다. 실제 system state 변경은 전체 system이 이를 처리할 수 있게 된 뒤 `post_patch()`에서 수행하는 것이 일반적입니다.
`pre_patch()`에서 오류가 나면 자신이 만든 변경을 직접 정리하거나 `post_unpatch()`를 명시적으로 호출해 정리해야 합니다.
`post_patch()`는 호환되는 이전 livepatch에서 `state->data`를 복사하고 실제 system state를 변경해 새 code가 사용할 수 있게 합니다. `state->data`에 복원에 필요한 모든 정보가 있는지 보장하고, 더 이상 필요 없는 교체 대상 livepatch의 data를 해제합니다.
`pre_unpatch()`는 livepatch가 추가한 code가 system state 변경에 의존하지 못하게 차단한 뒤 실제 변경을 되돌립니다.
`post_unpatch()`는 `klp_get_prev_state()`를 확인해 transition reverse와 livepatch disable을 구별합니다. Reverse라면 이전 system state를 복원하며, 이미 그 상태가 남아 있다면 아무 작업도 하지 않을 수 있습니다. 마지막으로 더 이상 필요 없는 설정과 data를 제거합니다.
일반적으로 `pre_unpatch()`는 `post_patch()`의 대칭 작업입니다. 하지만 livepatch를 disable할 때만 호출되므로 이전에 설치된 livepatch를 고려할 필요는 없습니다.
`post_unpatch()`는 `pre_patch()`의 대칭 작업이지만 transition reverse 중에도 호출될 수 있습니다. 따라서 이전에 설치된 livepatch의 state를 반드시 처리해야 합니다.
준비·적용·차단·복원 단계를 callback별로 분리합니다.
Transition 전후에 data와 실제 system state의 소유권이 이동합니다.
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.
요약·해설
system-state.rst:1-167System state tracking은 code를 교체한 뒤에도 남는 callback·shadow data 변경을 `id`와 `version`으로 식별해 누적 patch의 호환성을 판정합니다.
새 patch는 이전 변경을 takeover하거나 update하고, disable·transition reverse·enable 실패 때 각각 원래 상태 또는 교체 전 상태를 정확히 복원해야 합니다.
`pre_patch()`부터 `post_unpatch()`까지의 callback은 data 준비, 실제 변경, 새 code 의존 차단, 이전 상태 복원을 나누어 담당합니다.