← Documents Documentation/dev-tools/testing-overview.rst GitHub 원문 ↗

Linux 6.18.37 · Dev Tools

Kernel Testing Guide

KUnit과 kselftest, coverage, dynamic analyzer와 static analyzer의 차이와 선택 기준을 설명합니다.

Source pathDocumentation/dev-tools/testing-overview.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약과 해설

testing-overview.rst:1-182

Kernel 내부 unit과 codepath는 KUnit, userspace interface를 통한 전체 feature는 kselftest가 적합합니다. gcov와 KCOV는 test가 실행한 code 범위를 서로 다른 granularity로 측정합니다.

Dynamic analyzer는 test 중 실제 bug class를 탐지하고 static analyzer는 compile time source pattern과 value flow를 검사합니다. Sparse, Smatch와 Coccinelle은 type, flow, semantic patch라는 서로 다른 강점을 조합합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ====================
4 Kernel Testing Guide
5 ====================
6
7
8 There are a number of different tools for testing the Linux kernel, so knowing
9 when to use each of them can be a challenge. This document provides a rough
10 overview of their differences, and how they fit together.
11
12
13 Writing and Running Tests
14 =========================
15
16 The bulk of kernel tests are written using either the kselftest or KUnit
17 frameworks. These both provide infrastructure to help make running tests and
18 groups of tests easier, as well as providing helpers to aid in writing new
19 tests.
20
21 If you're looking to verify the behaviour of the Kernel — particularly specific
22 parts of the kernel — then you'll want to use KUnit or kselftest.
23
24
25 The Difference Between KUnit and kselftest
26 ------------------------------------------
27
28 KUnit (Documentation/dev-tools/kunit/index.rst) is an entirely in-kernel system
29 for "white box" testing: because test code is part of the kernel, it can access
30 internal structures and functions which aren't exposed to userspace.
31
32 KUnit tests therefore are best written against small, self-contained parts
33 of the kernel, which can be tested in isolation. This aligns well with the
34 concept of 'unit' testing.
35
36 For example, a KUnit test might test an individual kernel function (or even a
37 single codepath through a function, such as an error handling case), rather
38 than a feature as a whole.
39
40 This also makes KUnit tests very fast to build and run, allowing them to be
41 run frequently as part of the development process.
42
43 There is a KUnit test style guide which may give further pointers in
44 Documentation/dev-tools/kunit/style.rst
45
46
47 kselftest (Documentation/dev-tools/kselftest.rst), on the other hand, is
48 largely implemented in userspace, and tests are normal userspace scripts or
49 programs.
50
51 This makes it easier to write more complicated tests, or tests which need to
52 manipulate the overall system state more (e.g., spawning processes, etc.).
53 However, it's not possible to call kernel functions directly from kselftest.
54 This means that only kernel functionality which is exposed to userspace somehow
55 (e.g. by a syscall, device, filesystem, etc.) can be tested with kselftest. To
56 work around this, some tests include a companion kernel module which exposes
57 more information or functionality. If a test runs mostly or entirely within the
58 kernel, however, KUnit may be the more appropriate tool.
59
60 kselftest is therefore suited well to tests of whole features, as these will
61 expose an interface to userspace, which can be tested, but not implementation
62 details. This aligns well with 'system' or 'end-to-end' testing.
63
64 For example, all new system calls should be accompanied by kselftest tests.
65
66 Code Coverage Tools
67 ===================
68
69 The Linux Kernel supports two different code coverage measurement tools. These
70 can be used to verify that a test is executing particular functions or lines
71 of code. This is useful for determining how much of the kernel is being tested,
72 and for finding corner-cases which are not covered by the appropriate test.
73
74 Documentation/dev-tools/gcov.rst is GCC's coverage testing tool, which can be
75 used with the kernel to get global or per-module coverage. Unlike KCOV, it
76 does not record per-task coverage. Coverage data can be read from debugfs,
77 and interpreted using the usual gcov tooling.
78
79 Documentation/dev-tools/kcov.rst is a feature which can be built in to the
80 kernel to allow capturing coverage on a per-task level. It's therefore useful
81 for fuzzing and other situations where information about code executed during,
82 for example, a single syscall is useful.
83
84
85 Dynamic Analysis Tools
86 ======================
87
88 The kernel also supports a number of dynamic analysis tools, which attempt to
89 detect classes of issues when they occur in a running kernel. These typically
90 each look for a different class of bugs, such as invalid memory accesses,
91 concurrency issues such as data races, or other undefined behaviour like
92 integer overflows.
93
94 Some of these tools are listed below:
95
96 * kmemleak detects possible memory leaks. See
97 Documentation/dev-tools/kmemleak.rst
98 * KASAN detects invalid memory accesses such as out-of-bounds and
99 use-after-free errors. See Documentation/dev-tools/kasan.rst
100 * UBSAN detects behaviour that is undefined by the C standard, like integer
101 overflows. See Documentation/dev-tools/ubsan.rst
102 * KCSAN detects data races. See Documentation/dev-tools/kcsan.rst
103 * KFENCE is a low-overhead detector of memory issues, which is much faster than
104 KASAN and can be used in production. See Documentation/dev-tools/kfence.rst
105 * lockdep is a locking correctness validator. See
106 Documentation/locking/lockdep-design.rst
107 * Runtime Verification (RV) supports checking specific behaviours for a given
108 subsystem. See Documentation/trace/rv/runtime-verification.rst
109 * There are several other pieces of debug instrumentation in the kernel, many
110 of which can be found in lib/Kconfig.debug
111
112 These tools tend to test the kernel as a whole, and do not "pass" like
113 kselftest or KUnit tests. They can be combined with KUnit or kselftest by
114 running tests on a kernel with these tools enabled: you can then be sure
115 that none of these errors are occurring during the test.
116
117 Some of these tools integrate with KUnit or kselftest and will
118 automatically fail tests if an issue is detected.
119
120 Static Analysis Tools
121 =====================
122
123 In addition to testing a running kernel, one can also analyze kernel source code
124 directly (**at compile time**) using **static analysis** tools. The tools
125 commonly used in the kernel allow one to inspect the whole source tree or just
126 specific files within it. They make it easier to detect and fix problems during
127 the development process.
128
129 Sparse can help test the kernel by performing type-checking, lock checking,
130 value range checking, in addition to reporting various errors and warnings while
131 examining the code. See the Documentation/dev-tools/sparse.rst documentation
132 page for details on how to use it.
133
134 Smatch extends Sparse and provides additional checks for programming logic
135 mistakes such as missing breaks in switch statements, unused return values on
136 error checking, forgetting to set an error code in the return of an error path,
137 etc. Smatch also has tests against more serious issues such as integer
138 overflows, null pointer dereferences, and memory leaks. See the project page at
139 http://smatch.sourceforge.net/.
140
141 Coccinelle is another static analyzer at our disposal. Coccinelle is often used
142 to aid refactoring and collateral evolution of source code, but it can also help
143 to avoid certain bugs that occur in common code patterns. The types of tests
144 available include API tests, tests for correct usage of kernel iterators, checks
145 for the soundness of free operations, analysis of locking behavior, and further
146 tests known to help keep consistent kernel usage. See the
147 Documentation/dev-tools/coccinelle.rst documentation page for details.
148
149 Beware, though, that static analysis tools suffer from **false positives**.
150 Errors and warns need to be evaluated carefully before attempting to fix them.
151
152 When to use Sparse and Smatch
153 -----------------------------
154
155 Sparse does type checking, such as verifying that annotated variables do not
156 cause endianness bugs, detecting places that use ``__user`` pointers improperly,
157 and analyzing the compatibility of symbol initializers.
158
159 Smatch does flow analysis and, if allowed to build the function database, it
160 also does cross function analysis. Smatch tries to answer questions like where
161 is this buffer allocated? How big is it? Can this index be controlled by the
162 user? Is this variable larger than that variable?
163
164 It's generally easier to write checks in Smatch than it is to write checks in
165 Sparse. Nevertheless, there are some overlaps between Sparse and Smatch checks.
166
167 Strong points of Smatch and Coccinelle
168 --------------------------------------
169
170 Coccinelle is probably the easiest for writing checks. It works before the
171 pre-processor so it's easier to check for bugs in macros using Coccinelle.
172 Coccinelle also creates patches for you, which no other tool does.
173
174 For example, with Coccinelle you can do a mass conversion from
175 ``kmalloc(x * size, GFP_KERNEL)`` to ``kmalloc_array(x, size, GFP_KERNEL)``, and
176 that's really useful. If you just created a Smatch warning and try to push the
177 work of converting on to the maintainers they would be annoyed. You'd have to
178 argue about each warning if can really overflow or not.
179
180 Coccinelle does no analysis of variable values, which is the strong point of
181 Smatch. On the other hand, Coccinelle allows you to do simple things in a simple
182 way.
183

3. 한국어 전문 번역

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

Kernel test 작성과 실행 framework

1-65

SPDX 라이선스 식별자: GPL-2.0

Kernel Testing Guide

Linux kernel을 검사하는 tool은 여러 가지이므로 상황마다 무엇을 사용해야 할지 판단하기 어렵습니다. 이 문서는 각 tool의 대략적인 차이와 서로 결합되는 방식을 설명합니다.

Test 작성과 실행

대부분의 kernel test는 kselftest 또는 KUnit framework로 작성합니다. 둘 다 test와 test group을 쉽게 실행하는 infrastructure와 새 test 작성 helper를 제공합니다.

특히 kernel의 특정 부분을 포함한 kernel behavior를 검증하려면 KUnit 또는 kselftest를 사용합니다.

KUnit과 kselftest의 차이

KUnit (`Documentation/dev-tools/kunit/index.rst`)은 완전히 in-kernel에서 동작하는 white-box testing system입니다. Test code가 kernel 일부이므로 userspace에 노출되지 않은 internal structure와 function에 접근할 수 있습니다.

따라서 KUnit test는 isolated하게 검사할 수 있는 작고 self-contained된 kernel 부분에 가장 적합하며 unit testing 개념과 잘 맞습니다.

예를 들어 전체 feature보다 개별 kernel function 또는 error handling case처럼 하나의 function 안에 있는 특정 codepath를 검사할 수 있습니다.

KUnit test는 build와 실행이 매우 빨라 development process에서 자주 실행할 수 있습니다. 추가 지침은 `Documentation/dev-tools/kunit/style.rst`의 style guide를 참조하십시오.

반면 kselftest (`Documentation/dev-tools/kselftest.rst`)는 대부분 userspace에서 구현되며 test는 일반 userspace script 또는 program입니다.

복잡한 test나 process spawn처럼 전체 system state를 많이 조작하는 test를 쉽게 작성할 수 있습니다. 하지만 kernel function을 직접 호출할 수 없어 syscall, device, filesystem 등 userspace에 노출된 kernel 기능만 검사할 수 있습니다.

일부 test는 이 한계를 보완하려고 추가 정보나 기능을 노출하는 companion kernel module을 포함합니다. 그러나 test가 대부분 또는 전부 kernel 안에서 실행된다면 KUnit이 더 적합할 수 있습니다.

Kselftest는 userspace interface를 통해 implementation detail이 아닌 전체 feature를 검사하므로 system 또는 end-to-end testing에 잘 맞습니다. 모든 새 system call에는 kselftest test가 함께 제공되어야 합니다.

KUnit과 kselftest 선택
항목KUnitkselftest
실행 위치Kernel 내부주로 userspace
접근Internal function과 structureSyscall, device, filesystem interface
적합한 범위작은 unit과 특정 codepath전체 feature와 end-to-end behavior
속도와 상태빠르고 isolated복잡한 system state 조작 가능
Kernel helperTest code 자체가 kernel 일부필요하면 companion module

실행 위치, 접근 범위와 적합한 test level을 비교합니다.

Code coverage tool

66-84

Code coverage tool

Linux kernel은 서로 다른 code coverage measurement tool 두 가지를 지원합니다. Test가 특정 function 또는 source line을 실행하는지 검증해 검사된 kernel 범위를 측정하고 아직 다루지 않은 corner case를 찾는 데 사용합니다.

`Documentation/dev-tools/gcov.rst`는 GCC coverage testing tool입니다. Kernel 전체 또는 module별 coverage를 얻을 수 있고 KCOV와 달리 task별 coverage는 기록하지 않습니다. Debugfs에서 data를 읽어 일반 gcov tooling으로 해석합니다.

`Documentation/dev-tools/kcov.rst`는 kernel에 build할 수 있는 feature로 task별 coverage를 수집합니다. Fuzzing이나 단일 syscall 실행 중 어떤 code가 실행되었는지 알아야 하는 상황에 유용합니다.

Kernel coverage tool 비교
ToolGranularityData와 use case
gcovGlobal 또는 per-moduledebugfs data, 일반 gcov tooling
KCOVPer-taskFuzzing과 단일 syscall execution 추적

Coverage granularity와 대표 use case를 구분했습니다.

Dynamic analysis tool

85-119

Dynamic analysis tool

Kernel은 실행 중 발생하는 문제 class를 탐지하는 여러 dynamic analysis tool을 지원합니다. Invalid memory access, data race 같은 concurrency issue, integer overflow 같은 undefined behavior 등 tool마다 다른 bug class를 검사합니다.

`kmemleak`은 가능한 memory leak을 탐지합니다. `Documentation/dev-tools/kmemleak.rst`를 참조하십시오.

KASAN은 out-of-bounds와 use-after-free 같은 invalid memory access를 탐지합니다. `Documentation/dev-tools/kasan.rst`를 참조하십시오.

UBSAN은 integer overflow처럼 C standard가 undefined로 규정한 behavior를 탐지합니다. `Documentation/dev-tools/ubsan.rst`를 참조하십시오.

KCSAN은 data race를 탐지합니다. `Documentation/dev-tools/kcsan.rst`를 참조하십시오.

KFENCE는 KASAN보다 훨씬 빠르고 production에서도 사용할 수 있는 low-overhead memory issue detector입니다. `Documentation/dev-tools/kfence.rst`를 참조하십시오.

Lockdep은 locking correctness validator입니다. `Documentation/locking/lockdep-design.rst`를 참조하십시오.

Runtime Verification, 즉 RV는 특정 subsystem의 지정 behavior를 검사합니다. `Documentation/trace/rv/runtime-verification.rst`를 참조하십시오.

그 밖의 debug instrumentation도 많으며 상당수는 `lib/Kconfig.debug`에 있습니다.

이 tool들은 보통 kernel 전체를 검사하며 kselftest나 KUnit처럼 pass 결과를 직접 내지 않습니다. Tool을 활성화한 kernel에서 KUnit 또는 kselftest를 실행하면 test 중 해당 error가 발생하지 않았음을 함께 검증할 수 있습니다.

일부 tool은 KUnit 또는 kselftest와 integration되어 issue가 탐지되면 test를 자동 실패시킵니다.

Dynamic analyzer와 탐지 대상
Tool대표 탐지 대상특성
kmemleakPossible memory leakKernel 전체 관찰
KASANOut-of-bounds, use-after-free정밀 memory checking
UBSANC undefined behaviorInteger overflow 등
KCSANData raceConcurrency issue
KFENCEMemory issueLow overhead, production 가능
lockdepLocking correctnessLock dependency 검증
RVSubsystem-specific behaviorRuntime specification 검증

실행 중 찾는 대표 bug class와 사용 특성을 정리했습니다.

Static analysis tool

120-151

Static analysis tool

실행 중인 kernel을 검사하는 것 외에도 compile time에 static analysis tool로 kernel source code를 직접 분석할 수 있습니다. Kernel에서 흔히 쓰는 tool은 전체 source tree 또는 특정 file을 검사해 development 중 문제를 쉽게 찾아 고치도록 돕습니다.

Sparse는 type checking, lock checking, value range checking을 수행하고 code를 검사하면서 여러 error와 warning을 report합니다. 사용법은 `Documentation/dev-tools/sparse.rst`를 참조하십시오.

Smatch는 Sparse를 확장해 switch statement의 missing break, error checking에서 사용하지 않은 return value, error path에서 error code를 설정하지 않은 문제 같은 programming logic mistake를 추가 검사합니다.

Smatch는 integer overflow, null pointer dereference, memory leak 같은 더 심각한 issue도 검사합니다. Project page는 `http://smatch.sourceforge.net/`입니다.

Coccinelle은 source code refactoring과 collateral evolution에 자주 사용되지만 흔한 code pattern의 bug도 방지합니다. API 사용, kernel iterator의 올바른 사용, free operation의 soundness, locking behavior와 일관된 kernel usage를 검사할 수 있습니다.

자세한 내용은 `Documentation/dev-tools/coccinelle.rst`를 참조하십시오.

주의: Static analysis tool은 false positive를 냅니다. Error와 warning을 수정하기 전에 실제 문제인지 주의 깊게 평가해야 합니다.

Sparse, Smatch와 Coccinelle 선택

152-182

Sparse와 Smatch를 사용할 때

Sparse는 annotation된 variable이 endianness bug를 일으키지 않는지, `__user` pointer가 잘못 사용되는지, symbol initializer가 호환되는지 같은 type checking을 수행합니다.

Smatch는 flow analysis를 수행하며 function database build를 허용하면 cross-function analysis도 수행합니다. Buffer가 어디서 할당되는지, 크기가 얼마인지, index를 user가 제어할 수 있는지, 한 variable이 다른 variable보다 큰지를 추론합니다.

일반적으로 Sparse보다 Smatch에서 check를 작성하기 쉽지만 두 tool의 검사 범위에는 일부 overlap이 있습니다.

Smatch와 Coccinelle의 강점

Coccinelle은 check 작성이 가장 쉬운 편입니다. Preprocessor 전에 동작하므로 macro bug를 검사하기 쉽고 다른 tool과 달리 patch도 생성합니다.

예를 들어 `kmalloc(x * size, GFP_KERNEL)`를 `kmalloc_array(x, size, GFP_KERNEL)`로 대량 변환할 수 있습니다. Smatch warning만 만들어 maintainer에게 변환 작업을 넘기면 각 warning이 실제 overflow 가능한지 논쟁하고 직접 고쳐야 하므로 부담이 됩니다.

Coccinelle은 variable value 분석을 하지 않으며 이 부분은 Smatch의 강점입니다. 반면 Coccinelle은 단순한 작업을 단순한 방식으로 수행할 수 있습니다.