← Documents Documentation/security/self-protection.rst GitHub 원문 ↗

Linux 6.18.37 · Security

커널 자기 보호

커널 공격 표면 축소, strict RWX, memory integrity, KASLR, 주소·메모리 정보 노출 방지 원칙을 설명합니다.

Source pathDocumentation/security/self-protection.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

self-protection.rst:1-316

커널 공격 표면 축소, strict RWX, memory integrity, KASLR, 주소·메모리 정보 노출 방지 원칙을 설명합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ======================
2 Kernel Self-Protection
3 ======================
4
5 Kernel self-protection is the design and implementation of systems and
6 structures within the Linux kernel to protect against security flaws in
7 the kernel itself. This covers a wide range of issues, including removing
8 entire classes of bugs, blocking security flaw exploitation methods,
9 and actively detecting attack attempts. Not all topics are explored in
10 this document, but it should serve as a reasonable starting point and
11 answer any frequently asked questions. (Patches welcome, of course!)
12
13 In the worst-case scenario, we assume an unprivileged local attacker
14 has arbitrary read and write access to the kernel's memory. In many
15 cases, bugs being exploited will not provide this level of access,
16 but with systems in place that defend against the worst case we'll
17 cover the more limited cases as well. A higher bar, and one that should
18 still be kept in mind, is protecting the kernel against a _privileged_
19 local attacker, since the root user has access to a vastly increased
20 attack surface. (Especially when they have the ability to load arbitrary
21 kernel modules.)
22
23 The goals for successful self-protection systems would be that they
24 are effective, on by default, require no opt-in by developers, have no
25 performance impact, do not impede kernel debugging, and have tests. It
26 is uncommon that all these goals can be met, but it is worth explicitly
27 mentioning them, since these aspects need to be explored, dealt with,
28 and/or accepted.
29
30
31 Attack Surface Reduction
32 ========================
33
34 The most fundamental defense against security exploits is to reduce the
35 areas of the kernel that can be used to redirect execution. This ranges
36 from limiting the exposed APIs available to userspace, making in-kernel
37 APIs hard to use incorrectly, minimizing the areas of writable kernel
38 memory, etc.
39
40 Strict kernel memory permissions
41 --------------------------------
42
43 When all of kernel memory is writable, it becomes trivial for attacks
44 to redirect execution flow. To reduce the availability of these targets
45 the kernel needs to protect its memory with a tight set of permissions.
46
47 Executable code and read-only data must not be writable
48 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49
50 Any areas of the kernel with executable memory must not be writable.
51 While this obviously includes the kernel text itself, we must consider
52 all additional places too: kernel modules, JIT memory, etc. (There are
53 temporary exceptions to this rule to support things like instruction
54 alternatives, breakpoints, kprobes, etc. If these must exist in a
55 kernel, they are implemented in a way where the memory is temporarily
56 made writable during the update, and then returned to the original
57 permissions.)
58
59 In support of this are ``CONFIG_STRICT_KERNEL_RWX`` and
60 ``CONFIG_STRICT_MODULE_RWX``, which seek to make sure that code is not
61 writable, data is not executable, and read-only data is neither writable
62 nor executable.
63
64 Most architectures have these options on by default and not user selectable.
65 For some architectures like arm that wish to have these be selectable,
66 the architecture Kconfig can select ARCH_OPTIONAL_KERNEL_RWX to enable
67 a Kconfig prompt. ``CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT`` determines
68 the default setting when ARCH_OPTIONAL_KERNEL_RWX is enabled.
69
70 Function pointers and sensitive variables must not be writable
71 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72
73 Vast areas of kernel memory contain function pointers that are looked
74 up by the kernel and used to continue execution (e.g. descriptor/vector
75 tables, file/network/etc operation structures, etc). The number of these
76 variables must be reduced to an absolute minimum.
77
78 Many such variables can be made read-only by setting them "const"
79 so that they live in the .rodata section instead of the .data section
80 of the kernel, gaining the protection of the kernel's strict memory
81 permissions as described above.
82
83 For variables that are initialized once at ``__init`` time, these can
84 be marked with the ``__ro_after_init`` attribute.
85
86 What remains are variables that are updated rarely (e.g. GDT). These
87 will need another infrastructure (similar to the temporary exceptions
88 made to kernel code mentioned above) that allow them to spend the rest
89 of their lifetime read-only. (For example, when being updated, only the
90 CPU thread performing the update would be given uninterruptible write
91 access to the memory.)
92
93 Segregation of kernel memory from userspace memory
94 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
95
96 The kernel must never execute userspace memory. The kernel must also never
97 access userspace memory without explicit expectation to do so. These
98 rules can be enforced either by support of hardware-based restrictions
99 (x86's SMEP/SMAP, ARM's PXN/PAN) or via emulation (ARM's Memory Domains).
100 By blocking userspace memory in this way, execution and data parsing
101 cannot be passed to trivially-controlled userspace memory, forcing
102 attacks to operate entirely in kernel memory.
103
104 Reduced access to syscalls
105 --------------------------
106
107 One trivial way to eliminate many syscalls for 64-bit systems is building
108 without ``CONFIG_COMPAT``. However, this is rarely a feasible scenario.
109
110 The "seccomp" system provides an opt-in feature made available to
111 userspace, which provides a way to reduce the number of kernel entry
112 points available to a running process. This limits the breadth of kernel
113 code that can be reached, possibly reducing the availability of a given
114 bug to an attack.
115
116 An area of improvement would be creating viable ways to keep access to
117 things like compat, user namespaces, BPF creation, and perf limited only
118 to trusted processes. This would keep the scope of kernel entry points
119 restricted to the more regular set of normally available to unprivileged
120 userspace.
121
122 Restricting access to kernel modules
123 ------------------------------------
124
125 The kernel should never allow an unprivileged user the ability to
126 load specific kernel modules, since that would provide a facility to
127 unexpectedly extend the available attack surface. (The on-demand loading
128 of modules via their predefined subsystems, e.g. MODULE_ALIAS_*, is
129 considered "expected" here, though additional consideration should be
130 given even to these.) For example, loading a filesystem module via an
131 unprivileged socket API is nonsense: only the root or physically local
132 user should trigger filesystem module loading. (And even this can be up
133 for debate in some scenarios.)
134
135 To protect against even privileged users, systems may need to either
136 disable module loading entirely (e.g. monolithic kernel builds or
137 modules_disabled sysctl), or provide signed modules (e.g.
138 ``CONFIG_MODULE_SIG_FORCE``, or dm-crypt with LoadPin), to keep from having
139 root load arbitrary kernel code via the module loader interface.
140
141
142 Memory integrity
143 ================
144
145 There are many memory structures in the kernel that are regularly abused
146 to gain execution control during an attack, By far the most commonly
147 understood is that of the stack buffer overflow in which the return
148 address stored on the stack is overwritten. Many other examples of this
149 kind of attack exist, and protections exist to defend against them.
150
151 Stack buffer overflow
152 ---------------------
153
154 The classic stack buffer overflow involves writing past the expected end
155 of a variable stored on the stack, ultimately writing a controlled value
156 to the stack frame's stored return address. The most widely used defense
157 is the presence of a stack canary between the stack variables and the
158 return address (``CONFIG_STACKPROTECTOR``), which is verified just before
159 the function returns. Other defenses include things like shadow stacks.
160
161 Stack depth overflow
162 --------------------
163
164 A less well understood attack is using a bug that triggers the
165 kernel to consume stack memory with deep function calls or large stack
166 allocations. With this attack it is possible to write beyond the end of
167 the kernel's preallocated stack space and into sensitive structures. Two
168 important changes need to be made for better protections: moving the
169 sensitive thread_info structure elsewhere, and adding a faulting memory
170 hole at the bottom of the stack to catch these overflows.
171
172 Heap memory integrity
173 ---------------------
174
175 The structures used to track heap free lists can be sanity-checked during
176 allocation and freeing to make sure they aren't being used to manipulate
177 other memory areas.
178
179 Counter integrity
180 -----------------
181
182 Many places in the kernel use atomic counters to track object references
183 or perform similar lifetime management. When these counters can be made
184 to wrap (over or under) this traditionally exposes a use-after-free
185 flaw. By trapping atomic wrapping, this class of bug vanishes.
186
187 Size calculation overflow detection
188 -----------------------------------
189
190 Similar to counter overflow, integer overflows (usually size calculations)
191 need to be detected at runtime to kill this class of bug, which
192 traditionally leads to being able to write past the end of kernel buffers.
193
194
195 Probabilistic defenses
196 ======================
197
198 While many protections can be considered deterministic (e.g. read-only
199 memory cannot be written to), some protections provide only statistical
200 defense, in that an attack must gather enough information about a
201 running system to overcome the defense. While not perfect, these do
202 provide meaningful defenses.
203
204 Canaries, blinding, and other secrets
205 -------------------------------------
206
207 It should be noted that things like the stack canary discussed earlier
208 are technically statistical defenses, since they rely on a secret value,
209 and such values may become discoverable through an information exposure
210 flaw.
211
212 Blinding literal values for things like JITs, where the executable
213 contents may be partially under the control of userspace, need a similar
214 secret value.
215
216 It is critical that the secret values used must be separate (e.g.
217 different canary per stack) and high entropy (e.g. is the RNG actually
218 working?) in order to maximize their success.
219
220 Kernel Address Space Layout Randomization (KASLR)
221 -------------------------------------------------
222
223 Since the location of kernel memory is almost always instrumental in
224 mounting a successful attack, making the location non-deterministic
225 raises the difficulty of an exploit. (Note that this in turn makes
226 the value of information exposures higher, since they may be used to
227 discover desired memory locations.)
228
229 Text and module base
230 ~~~~~~~~~~~~~~~~~~~~
231
232 By relocating the physical and virtual base address of the kernel at
233 boot-time (``CONFIG_RANDOMIZE_BASE``), attacks needing kernel code will be
234 frustrated. Additionally, offsetting the module loading base address
235 means that even systems that load the same set of modules in the same
236 order every boot will not share a common base address with the rest of
237 the kernel text.
238
239 Stack base
240 ~~~~~~~~~~
241
242 If the base address of the kernel stack is not the same between processes,
243 or even not the same between syscalls, targets on or beyond the stack
244 become more difficult to locate.
245
246 Dynamic memory base
247 ~~~~~~~~~~~~~~~~~~~
248
249 Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up
250 being relatively deterministic in layout due to the order of early-boot
251 initializations. If the base address of these areas is not the same
252 between boots, targeting them is frustrated, requiring an information
253 exposure specific to the region.
254
255 Structure layout
256 ~~~~~~~~~~~~~~~~
257
258 By performing a per-build randomization of the layout of sensitive
259 structures, attacks must either be tuned to known kernel builds or expose
260 enough kernel memory to determine structure layouts before manipulating
261 them.
262
263
264 Preventing Information Exposures
265 ================================
266
267 Since the locations of sensitive structures are the primary target for
268 attacks, it is important to defend against exposure of both kernel memory
269 addresses and kernel memory contents (since they may contain kernel
270 addresses or other sensitive things like canary values).
271
272 Kernel addresses
273 ----------------
274
275 Printing kernel addresses to userspace leaks sensitive information about
276 the kernel memory layout. Care should be exercised when using any printk
277 specifier that prints the raw address, currently %px, %p[ad], (and %p[sSb]
278 in certain circumstances [*]). Any file written to using one of these
279 specifiers should be readable only by privileged processes.
280
281 Kernels 4.14 and older printed the raw address using %p. As of 4.15-rc1
282 addresses printed with the specifier %p are hashed before printing.
283
284 [*] If KALLSYMS is enabled and symbol lookup fails, the raw address is
285 printed. If KALLSYMS is not enabled the raw address is printed.
286
287 Unique identifiers
288 ------------------
289
290 Kernel memory addresses must never be used as identifiers exposed to
291 userspace. Instead, use an atomic counter, an idr, or similar unique
292 identifier.
293
294 Memory initialization
295 ---------------------
296
297 Memory copied to userspace must always be fully initialized. If not
298 explicitly memset(), this will require changes to the compiler to make
299 sure structure holes are cleared.
300
301 Memory poisoning
302 ----------------
303
304 When releasing memory, it is best to poison the contents, to avoid reuse
305 attacks that rely on the old contents of memory. E.g., clear stack on a
306 syscall return (``CONFIG_KSTACK_ERASE``), wipe heap memory on a
307 free. This frustrates many uninitialized variable attacks, stack content
308 exposures, heap content exposures, and use-after-free attacks.
309
310 Destination tracking
311 --------------------
312
313 To help kill classes of bugs that result in kernel addresses being
314 written to userspace, the destination of writes needs to be tracked. If
315 the buffer is destined for userspace (e.g. seq_file backed ``/proc`` files),
316 it should automatically censor sensitive values.
317

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

위협 모델과 성공 조건

1-30

Kernel self-protection은 커널 자체의 보안 결함을 방어하기 위한 시스템과 구조를 설계·구현하는 작업이다. 전체 bug class 제거, exploit 기법 차단, 공격 시도 능동 탐지를 포함한다. 모든 주제를 다루지는 않지만 출발점과 자주 묻는 질문에 대한 답을 제공한다.

최악의 경우 권한 없는 local attacker가 kernel memory를 임의로 읽고 쓸 수 있다고 가정한다. 실제 bug는 더 제한된 접근만 줄 수 있지만 최악을 방어하면 제한된 사례도 포괄할 수 있다. 더 높은 목표는 root가 훨씬 넓은 공격 표면, 특히 임의 kernel module 적재 권한을 가지므로 privileged local attacker에게서도 커널을 보호하는 것이다.

성공적인 자기 보호는 효과적이고 기본 활성화되며 개발자의 opt-in이 필요 없고 성능 영향과 debugging 방해가 없으며 test를 갖춰야 한다. 모든 조건을 동시에 만족하기 어렵더라도 각 조건의 비용과 tradeoff를 명시적으로 검토하고 수용해야 한다.

자기 보호 목표
기준의미
Effective실제 공격 기법을 차단
On by default사용자가 따로 켜지 않아도 적용
No developer opt-in개별 코드가 보호를 요청할 필요 없음
No performance impact정상 경로 비용 최소화
Debugging compatible커널 분석을 방해하지 않음
Tested회귀 검증 보유

보호 기능이 배포 가능한 기본 방어가 되기 위한 기준이다.

======================
Kernel Self-Protection
======================

Kernel self-protection is the design and implementation of systems and
structures within the Linux kernel to protect against security flaws in
the kernel itself. This covers a wide range of issues, including removing
entire classes of bugs, blocking security flaw exploitation methods,
and actively detecting attack attempts. Not all topics are explored in
this document, but it should serve as a reasonable starting point and
answer any frequently asked questions. (Patches welcome, of course!)

In the worst-case scenario, we assume an unprivileged local attacker
has arbitrary read and write access to the kernel's memory. In many
cases, bugs being exploited will not provide this level of access,
but with systems in place that defend against the worst case we'll
cover the more limited cases as well. A higher bar, and one that should
still be kept in mind, is protecting the kernel against a _privileged_
local attacker, since the root user has access to a vastly increased
attack surface. (Especially when they have the ability to load arbitrary
kernel modules.)

The goals for successful self-protection systems would be that they
are effective, on by default, require no opt-in by developers, have no
performance impact, do not impede kernel debugging, and have tests. It
is uncommon that all these goals can be met, but it is worth explicitly
mentioning them, since these aspects need to be explored, dealt with,
and/or accepted.

공격 표면 축소와 엄격한 메모리 권한

31-69

가장 근본적인 방어는 공격자가 실행 흐름을 바꾸는 데 사용할 수 있는 커널 영역을 줄이는 것이다. 사용자 공간에 노출된 API를 제한하고, 커널 내부 API를 잘못 쓰기 어렵게 만들며, writable kernel memory를 최소화해야 한다.

kernel memory 전체가 writable이면 실행 흐름을 바꾸기 쉽다. executable memory는 kernel text뿐 아니라 module과 JIT memory를 포함해 writable이어서는 안 된다. instruction alternative, breakpoint, kprobe 같은 기능이 임시 쓰기를 요구하면 update 동안만 writable로 바꾸고 즉시 원래 권한으로 되돌려야 한다.

`CONFIG_STRICT_KERNEL_RWX`와 `CONFIG_STRICT_MODULE_RWX`는 code가 writable하지 않고 data가 executable하지 않으며 read-only data가 writable·executable하지 않게 한다. 대부분 architecture는 기본으로 켜고 사용자가 선택하지 못하게 한다. ARM처럼 선택 가능하게 하려면 Kconfig에서 `ARCH_OPTIONAL_KERNEL_RWX`를 선택하며 `CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT`가 기본값을 정한다.

엄격한 RWX 정책
영역허용 속성
Kernel/module code실행 가능, 쓰기 금지
일반 data쓰기 가능, 실행 금지
Read-only data쓰기·실행 모두 금지
JIT·patch 임시 update짧은 기간만 쓰기 허용 후 복원

memory의 목적에 따라 쓰기와 실행 권한을 분리한다.

Attack Surface Reduction
========================

The most fundamental defense against security exploits is to reduce the
areas of the kernel that can be used to redirect execution. This ranges
from limiting the exposed APIs available to userspace, making in-kernel
APIs hard to use incorrectly, minimizing the areas of writable kernel
memory, etc.

Strict kernel memory permissions
--------------------------------

When all of kernel memory is writable, it becomes trivial for attacks
to redirect execution flow. To reduce the availability of these targets
the kernel needs to protect its memory with a tight set of permissions.

Executable code and read-only data must not be writable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Any areas of the kernel with executable memory must not be writable.
While this obviously includes the kernel text itself, we must consider
all additional places too: kernel modules, JIT memory, etc. (There are
temporary exceptions to this rule to support things like instruction
alternatives, breakpoints, kprobes, etc. If these must exist in a
kernel, they are implemented in a way where the memory is temporarily
made writable during the update, and then returned to the original
permissions.)

In support of this are ``CONFIG_STRICT_KERNEL_RWX`` and
``CONFIG_STRICT_MODULE_RWX``, which seek to make sure that code is not
writable, data is not executable, and read-only data is neither writable
nor executable.

Most architectures have these options on by default and not user selectable.
For some architectures like arm that wish to have these be selectable,
the architecture Kconfig can select ARCH_OPTIONAL_KERNEL_RWX to enable
a Kconfig prompt. ``CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT`` determines
the default setting when ARCH_OPTIONAL_KERNEL_RWX is enabled.

Function pointer 보호와 사용자 memory 격리

70-103

descriptor/vector table과 file·network operation 구조 등 넓은 kernel memory에는 다음 실행 위치로 쓰이는 function pointer가 있다. 이런 변수의 수를 최소화해야 한다. 가능한 변수는 `const`로 선언해 `.data` 대신 `.rodata`에 두고 strict memory permission의 보호를 받게 한다.

`__init` 시 한 번만 초기화하는 변수는 `__ro_after_init`로 표시할 수 있다. GDT처럼 드물게 갱신되는 변수에는 평생 대부분을 read-only로 유지하면서 갱신 CPU thread에만 중단 불가능한 write access를 잠깐 허용하는 별도 인프라가 필요하다.

커널은 사용자 공간 memory를 절대 실행해서는 안 되고, 명시적으로 예상한 경우 외에는 접근해서도 안 된다. x86 SMEP/SMAP, ARM PXN/PAN 같은 hardware restriction이나 ARM Memory Domains 같은 emulation으로 강제한다. 사용자 memory를 차단하면 공격자는 쉽게 제어할 수 있는 영역으로 실행이나 data parsing을 넘기지 못하고 kernel memory 안에서만 공격해야 한다.

민감 변수의 수명
const 가능 여부 판단.rodata에 배치초기화 전용이면 __ro_after_init드문 갱신은 한 CPU에 임시 write즉시 read-only 복원

초기화와 드문 갱신 시점을 제외하고 function pointer와 민감 값을 read-only로 유지한다.

Function pointers and sensitive variables must not be writable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Vast areas of kernel memory contain function pointers that are looked
up by the kernel and used to continue execution (e.g. descriptor/vector
tables, file/network/etc operation structures, etc). The number of these
variables must be reduced to an absolute minimum.

Many such variables can be made read-only by setting them "const"
so that they live in the .rodata section instead of the .data section
of the kernel, gaining the protection of the kernel's strict memory
permissions as described above.

For variables that are initialized once at ``__init`` time, these can
be marked with the ``__ro_after_init`` attribute.

What remains are variables that are updated rarely (e.g. GDT). These
will need another infrastructure (similar to the temporary exceptions
made to kernel code mentioned above) that allow them to spend the rest
of their lifetime read-only. (For example, when being updated, only the
CPU thread performing the update would be given uninterruptible write
access to the memory.)

Segregation of kernel memory from userspace memory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The kernel must never execute userspace memory. The kernel must also never
access userspace memory without explicit expectation to do so. These
rules can be enforced either by support of hardware-based restrictions
(x86's SMEP/SMAP, ARM's PXN/PAN) or via emulation (ARM's Memory Domains).
By blocking userspace memory in this way, execution and data parsing
cannot be passed to trivially-controlled userspace memory, forcing
attacks to operate entirely in kernel memory.

Syscall과 module 접근 제한

104-140

64비트 시스템에서 `CONFIG_COMPAT` 없이 빌드하면 많은 syscall을 제거할 수 있지만 현실적으로 가능한 경우는 드물다. `seccomp`는 사용자 공간이 opt-in하여 실행 프로세스가 접근할 수 있는 kernel entry point 수를 줄이고, 특정 bug를 공격에 이용할 수 있는 코드 범위를 제한한다.

compat, user namespace, BPF 생성, perf 같은 기능을 신뢰된 프로세스만 사용하도록 제한하는 실용적인 방법이 더 필요하다. 그러면 권한 없는 사용자 공간에 노출되는 kernel entry point를 일반적인 최소 집합으로 유지할 수 있다.

권한 없는 사용자가 특정 kernel module을 직접 적재하게 해서는 안 된다. `MODULE_ALIAS_*`처럼 미리 정의된 subsystem의 on-demand loading은 예상된 것으로 보지만 추가 검토가 필요하다. 예를 들어 권한 없는 socket API로 filesystem module을 적재하는 것은 부적절하며 root나 물리적으로 local인 사용자만 유발해야 한다.

privileged user까지 방어하려면 monolithic kernel이나 `modules_disabled` sysctl로 module loading을 완전히 끄거나, `CONFIG_MODULE_SIG_FORCE` 또는 dm-crypt와 LoadPin 같은 방식으로 signed module만 허용해 root가 loader interface로 임의 kernel code를 넣지 못하게 해야 한다.

Kernel entry 축소
표면축소 수단
Syscallseccomp, 가능한 경우 CONFIG_COMPAT 제거
고위험 기능compat·userns·BPF·perf를 trusted process로 제한
Module loadingmodules_disabled 또는 monolithic build
허용 moduleCONFIG_MODULE_SIG_FORCE, LoadPin

기능별로 신뢰 경계를 좁히는 수단을 정리한다.

Reduced access to syscalls
--------------------------

One trivial way to eliminate many syscalls for 64-bit systems is building
without ``CONFIG_COMPAT``. However, this is rarely a feasible scenario.

The "seccomp" system provides an opt-in feature made available to
userspace, which provides a way to reduce the number of kernel entry
points available to a running process. This limits the breadth of kernel
code that can be reached, possibly reducing the availability of a given
bug to an attack.

An area of improvement would be creating viable ways to keep access to
things like compat, user namespaces, BPF creation, and perf limited only
to trusted processes. This would keep the scope of kernel entry points
restricted to the more regular set of normally available to unprivileged
userspace.

Restricting access to kernel modules
------------------------------------

The kernel should never allow an unprivileged user the ability to
load specific kernel modules, since that would provide a facility to
unexpectedly extend the available attack surface. (The on-demand loading
of modules via their predefined subsystems, e.g. MODULE_ALIAS_*, is
considered "expected" here, though additional consideration should be
given even to these.) For example, loading a filesystem module via an
unprivileged socket API is nonsense: only the root or physically local
user should trigger filesystem module loading. (And even this can be up
for debate in some scenarios.)

To protect against even privileged users, systems may need to either
disable module loading entirely (e.g. monolithic kernel builds or
modules_disabled sysctl), or provide signed modules (e.g.
``CONFIG_MODULE_SIG_FORCE``, or dm-crypt with LoadPin), to keep from having
root load arbitrary kernel code via the module loader interface.

Memory 무결성

141-193

공격자는 여러 kernel memory 구조를 악용해 실행 제어권을 얻는다. 대표적인 stack buffer overflow는 stack의 return address를 덮어쓰는 방식이며, `CONFIG_STACKPROTECTOR`가 stack 변수와 return address 사이의 canary를 함수 반환 직전에 검사한다. shadow stack도 방어 수단이다.

Stack depth overflow는 깊은 함수 호출이나 큰 stack allocation으로 미리 할당된 kernel stack 끝을 넘어 민감 구조에 쓰게 한다. 더 나은 방어를 위해 민감한 `thread_info`를 다른 곳으로 옮기고 stack 아래쪽에 fault를 내는 memory hole을 추가해야 한다.

Heap free list 추적 구조는 allocation과 free 시 sanity check하여 다른 memory를 조작하는 도구로 쓰이지 않게 할 수 있다. object reference나 수명 관리를 위한 atomic counter가 overflow 또는 underflow로 wrap되면 전통적으로 use-after-free가 생기므로 atomic wrapping을 trap하면 이 bug class를 없앨 수 있다.

Counter와 마찬가지로 주로 size calculation에서 생기는 integer overflow도 runtime에 탐지해야 한다. 이를 잡지 못하면 kernel buffer 끝을 넘어 쓸 수 있는 결함으로 이어진다.

Memory integrity 방어
위협방어
Stack buffer overflowstack canary, shadow stack
Stack depth overflowthread_info 이동, guard hole
Heap free list 조작allocation/free sanity check
Atomic counter wrapoverflow·underflow trap
Size calculation overflowruntime integer overflow detection

손상되는 구조와 대응 기법을 연결한다.


Memory integrity
================

There are many memory structures in the kernel that are regularly abused
to gain execution control during an attack, By far the most commonly
understood is that of the stack buffer overflow in which the return
address stored on the stack is overwritten. Many other examples of this
kind of attack exist, and protections exist to defend against them.

Stack buffer overflow
---------------------

The classic stack buffer overflow involves writing past the expected end
of a variable stored on the stack, ultimately writing a controlled value
to the stack frame's stored return address. The most widely used defense
is the presence of a stack canary between the stack variables and the
return address (``CONFIG_STACKPROTECTOR``), which is verified just before
the function returns. Other defenses include things like shadow stacks.

Stack depth overflow
--------------------

A less well understood attack is using a bug that triggers the
kernel to consume stack memory with deep function calls or large stack
allocations. With this attack it is possible to write beyond the end of
the kernel's preallocated stack space and into sensitive structures. Two
important changes need to be made for better protections: moving the
sensitive thread_info structure elsewhere, and adding a faulting memory
hole at the bottom of the stack to catch these overflows.

Heap memory integrity
---------------------

The structures used to track heap free lists can be sanity-checked during
allocation and freeing to make sure they aren't being used to manipulate
other memory areas.

Counter integrity
-----------------

Many places in the kernel use atomic counters to track object references
or perform similar lifetime management. When these counters can be made
to wrap (over or under) this traditionally exposes a use-after-free
flaw. By trapping atomic wrapping, this class of bug vanishes.

Size calculation overflow detection
-----------------------------------

Similar to counter overflow, integer overflows (usually size calculations)
need to be detected at runtime to kill this class of bug, which
traditionally leads to being able to write past the end of kernel buffers.

확률적 방어와 비밀 값

194-219

Read-only memory처럼 결정론적인 보호와 달리, 일부 방어는 공격자가 실행 중인 시스템 정보를 충분히 모아야 우회할 수 있게 하는 통계적 방어다. 완벽하지 않아도 실질적인 방어를 제공한다.

Stack canary는 secret value에 의존하므로 정보 노출 결함으로 값을 알아낼 수 있는 확률적 방어다. 사용자 공간이 executable content 일부를 제어할 수 있는 JIT의 literal value blinding도 비슷한 secret이 필요하다.

성공 가능성을 높이려면 secret value를 서로 분리해야 한다. 예를 들어 stack마다 다른 canary를 사용해야 하며, RNG가 실제로 올바르게 동작하는지 확인하여 높은 entropy를 확보해야 한다.

확률적 방어 조건
고품질 RNG 확인용도·stack별 독립 secret 생성canary·JIT blinding에 적용정보 노출 최소화재사용과 상관관계 차단

공격자가 추측하거나 노출로 회수하기 어려운 독립 비밀을 사용한다.


Probabilistic defenses
======================

While many protections can be considered deterministic (e.g. read-only
memory cannot be written to), some protections provide only statistical
defense, in that an attack must gather enough information about a
running system to overcome the defense. While not perfect, these do
provide meaningful defenses.

Canaries, blinding, and other secrets
-------------------------------------

It should be noted that things like the stack canary discussed earlier
are technically statistical defenses, since they rely on a secret value,
and such values may become discoverable through an information exposure
flaw.

Blinding literal values for things like JITs, where the executable
contents may be partially under the control of userspace, need a similar
secret value.

It is critical that the secret values used must be separate (e.g.
different canary per stack) and high entropy (e.g. is the RNG actually
working?) in order to maximize their success.

KASLR과 layout 무작위화

220-263

성공적인 공격에는 kernel memory 위치가 거의 항상 중요하므로 위치를 비결정적으로 만들면 exploit 난도가 올라간다. 반대로 주소를 찾게 해 주는 정보 노출의 가치가 더 커진다는 점도 고려해야 한다.

`CONFIG_RANDOMIZE_BASE`는 부팅 때 kernel의 physical·virtual base address를 재배치해 kernel code 위치가 필요한 공격을 방해한다. module loading base도 offset하면 같은 module을 같은 순서로 적재하는 시스템도 kernel text와 공통 base를 공유하지 않는다.

프로세스마다 또는 syscall마다 kernel stack base를 다르게 하면 stack 안팎의 target 위치를 찾기 어렵다. `kmalloc`, `vmalloc` 같은 dynamic memory는 early boot 초기화 순서 때문에 비교적 결정적인 layout이 되므로 boot마다 base를 다르게 해 해당 영역에 특화된 정보 노출 없이는 target을 찾지 못하게 해야 한다.

민감한 structure layout을 build마다 무작위화하면 공격자는 알려진 kernel build에 맞추거나 조작 전에 충분한 kernel memory를 노출시켜 실제 layout을 알아내야 한다.

Layout randomization 범위
대상무작위화 시점효과
Kernel textbootphysical·virtual base 변경
Moduleload base동일 적재 순서의 공통 주소 제거
Kernel stackprocess 또는 syscallstack target 위치 불확실
Dynamic memorybootkmalloc·vmalloc base 변경
Structurebuildfield offset 변경

서로 다른 수명 주기에 주소와 field 배치를 무작위화한다.

Kernel Address Space Layout Randomization (KASLR)
-------------------------------------------------

Since the location of kernel memory is almost always instrumental in
mounting a successful attack, making the location non-deterministic
raises the difficulty of an exploit. (Note that this in turn makes
the value of information exposures higher, since they may be used to
discover desired memory locations.)

Text and module base
~~~~~~~~~~~~~~~~~~~~

By relocating the physical and virtual base address of the kernel at
boot-time (``CONFIG_RANDOMIZE_BASE``), attacks needing kernel code will be
frustrated. Additionally, offsetting the module loading base address
means that even systems that load the same set of modules in the same
order every boot will not share a common base address with the rest of
the kernel text.

Stack base
~~~~~~~~~~

If the base address of the kernel stack is not the same between processes,
or even not the same between syscalls, targets on or beyond the stack
become more difficult to locate.

Dynamic memory base
~~~~~~~~~~~~~~~~~~~

Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up
being relatively deterministic in layout due to the order of early-boot
initializations. If the base address of these areas is not the same
between boots, targeting them is frustrated, requiring an information
exposure specific to the region.

Structure layout
~~~~~~~~~~~~~~~~

By performing a per-build randomization of the layout of sensitive
structures, attacks must either be tuned to known kernel builds or expose
enough kernel memory to determine structure layouts before manipulating
them.

Kernel 주소와 식별자 노출 방지

264-293

민감 구조의 위치가 주요 공격 target이므로 kernel memory address와 memory content 노출을 모두 막아야 한다. memory content에는 address뿐 아니라 canary 같은 민감 값도 들어 있을 수 있다.

사용자 공간에 kernel address를 출력하면 memory layout을 누출한다. raw address를 출력하는 `%px`, `%p[ad]`, 특정 조건의 `%p[sSb]`를 사용할 때 주의해야 하며, 이런 specifier로 쓴 파일은 privileged process만 읽을 수 있어야 한다. 4.14 이하 kernel의 `%p`는 raw address를 출력했지만 4.15-rc1부터는 출력 전에 hash한다.

KALLSYMS가 켜져 있어도 symbol lookup이 실패하면 raw address를 출력하며, KALLSYMS가 없을 때도 raw address가 나온다. Kernel memory address를 사용자 공간 식별자로 사용해서는 안 되고 atomic counter, `idr`, 그 밖의 고유 identifier를 사용해야 한다.

주소 출력 위험
경우동작
%px, %p[ad]raw address 출력 가능
%p[sSb]일부 조건에서 raw address
%p, Linux 4.15-rc1 이후출력 전 hash
KALLSYMS lookup 실패raw address 출력
사용자 식별자주소 대신 atomic counter·idr 사용

specifier와 symbol lookup 상태에 따라 raw address 노출 여부가 달라진다.

Preventing Information Exposures
================================

Since the locations of sensitive structures are the primary target for
attacks, it is important to defend against exposure of both kernel memory
addresses and kernel memory contents (since they may contain kernel
addresses or other sensitive things like canary values).

Kernel addresses
----------------

Printing kernel addresses to userspace leaks sensitive information about
the kernel memory layout. Care should be exercised when using any printk
specifier that prints the raw address, currently %px, %p[ad], (and %p[sSb]
in certain circumstances [*]).  Any file written to using one of these
specifiers should be readable only by privileged processes.

Kernels 4.14 and older printed the raw address using %p. As of 4.15-rc1
addresses printed with the specifier %p are hashed before printing.

[*] If KALLSYMS is enabled and symbol lookup fails, the raw address is
printed. If KALLSYMS is not enabled the raw address is printed.

Unique identifiers
------------------

Kernel memory addresses must never be used as identifiers exposed to
userspace. Instead, use an atomic counter, an idr, or similar unique
identifier.

초기화, poisoning, destination 추적

294-316

사용자 공간으로 복사하는 memory는 항상 완전히 초기화해야 한다. 명시적으로 `memset()`하지 않는다면 compiler가 structure hole까지 지우도록 바꿔야 한다.

memory를 해제할 때 내용을 poison하면 이전 내용을 재사용하는 공격을 막을 수 있다. syscall return 때 `CONFIG_KSTACK_ERASE`로 stack을 지우고 free할 때 heap memory를 wipe하면 uninitialized variable 공격, stack·heap content 노출, use-after-free 공격을 어렵게 한다.

Kernel address가 사용자 공간에 기록되는 bug class를 제거하려면 write destination을 추적해야 한다. `seq_file` 기반 `/proc` 파일처럼 buffer 목적지가 사용자 공간이라면 민감 값을 자동으로 검열해야 한다.

사용자 공간 복사 보호
Structure와 padding 완전 초기화write destination이 userspace인지 추적민감 address 자동 검열복사 수행stack·heap 해제 시 poison 또는 wipe

데이터 생성부터 해제까지 노출 가능한 잔여 값을 관리한다.

Memory initialization
---------------------

Memory copied to userspace must always be fully initialized. If not
explicitly memset(), this will require changes to the compiler to make
sure structure holes are cleared.

Memory poisoning
----------------

When releasing memory, it is best to poison the contents, to avoid reuse
attacks that rely on the old contents of memory. E.g., clear stack on a
syscall return (``CONFIG_KSTACK_ERASE``), wipe heap memory on a
free. This frustrates many uninitialized variable attacks, stack content
exposures, heap content exposures, and use-after-free attacks.

Destination tracking
--------------------

To help kill classes of bugs that result in kernel addresses being
written to userspace, the destination of writes needs to be tracked. If
the buffer is destined for userspace (e.g. seq_file backed ``/proc`` files),
it should automatically censor sensitive values.