요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
===========================
Livepatch module ELF format
===========================
This document outlines the ELF format requirements that livepatch modules must follow.
.. Table of Contents
.. contents:: :local:
1. Background and motivation
============================
Formerly, livepatch required separate architecture-specific code to write
relocations. However, arch-specific code to write relocations already
exists in the module loader, so this former approach produced redundant
code. So, instead of duplicating code and re-implementing what the module
loader can already do, livepatch leverages existing code in the module
loader to perform the all the arch-specific relocation work. Specifically,
livepatch reuses the apply_relocate_add() function in the module loader to
write relocations. The patch module ELF format described in this document
enables livepatch to be able to do this. The hope is that this will make
livepatch more easily portable to other architectures and reduce the amount
of arch-specific code required to port livepatch to a particular
architecture.
Since apply_relocate_add() requires access to a module's section header
table, symbol table, and relocation section indices, ELF information is
preserved for livepatch modules (see section 5). Livepatch manages its own
relocation sections and symbols, which are described in this document. The
ELF constants used to mark livepatch symbols and relocation sections were
selected from OS-specific ranges according to the definitions from glibc.
Why does livepatch need to write its own relocations?
-----------------------------------------------------
A typical livepatch module contains patched versions of functions that can
reference non-exported global symbols and non-included local symbols.
Relocations referencing these types of symbols cannot be left in as-is
since the kernel module loader cannot resolve them and will therefore
reject the livepatch module. Furthermore, we cannot apply relocations that
affect modules not yet loaded at patch module load time (e.g. a patch to a
driver that is not loaded). Formerly, livepatch solved this problem by
embedding special "dynrela" (dynamic rela) sections in the resulting patch
module ELF output. Using these dynrela sections, livepatch could resolve
symbols while taking into account its scope and what module the symbol
belongs to, and then manually apply the dynamic relocations. However this
approach required livepatch to supply arch-specific code in order to write
these relocations. In the new format, livepatch manages its own SHT_RELA
relocation sections in place of dynrela sections, and the symbols that the
relas reference are special livepatch symbols (see section 2 and 3). The
arch-specific livepatch relocation code is replaced by a call to
apply_relocate_add().
2. Livepatch modinfo field
==========================
Livepatch modules are required to have the "livepatch" modinfo attribute.
See the sample livepatch module in samples/livepatch/ for how this is done.
Livepatch modules can be identified by users by using the 'modinfo' command
and looking for the presence of the "livepatch" field. This field is also
used by the kernel module loader to identify livepatch modules.
Example:
--------
**Modinfo output:**
::
% modinfo livepatch-meminfo.ko
filename: livepatch-meminfo.ko
livepatch: Y
license: GPL
depends:
vermagic: 4.3.0+ SMP mod_unload
3. Livepatch relocation sections
================================
A livepatch module manages its own ELF relocation sections to apply
relocations to modules as well as to the kernel (vmlinux) at the
appropriate time. For example, if a patch module patches a driver that is
not currently loaded, livepatch will apply the corresponding livepatch
relocation section(s) to the driver once it loads.
Each "object" (e.g. vmlinux, or a module) within a patch module may have
multiple livepatch relocation sections associated with it (e.g. patches to
multiple functions within the same object). There is a 1-1 correspondence
between a livepatch relocation section and the target section (usually the
text section of a function) to which the relocation(s) apply. It is
also possible for a livepatch module to have no livepatch relocation
sections, as in the case of the sample livepatch module (see
samples/livepatch).
Since ELF information is preserved for livepatch modules (see Section 5), a
livepatch relocation section can be applied simply by passing in the
appropriate section index to apply_relocate_add(), which then uses it to
access the relocation section and apply the relocations.
Every symbol referenced by a rela in a livepatch relocation section is a
livepatch symbol. These must be resolved before livepatch can call
apply_relocate_add(). See Section 3 for more information.
3.1 Livepatch relocation section format
=======================================
Livepatch relocation sections must be marked with the SHF_RELA_LIVEPATCH
section flag. See include/uapi/linux/elf.h for the definition. The module
loader recognizes this flag and will avoid applying those relocation sections
at patch module load time. These sections must also be marked with SHF_ALLOC,
so that the module loader doesn't discard them on module load (i.e. they will
be copied into memory along with the other SHF_ALLOC sections).
The name of a livepatch relocation section must conform to the following
format::
.klp.rela.objname.section_name
^ ^^ ^ ^ ^
|________||_____| |__________|
[A] [B] [C]
[A]
The relocation section name is prefixed with the string ".klp.rela."
[B]
The name of the object (i.e. "vmlinux" or name of module) to
which the relocation section belongs follows immediately after the prefix.
[C]
The actual name of the section to which this relocation section applies.
Examples:
---------
**Livepatch relocation section names:**
::
.klp.rela.ext4.text.ext4_attr_store
.klp.rela.vmlinux.text.cmdline_proc_show
**`readelf --sections` output for a patch
module that patches vmlinux and modules 9p, btrfs, ext4:**
::
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ snip ]
[29] .klp.rela.9p.text.caches.show RELA 0000000000000000 002d58 0000c0 18 AIo 64 9 8
[30] .klp.rela.btrfs.text.btrfs.feature.attr.show RELA 0000000000000000 002e18 000060 18 AIo 64 11 8
[ snip ]
[34] .klp.rela.ext4.text.ext4.attr.store RELA 0000000000000000 002fd8 0000d8 18 AIo 64 13 8
[35] .klp.rela.ext4.text.ext4.attr.show RELA 0000000000000000 0030b0 000150 18 AIo 64 15 8
[36] .klp.rela.vmlinux.text.cmdline.proc.show RELA 0000000000000000 003200 000018 18 AIo 64 17 8
[37] .klp.rela.vmlinux.text.meminfo.proc.show RELA 0000000000000000 003218 0000f0 18 AIo 64 19 8
[ snip ] ^ ^
| |
[*] [*]
[*]
Livepatch relocation sections are SHT_RELA sections but with a few special
characteristics. Notice that they are marked SHF_ALLOC ("A") so that they will
not be discarded when the module is loaded into memory, as well as with the
SHF_RELA_LIVEPATCH flag ("o" - for OS-specific).
**`readelf --relocs` output for a patch module:**
::
Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
000000000000001f 0000005e00000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.printk,0 - 4
0000000000000028 0000003d0000000b R_X86_64_32S 0000000000000000 .klp.sym.btrfs.btrfs_ktype,0 + 0
0000000000000036 0000003b00000002 R_X86_64_PC32 0000000000000000 .klp.sym.btrfs.can_modify_feature.isra.3,0 - 4
000000000000004c 0000004900000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.snprintf,0 - 4
[ snip ] ^
|
[*]
[*]
Every symbol referenced by a relocation is a livepatch symbol.
4. Livepatch symbols
====================
Livepatch symbols are symbols referred to by livepatch relocation sections.
These are symbols accessed from new versions of functions for patched
objects, whose addresses cannot be resolved by the module loader (because
they are local or unexported global syms). Since the module loader only
resolves exported syms, and not every symbol referenced by the new patched
functions is exported, livepatch symbols were introduced. They are used
also in cases where we cannot immediately know the address of a symbol when
a patch module loads. For example, this is the case when livepatch patches
a module that is not loaded yet. In this case, the relevant livepatch
symbols are resolved simply when the target module loads. In any case, for
any livepatch relocation section, all livepatch symbols referenced by that
section must be resolved before livepatch can call apply_relocate_add() for
that reloc section.
Livepatch symbols must be marked with SHN_LIVEPATCH so that the module
loader can identify and ignore them. Livepatch modules keep these symbols
in their symbol tables, and the symbol table is made accessible through
module->symtab.
4.1 A livepatch module's symbol table
=====================================
Normally, a stripped down copy of a module's symbol table (containing only
"core" symbols) is made available through module->symtab (See layout_symtab()
in kernel/module/kallsyms.c). For livepatch modules, the symbol table copied
into memory on module load must be exactly the same as the symbol table produced
when the patch module was compiled. This is because the relocations in each
livepatch relocation section refer to their respective symbols with their symbol
indices, and the original symbol indices (and thus the symtab ordering) must be
preserved in order for apply_relocate_add() to find the right symbol.
For example, take this particular rela from a livepatch module::
Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
000000000000001f 0000005e00000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.printk,0 - 4
This rela refers to the symbol '.klp.sym.vmlinux.printk,0', and the symbol
index is encoded in 'Info'. Here its symbol index is 0x5e, which is 94 in
decimal, which refers to the symbol index 94.
And in this patch module's corresponding symbol table, symbol index 94 refers
to that very symbol::
[ snip ]
94: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.printk,0
[ snip ]
4.2 Livepatch symbol format
===========================
Livepatch symbols must have their section index marked as SHN_LIVEPATCH, so
that the module loader can identify them and not attempt to resolve them.
See include/uapi/linux/elf.h for the actual definitions.
Livepatch symbol names must conform to the following format::
.klp.sym.objname.symbol_name,sympos
^ ^^ ^ ^ ^ ^
|_______||_____| |_________| |
[A] [B] [C] [D]
[A]
The symbol name is prefixed with the string ".klp.sym."
[B]
The name of the object (i.e. "vmlinux" or name of module) to
which the symbol belongs follows immediately after the prefix.
[C]
The actual name of the symbol.
[D]
The position of the symbol in the object (as according to kallsyms)
This is used to differentiate duplicate symbols within the same
object. The symbol position is expressed numerically (0, 1, 2...).
The symbol position of a unique symbol is 0.
Examples:
---------
**Livepatch symbol names:**
::
.klp.sym.vmlinux.snprintf,0
.klp.sym.vmlinux.printk,0
.klp.sym.btrfs.btrfs_ktype,0
**`readelf --symbols` output for a patch module:**
::
Symbol table '.symtab' contains 127 entries:
Num: Value Size Type Bind Vis Ndx Name
[ snip ]
73: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.snprintf,0
74: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.capable,0
75: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.find_next_bit,0
76: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.si_swapinfo,0
[ snip ] ^
|
[*]
[*]
Note that the 'Ndx' (Section index) for these symbols is SHN_LIVEPATCH (0xff20).
"OS" means OS-specific.
5. Symbol table and ELF section access
======================================
A livepatch module's symbol table is accessible through module->symtab.
Since apply_relocate_add() requires access to a module's section headers,
symbol table, and relocation section indices, ELF information is preserved for
livepatch modules and is made accessible by the module loader through
module->klp_info, which is a :c:type:`klp_modinfo` struct. When a livepatch module
loads, this struct is filled in by the module loader.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
배경과 설계 동기
1-55이 문서는 라이브패치 모듈이 따라야 하는 ELF 형식을 규정합니다. 과거에는 라이브패치가 relocation을 기록하기 위해 아키텍처별 코드를 따로 가지고 있었지만, 모듈 로더에도 이미 같은 작업을 수행하는 코드가 있었습니다. 중복 구현을 없애기 위해 현재 형식은 모듈 로더의 `apply_relocate_add()`를 재사용합니다. 그 결과 새 아키텍처로 라이브패치를 이식할 때 필요한 아키텍처별 코드가 줄어듭니다.
`apply_relocate_add()`는 모듈의 section header table, symbol table, relocation section index에 접근해야 합니다. 따라서 라이브패치 모듈에서는 이 ELF 정보를 보존하며, 라이브패치 전용 relocation section과 symbol을 별도로 관리합니다. 이들을 표시하는 ELF 상수는 glibc가 정의한 OS 전용 범위에서 선택했습니다.
패치된 함수는 export되지 않은 global symbol이나 결과 모듈에 포함되지 않은 local symbol을 참조할 수 있습니다. 모듈 로더는 이런 symbol을 해석할 수 없으므로 일반 relocation 상태로 남겨 두면 라이브패치 모듈을 거부합니다. 또한 패치 모듈을 적재할 때 아직 올라오지 않은 드라이버처럼 대상 모듈이 존재하지 않으면 그 모듈을 향한 relocation도 즉시 적용할 수 없습니다.
이전 형식은 특별한 `dynrela` section을 패치 모듈 ELF에 넣고, symbol의 scope와 소속 모듈을 고려해 직접 dynamic relocation을 적용했습니다. 하지만 이 방식에는 아키텍처별 relocation 기록 코드가 필요했습니다. 새 형식은 `dynrela` 대신 라이브패치가 관리하는 `SHT_RELA` section과 전용 symbol을 사용하고, 실제 relocation 적용은 `apply_relocate_add()`에 맡깁니다.
중복 아키텍처 코드를 모듈 로더의 기존 구현으로 통합합니다.
===========================
Livepatch module ELF format
===========================
This document outlines the ELF format requirements that livepatch modules must follow.
.. Table of Contents
.. contents:: :local:
1. Background and motivation
============================
Formerly, livepatch required separate architecture-specific code to write
relocations. However, arch-specific code to write relocations already
exists in the module loader, so this former approach produced redundant
code. So, instead of duplicating code and re-implementing what the module
loader can already do, livepatch leverages existing code in the module
loader to perform the all the arch-specific relocation work. Specifically,
livepatch reuses the apply_relocate_add() function in the module loader to
write relocations. The patch module ELF format described in this document
enables livepatch to be able to do this. The hope is that this will make
livepatch more easily portable to other architectures and reduce the amount
of arch-specific code required to port livepatch to a particular
architecture.
Since apply_relocate_add() requires access to a module's section header
table, symbol table, and relocation section indices, ELF information is
preserved for livepatch modules (see section 5). Livepatch manages its own
relocation sections and symbols, which are described in this document. The
ELF constants used to mark livepatch symbols and relocation sections were
selected from OS-specific ranges according to the definitions from glibc.
Why does livepatch need to write its own relocations?
-----------------------------------------------------
A typical livepatch module contains patched versions of functions that can
reference non-exported global symbols and non-included local symbols.
Relocations referencing these types of symbols cannot be left in as-is
since the kernel module loader cannot resolve them and will therefore
reject the livepatch module. Furthermore, we cannot apply relocations that
affect modules not yet loaded at patch module load time (e.g. a patch to a
driver that is not loaded). Formerly, livepatch solved this problem by
embedding special "dynrela" (dynamic rela) sections in the resulting patch
module ELF output. Using these dynrela sections, livepatch could resolve
symbols while taking into account its scope and what module the symbol
belongs to, and then manually apply the dynamic relocations. However this
approach required livepatch to supply arch-specific code in order to write
these relocations. In the new format, livepatch manages its own SHT_RELA
relocation sections in place of dynrela sections, and the symbols that the
relas reference are special livepatch symbols (see section 2 and 3). The
arch-specific livepatch relocation code is replaced by a call to
apply_relocate_add().
라이브패치 modinfo 필드
56-79라이브패치 모듈에는 반드시 `livepatch` modinfo attribute가 있어야 합니다. 설정 방법은 `samples/livepatch/`의 예제 모듈에서 확인할 수 있습니다.
사용자는 `modinfo` 명령 출력에 `livepatch` 필드가 있는지 확인해 라이브패치 모듈을 식별할 수 있습니다. 커널 모듈 로더도 같은 필드를 사용해 해당 모듈이 라이브패치임을 판별합니다.
예시 출력의 `livepatch: Y`가 필수 표식입니다. `filename`, `license`, `depends`, `vermagic` 같은 나머지 항목은 일반 모듈 정보와 같은 의미를 가집니다.
사용자 도구와 커널 로더가 같은 attribute를 읽습니다.
2. Livepatch modinfo field
==========================
Livepatch modules are required to have the "livepatch" modinfo attribute.
See the sample livepatch module in samples/livepatch/ for how this is done.
Livepatch modules can be identified by users by using the 'modinfo' command
and looking for the presence of the "livepatch" field. This field is also
used by the kernel module loader to identify livepatch modules.
Example:
--------
**Modinfo output:**
::
% modinfo livepatch-meminfo.ko
filename: livepatch-meminfo.ko
livepatch: Y
license: GPL
depends:
vermagic: 4.3.0+ SMP mod_unload
라이브패치 relocation section
80-106라이브패치 모듈은 vmlinux와 각 kernel module에 필요한 relocation을 적절한 시점에 적용하기 위해 자체 ELF relocation section을 관리합니다. 패치 대상 드라이버가 아직 적재되지 않았다면, 그 드라이버가 올라오는 시점에 대응하는 라이브패치 relocation section을 적용합니다.
패치 모듈 안의 각 object, 즉 `vmlinux` 또는 특정 module은 여러 라이브패치 relocation section을 가질 수 있습니다. 같은 object의 여러 함수를 패치할 수 있기 때문입니다. 각 라이브패치 relocation section과 relocation 대상 section, 보통 특정 함수의 text section 사이에는 1:1 대응 관계가 있습니다.
반대로 `samples/livepatch` 예제처럼 전용 relocation이 하나도 없는 라이브패치 모듈도 유효합니다. ELF 정보가 보존되므로 라이브패치는 알맞은 section index를 `apply_relocate_add()`에 넘기는 것만으로 relocation section을 찾아 적용할 수 있습니다.
라이브패치 relocation section의 각 `rela`가 참조하는 symbol은 모두 라이브패치 symbol입니다. 해당 section에 `apply_relocate_add()`를 호출하기 전에 이 symbol들을 전부 해석해야 합니다.
아직 적재되지 않은 대상 모듈도 같은 ELF section을 보존해 나중에 처리합니다.
3. Livepatch relocation sections
================================
A livepatch module manages its own ELF relocation sections to apply
relocations to modules as well as to the kernel (vmlinux) at the
appropriate time. For example, if a patch module patches a driver that is
not currently loaded, livepatch will apply the corresponding livepatch
relocation section(s) to the driver once it loads.
Each "object" (e.g. vmlinux, or a module) within a patch module may have
multiple livepatch relocation sections associated with it (e.g. patches to
multiple functions within the same object). There is a 1-1 correspondence
between a livepatch relocation section and the target section (usually the
text section of a function) to which the relocation(s) apply. It is
also possible for a livepatch module to have no livepatch relocation
sections, as in the case of the sample livepatch module (see
samples/livepatch).
Since ELF information is preserved for livepatch modules (see Section 5), a
livepatch relocation section can be applied simply by passing in the
appropriate section index to apply_relocate_add(), which then uses it to
access the relocation section and apply the relocations.
Every symbol referenced by a rela in a livepatch relocation section is a
livepatch symbol. These must be resolved before livepatch can call
apply_relocate_add(). See Section 3 for more information.
Relocation section 형식
107-186라이브패치 relocation section에는 `SHF_RELA_LIVEPATCH` flag를 표시해야 합니다. 정의는 `include/uapi/linux/elf.h`에 있습니다. 모듈 로더는 이 flag를 보고 패치 모듈을 처음 적재할 때 해당 relocation section을 적용하지 않습니다.
또한 section에는 `SHF_ALLOC`을 표시해야 합니다. 그래야 모듈 로더가 적재 과정에서 section을 버리지 않고 다른 `SHF_ALLOC` section과 함께 메모리로 복사합니다.
Section 이름은 `.klp.rela.objname.section_name` 형식을 따릅니다. `[A]`는 고정 prefix `.klp.rela.`, `[B]`는 relocation section이 속한 object 이름인 `vmlinux` 또는 module 이름, `[C]`는 relocation이 실제로 적용될 대상 section 이름입니다.
원문의 ASCII 주석을 같은 의미의 필드 표로 다시 구성했습니다.
따라서 `.klp.rela.ext4.text.ext4_attr_store`는 ext4 object의 `text.ext4_attr_store` section에 적용되고, `.klp.rela.vmlinux.text.cmdline_proc_show`는 vmlinux의 해당 text section에 적용됩니다.
`readelf --sections` 예시에서 9p, btrfs, ext4, vmlinux를 대상으로 하는 section은 모두 type이 `RELA`입니다. flag의 `A`는 `SHF_ALLOC`, OS 전용 flag를 뜻하는 `o`는 `SHF_RELA_LIVEPATCH`입니다. 이 조합 덕분에 section이 메모리에 남으면서도 최초 모듈 적재 때 일반 relocation처럼 자동 적용되지는 않습니다.
`readelf --relocs` 예시에는 btrfs 함수가 참조하는 `printk`, `btrfs_ktype`, `can_modify_feature.isra.3`, `snprintf`의 relocation 네 개가 나옵니다. 각 symbol 이름이 `.klp.sym.`으로 시작하므로 모든 참조가 라이브패치 symbol이라는 조건을 확인할 수 있습니다.
두 flag는 보존 시점과 적용 시점을 분리합니다.
3.1 Livepatch relocation section format
=======================================
Livepatch relocation sections must be marked with the SHF_RELA_LIVEPATCH
section flag. See include/uapi/linux/elf.h for the definition. The module
loader recognizes this flag and will avoid applying those relocation sections
at patch module load time. These sections must also be marked with SHF_ALLOC,
so that the module loader doesn't discard them on module load (i.e. they will
be copied into memory along with the other SHF_ALLOC sections).
The name of a livepatch relocation section must conform to the following
format::
.klp.rela.objname.section_name
^ ^^ ^ ^ ^
|________||_____| |__________|
[A] [B] [C]
[A]
The relocation section name is prefixed with the string ".klp.rela."
[B]
The name of the object (i.e. "vmlinux" or name of module) to
which the relocation section belongs follows immediately after the prefix.
[C]
The actual name of the section to which this relocation section applies.
Examples:
---------
**Livepatch relocation section names:**
::
.klp.rela.ext4.text.ext4_attr_store
.klp.rela.vmlinux.text.cmdline_proc_show
**`readelf --sections` output for a patch
module that patches vmlinux and modules 9p, btrfs, ext4:**
::
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ snip ]
[29] .klp.rela.9p.text.caches.show RELA 0000000000000000 002d58 0000c0 18 AIo 64 9 8
[30] .klp.rela.btrfs.text.btrfs.feature.attr.show RELA 0000000000000000 002e18 000060 18 AIo 64 11 8
[ snip ]
[34] .klp.rela.ext4.text.ext4.attr.store RELA 0000000000000000 002fd8 0000d8 18 AIo 64 13 8
[35] .klp.rela.ext4.text.ext4.attr.show RELA 0000000000000000 0030b0 000150 18 AIo 64 15 8
[36] .klp.rela.vmlinux.text.cmdline.proc.show RELA 0000000000000000 003200 000018 18 AIo 64 17 8
[37] .klp.rela.vmlinux.text.meminfo.proc.show RELA 0000000000000000 003218 0000f0 18 AIo 64 19 8
[ snip ] ^ ^
| |
[*] [*]
[*]
Livepatch relocation sections are SHT_RELA sections but with a few special
characteristics. Notice that they are marked SHF_ALLOC ("A") so that they will
not be discarded when the module is loaded into memory, as well as with the
SHF_RELA_LIVEPATCH flag ("o" - for OS-specific).
**`readelf --relocs` output for a patch module:**
::
Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
000000000000001f 0000005e00000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.printk,0 - 4
0000000000000028 0000003d0000000b R_X86_64_32S 0000000000000000 .klp.sym.btrfs.btrfs_ktype,0 + 0
0000000000000036 0000003b00000002 R_X86_64_PC32 0000000000000000 .klp.sym.btrfs.can_modify_feature.isra.3,0 - 4
000000000000004c 0000004900000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.snprintf,0 - 4
[ snip ] ^
|
[*]
[*]
Every symbol referenced by a relocation is a livepatch symbol.
라이브패치 symbol
187-208라이브패치 symbol은 라이브패치 relocation section이 참조하는 symbol입니다. 패치된 새 함수가 접근하지만 모듈 로더로는 주소를 해석할 수 없는 local symbol이나 export되지 않은 global symbol을 나타냅니다.
패치 대상 module이 아직 적재되지 않아 symbol 주소를 바로 알 수 없는 경우에도 이 형식을 사용합니다. 대상 module이 나중에 적재될 때 관련 라이브패치 symbol을 해석합니다. 어떤 경우든 특정 relocation section에 `apply_relocate_add()`를 호출하기 전에 그 section이 참조하는 모든 라이브패치 symbol의 주소가 확정되어야 합니다.
모듈 로더가 이 symbol을 일반 symbol처럼 해석하지 않도록 section index를 `SHN_LIVEPATCH`로 표시합니다. 라이브패치 모듈은 symbol을 symbol table에 유지하며, 커널에서는 `module->symtab`을 통해 접근할 수 있습니다.
Relocation은 참조 symbol이 모두 준비된 뒤에만 적용됩니다.
4. Livepatch symbols
====================
Livepatch symbols are symbols referred to by livepatch relocation sections.
These are symbols accessed from new versions of functions for patched
objects, whose addresses cannot be resolved by the module loader (because
they are local or unexported global syms). Since the module loader only
resolves exported syms, and not every symbol referenced by the new patched
functions is exported, livepatch symbols were introduced. They are used
also in cases where we cannot immediately know the address of a symbol when
a patch module loads. For example, this is the case when livepatch patches
a module that is not loaded yet. In this case, the relevant livepatch
symbols are resolved simply when the target module loads. In any case, for
any livepatch relocation section, all livepatch symbols referenced by that
section must be resolved before livepatch can call apply_relocate_add() for
that reloc section.
Livepatch symbols must be marked with SHN_LIVEPATCH so that the module
loader can identify and ignore them. Livepatch modules keep these symbols
in their symbol tables, and the symbol table is made accessible through
module->symtab.
라이브패치 모듈의 symbol table
209-236일반 module은 `layout_symtab()`이 core symbol만 담은 축소된 symbol table 복사본을 만들어 `module->symtab`으로 제공합니다. 그러나 라이브패치 모듈은 적재 후 메모리에 복사되는 symbol table이 패치 모듈 컴파일 때 만들어진 원본과 정확히 같아야 합니다.
각 라이브패치 relocation은 symbol을 이름이 아니라 symbol index로 참조합니다. 따라서 원래 index와 symbol table 순서를 보존해야 `apply_relocate_add()`가 올바른 symbol을 찾습니다.
예시 relocation의 `Info` 값에 들어 있는 symbol index `0x5e`는 10진수 94입니다. 대응 symbol table의 94번 entry가 실제로 `.klp.sym.vmlinux.printk,0`을 가리킵니다. table을 축소하거나 재정렬하면 이 연결이 깨져 잘못된 symbol에 relocation이 적용될 수 있습니다.
원래 symbol index를 그대로 보존해야 하는 이유입니다.
4.1 A livepatch module's symbol table
=====================================
Normally, a stripped down copy of a module's symbol table (containing only
"core" symbols) is made available through module->symtab (See layout_symtab()
in kernel/module/kallsyms.c). For livepatch modules, the symbol table copied
into memory on module load must be exactly the same as the symbol table produced
when the patch module was compiled. This is because the relocations in each
livepatch relocation section refer to their respective symbols with their symbol
indices, and the original symbol indices (and thus the symtab ordering) must be
preserved in order for apply_relocate_add() to find the right symbol.
For example, take this particular rela from a livepatch module::
Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
000000000000001f 0000005e00000002 R_X86_64_PC32 0000000000000000 .klp.sym.vmlinux.printk,0 - 4
This rela refers to the symbol '.klp.sym.vmlinux.printk,0', and the symbol
index is encoded in 'Info'. Here its symbol index is 0x5e, which is 94 in
decimal, which refers to the symbol index 94.
And in this patch module's corresponding symbol table, symbol index 94 refers
to that very symbol::
[ snip ]
94: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.printk,0
[ snip ]
라이브패치 symbol 이름 형식
237-296라이브패치 symbol은 모듈 로더가 식별하고 직접 해석하지 않도록 section index를 `SHN_LIVEPATCH`로 표시해야 합니다. 실제 상수 정의는 `include/uapi/linux/elf.h`에 있습니다.
Symbol 이름은 `.klp.sym.objname.symbol_name,sympos` 형식을 따릅니다. `[A]`는 고정 prefix `.klp.sym.`, `[B]`는 symbol이 속한 `vmlinux` 또는 module 이름, `[C]`는 실제 symbol 이름, `[D]`는 kallsyms 기준으로 같은 object 안에서 해당 이름이 나타나는 위치입니다.
동일 object에 같은 이름의 symbol이 여러 개 있으면 position을 `0`, `1`, `2` 순서로 부여해 구별합니다. 유일한 symbol의 position은 `0`입니다. 따라서 `.klp.sym.btrfs.btrfs_ktype,0`은 btrfs object에서 처음 발견되는 `btrfs_ktype`을 뜻합니다.
원문의 ASCII 주석을 필드별 규칙으로 옮겼습니다.
예시에는 `.klp.sym.vmlinux.snprintf,0`, `.klp.sym.vmlinux.printk,0`, `.klp.sym.btrfs.btrfs_ktype,0`이 있습니다. `readelf --symbols` 출력의 `Ndx`가 `OS [0xff20]`으로 표시되는데, `0xff20`은 `SHN_LIVEPATCH`이고 `OS`는 OS 전용 범위라는 뜻입니다.
4.2 Livepatch symbol format
===========================
Livepatch symbols must have their section index marked as SHN_LIVEPATCH, so
that the module loader can identify them and not attempt to resolve them.
See include/uapi/linux/elf.h for the actual definitions.
Livepatch symbol names must conform to the following format::
.klp.sym.objname.symbol_name,sympos
^ ^^ ^ ^ ^ ^
|_______||_____| |_________| |
[A] [B] [C] [D]
[A]
The symbol name is prefixed with the string ".klp.sym."
[B]
The name of the object (i.e. "vmlinux" or name of module) to
which the symbol belongs follows immediately after the prefix.
[C]
The actual name of the symbol.
[D]
The position of the symbol in the object (as according to kallsyms)
This is used to differentiate duplicate symbols within the same
object. The symbol position is expressed numerically (0, 1, 2...).
The symbol position of a unique symbol is 0.
Examples:
---------
**Livepatch symbol names:**
::
.klp.sym.vmlinux.snprintf,0
.klp.sym.vmlinux.printk,0
.klp.sym.btrfs.btrfs_ktype,0
**`readelf --symbols` output for a patch module:**
::
Symbol table '.symtab' contains 127 entries:
Num: Value Size Type Bind Vis Ndx Name
[ snip ]
73: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.snprintf,0
74: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.capable,0
75: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.find_next_bit,0
76: 0000000000000000 0 NOTYPE GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.si_swapinfo,0
[ snip ] ^
|
[*]
[*]
Note that the 'Ndx' (Section index) for these symbols is SHN_LIVEPATCH (0xff20).
"OS" means OS-specific.
Symbol table과 ELF section 접근
297-305라이브패치 모듈의 symbol table은 `module->symtab`으로 접근합니다.
`apply_relocate_add()`에 필요한 section header, symbol table, relocation section index도 라이브패치 모듈에 보존됩니다. 모듈 로더는 이 정보를 `struct klp_modinfo` 형식의 `module->klp_info`를 통해 제공하며, 라이브패치 모듈을 적재할 때 구조체를 채웁니다.
런타임 relocation에 필요한 정보와 커널 접근 지점입니다.
5. Symbol table and ELF section access
======================================
A livepatch module's symbol table is accessible through module->symtab.
Since apply_relocate_add() requires access to a module's section headers,
symbol table, and relocation section indices, ELF information is preserved for
livepatch modules and is made accessible by the module loader through
module->klp_info, which is a :c:type:`klp_modinfo` struct. When a livepatch module
loads, this struct is filled in by the module loader.
요약·해설
module-elf-format.rst:1-305라이브패치 모듈은 모듈 로더의 `apply_relocate_add()`를 재사용하기 위해 section header, symbol table, relocation index를 보존합니다.
`.klp.rela.<object>.<section>`과 `.klp.sym.<object>.<symbol>,<position>` 규칙은 relocation 적용 대상과 local·unexported symbol의 소속을 명시합니다.
대상 module이 늦게 적재되는 경우에도 symbol을 먼저 해석한 뒤 보존된 index로 relocation을 적용하며, 원래 symbol table 순서를 정확히 유지해야 합니다.