← Documents Documentation/kbuild/reproducible-builds.rst GitHub 원문 ↗

Linux 6.18.37 · Kbuild

Reproducible Builds

Kernel binary 재현성을 해치는 timestamp, build identity, path, signing, random seed와 Git 상태를 통제하는 방법입니다.

Source pathDocumentation/kbuild/reproducible-builds.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약·해설

reproducible-builds.rst:1-140

재현 가능한 kernel build는 같은 source와 tool에서 동일한 binary를 생성해 build infrastructure의 무결성과 변경 영향을 검증합니다.

시간·user·host·absolute path·temporary signing key·RANDSTRUCT seed·Git identity를 모두 명시적인 input으로 고정해야 합니다.

재현성 점검 순서
Timestamp와 build identity 고정Source·macro path remapSource tree의 generated file 제거Signing key·signature를 명시적 input으로 분리Random seed와 Git state 고정

환경에서 binary로 유입되는 변수를 차례로 제거합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 ===================
2 Reproducible builds
3 ===================
4
5 It is generally desirable that building the same source code with
6 the same set of tools is reproducible, i.e. the output is always
7 exactly the same. This makes it possible to verify that the build
8 infrastructure for a binary distribution or embedded system has not
9 been subverted. This can also make it easier to verify that a source
10 or tool change does not make any difference to the resulting binaries.
11
12 The `Reproducible Builds project`_ has more information about this
13 general topic. This document covers the various reasons why building
14 the kernel may be unreproducible, and how to avoid them.
15
16 Timestamps
17 ----------
18
19 The kernel embeds timestamps in three places:
20
21 * The version string exposed by ``uname()`` and included in
22 ``/proc/version``
23
24 * File timestamps in the embedded initramfs
25
26 * If enabled via ``CONFIG_IKHEADERS``, file timestamps of kernel
27 headers embedded in the kernel or respective module,
28 exposed via ``/sys/kernel/kheaders.tar.xz``
29
30 By default the timestamp is the current time and in the case of
31 ``kheaders`` the various files' modification times. This must
32 be overridden using the `KBUILD_BUILD_TIMESTAMP`_ variable.
33 If you are building from a git commit, you could use its commit date.
34
35 The kernel does *not* use the ``__DATE__`` and ``__TIME__`` macros,
36 and enables warnings if they are used. If you incorporate external
37 code that does use these, you must override the timestamp they
38 correspond to by setting the `SOURCE_DATE_EPOCH`_ environment
39 variable.
40
41 User, host
42 ----------
43
44 The kernel embeds the building user and host names in
45 ``/proc/version``. These must be overridden using the
46 `KBUILD_BUILD_USER and KBUILD_BUILD_HOST`_ variables. If you are
47 building from a git commit, you could use its committer address.
48
49 Absolute filenames
50 ------------------
51
52 When the kernel is built out-of-tree, debug information may include
53 absolute filenames for the source files. This must be overridden by
54 including the ``-fdebug-prefix-map`` option in the `KCFLAGS`_ variable.
55
56 Depending on the compiler used, the ``__FILE__`` macro may also expand
57 to an absolute filename in an out-of-tree build. Kbuild automatically
58 uses the ``-fmacro-prefix-map`` option to prevent this, if it is
59 supported.
60
61 The Reproducible Builds web site has more information about these
62 `prefix-map options`_.
63
64 Some CONFIG options such as `CONFIG_DEBUG_EFI` embed absolute paths in
65 object files. Such options should be disabled.
66
67 Generated files in source packages
68 ----------------------------------
69
70 The build processes for some programs under the ``tools/``
71 subdirectory do not completely support out-of-tree builds. This may
72 cause a later source package build using e.g. ``make rpm-pkg`` to
73 include generated files. You should ensure the source tree is
74 pristine by running ``make mrproper`` or ``git clean -d -f -x`` before
75 building a source package.
76
77 Module signing
78 --------------
79
80 If you enable ``CONFIG_MODULE_SIG_ALL``, the default behaviour is to
81 generate a different temporary key for each build, resulting in the
82 modules being unreproducible. However, including a signing key with
83 your source would presumably defeat the purpose of signing modules.
84
85 One approach to this is to divide up the build process so that the
86 unreproducible parts can be treated as sources:
87
88 1. Generate a persistent signing key. Add the certificate for the key
89 to the kernel source.
90
91 2. Set the ``CONFIG_SYSTEM_TRUSTED_KEYS`` symbol to include the
92 signing key's certificate, set ``CONFIG_MODULE_SIG_KEY`` to an
93 empty string, and disable ``CONFIG_MODULE_SIG_ALL``.
94 Build the kernel and modules.
95
96 3. Create detached signatures for the modules, and publish them as
97 sources.
98
99 4. Perform a second build that attaches the module signatures. It
100 can either rebuild the modules or use the output of step 2.
101
102 Structure randomisation
103 -----------------------
104
105 If you enable ``CONFIG_RANDSTRUCT``, you will need to pre-generate
106 the random seed in ``scripts/basic/randstruct.seed`` so the same
107 value is used by each build. See ``scripts/gen-randstruct-seed.sh``
108 for details.
109
110 Debug info conflicts
111 --------------------
112
113 This is not a problem of unreproducibility, but of generated files
114 being *too* reproducible.
115
116 Once you set all the necessary variables for a reproducible build, a
117 vDSO's debug information may be identical even for different kernel
118 versions. This can result in file conflicts between debug information
119 packages for the different kernel versions.
120
121 To avoid this, you can make the vDSO different for different
122 kernel versions by including an arbitrary string of "salt" in it.
123 This is specified by the Kconfig symbol ``CONFIG_BUILD_SALT``.
124
125 Git
126 ---
127
128 Uncommitted changes or different commit ids in git can also lead
129 to different compilation results. For example, after executing
130 ``git reset HEAD^``, even if the code is the same, the
131 ``include/config/kernel.release`` generated during compilation
132 will be different, which will eventually lead to binary differences.
133 See ``scripts/setlocalversion`` for details.
134
135 .. _KBUILD_BUILD_TIMESTAMP: kbuild.html#kbuild-build-timestamp
136 .. _KBUILD_BUILD_USER and KBUILD_BUILD_HOST: kbuild.html#kbuild-build-user-kbuild-build-host
137 .. _KCFLAGS: kbuild.html#kcflags
138 .. _prefix-map options: https://reproducible-builds.org/docs/build-path/
139 .. _Reproducible Builds project: https://reproducible-builds.org/
140 .. _SOURCE_DATE_EPOCH: https://reproducible-builds.org/docs/source-date-epoch/
141

3. 한국어 전문 번역

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

재현 가능한 빌드와 timestamp

1-39

같은 source code를 같은 tool 집합으로 build했을 때 output이 항상 byte 단위로 같아지는 재현성은 binary distribution이나 embedded system의 build infrastructure가 변조되지 않았음을 검증하고, source 또는 tool 변경이 binary에 영향을 주지 않았음을 확인하는 데 유용합니다.

이 문서는 kernel build가 달라지는 원인과 회피 방법을 다룹니다. 일반적인 배경은 Reproducible Builds project에서 확인할 수 있습니다.

Kernel에는 세 종류의 timestamp가 들어갑니다. `uname()`과 `/proc/version`의 version string, embedded initramfs의 file timestamp, 그리고 `CONFIG_IKHEADERS`가 활성화되었을 때 kernel 또는 module 안에 들어가 `/sys/kernel/kheaders.tar.xz`로 노출되는 header timestamp입니다.

Kernel에 포함되는 timestamp
위치기본 입력제어 방법
`uname()`·`/proc/version`Build 시각`KBUILD_BUILD_TIMESTAMP`
Embedded initramfsBuild 시각`KBUILD_BUILD_TIMESTAMP`
`kheaders.tar.xz`Header modification time`KBUILD_BUILD_TIMESTAMP`

현재 시각이나 file modification time을 고정된 값으로 바꿔야 합니다.

기본 timestamp는 현재 시각이고 kheaders는 각 file의 modification time도 사용합니다. `KBUILD_BUILD_TIMESTAMP`로 이를 덮어써야 하며, Git commit을 build한다면 commit date를 사용할 수 있습니다.

Kernel은 `__DATE__`와 `__TIME__` macro를 사용하지 않고 사용 시 warning을 활성화합니다. External code가 이 macro를 사용한다면 `SOURCE_DATE_EPOCH` environment variable로 대응 timestamp를 고정해야 합니다.

===================
Reproducible builds
===================

It is generally desirable that building the same source code with
the same set of tools is reproducible, i.e. the output is always
exactly the same.  This makes it possible to verify that the build
infrastructure for a binary distribution or embedded system has not
been subverted.  This can also make it easier to verify that a source
or tool change does not make any difference to the resulting binaries.

The `Reproducible Builds project`_ has more information about this
general topic.  This document covers the various reasons why building
the kernel may be unreproducible, and how to avoid them.

Timestamps
----------

The kernel embeds timestamps in three places:

* The version string exposed by ``uname()`` and included in
  ``/proc/version``

* File timestamps in the embedded initramfs

* If enabled via ``CONFIG_IKHEADERS``, file timestamps of kernel
  headers embedded in the kernel or respective module,
  exposed via ``/sys/kernel/kheaders.tar.xz``

By default the timestamp is the current time and in the case of
``kheaders`` the various files' modification times. This must
be overridden using the `KBUILD_BUILD_TIMESTAMP`_ variable.
If you are building from a git commit, you could use its commit date.

The kernel does *not* use the ``__DATE__`` and ``__TIME__`` macros,
and enables warnings if they are used.  If you incorporate external
code that does use these, you must override the timestamp they
correspond to by setting the `SOURCE_DATE_EPOCH`_ environment
variable.

사용자·host와 absolute path

40-67

Kernel은 build한 user와 host 이름을 `/proc/version`에 포함합니다. `KBUILD_BUILD_USER`와 `KBUILD_BUILD_HOST`로 값을 고정해야 합니다. Git commit을 기준으로 한다면 committer address를 사용할 수 있습니다.

Out-of-tree build의 debug information에는 source file의 absolute filename이 들어갈 수 있습니다. `KCFLAGS`에 `-fdebug-prefix-map` option을 추가해 build path를 안정적인 prefix로 치환해야 합니다.

Compiler에 따라 `__FILE__` macro도 absolute filename으로 확장될 수 있습니다. Kbuild는 compiler가 지원하면 `-fmacro-prefix-map`을 자동 사용해 이를 방지합니다.

`CONFIG_DEBUG_EFI`처럼 object file에 absolute path를 직접 넣는 configuration option도 있습니다. 재현 가능한 binary가 필요하면 이런 option을 비활성화해야 합니다.

Build identity와 path 고정
변동 원인제어 항목
Build user·host`KBUILD_BUILD_USER`, `KBUILD_BUILD_HOST`
Debug source path`KCFLAGS=-fdebug-prefix-map=...`
`__FILE__` pathKbuild의 자동 `-fmacro-prefix-map`
Path를 embed하는 CONFIG해당 option 비활성화

Host 환경에서 유입되는 비결정적 값을 명시적으로 통제합니다.


User, host
----------

The kernel embeds the building user and host names in
``/proc/version``.  These must be overridden using the
`KBUILD_BUILD_USER and KBUILD_BUILD_HOST`_ variables.  If you are
building from a git commit, you could use its committer address.

Absolute filenames
------------------

When the kernel is built out-of-tree, debug information may include
absolute filenames for the source files.  This must be overridden by
including the ``-fdebug-prefix-map`` option in the `KCFLAGS`_ variable.

Depending on the compiler used, the ``__FILE__`` macro may also expand
to an absolute filename in an out-of-tree build.  Kbuild automatically
uses the ``-fmacro-prefix-map`` option to prevent this, if it is
supported.

The Reproducible Builds web site has more information about these
`prefix-map options`_.

Some CONFIG options such as `CONFIG_DEBUG_EFI` embed absolute paths in
object files. Such options should be disabled.

Generated files in source packages

Generated file과 module signing

68-105

`tools/` 아래 일부 program은 out-of-tree build를 완전히 지원하지 않아 generated file이 source tree에 남을 수 있습니다. 이후 `make rpm-pkg` 같은 source package build가 이 file을 포함하면 결과가 달라집니다. Source package를 만들기 전에 `make mrproper` 또는 `git clean -d -f -x`로 tree를 pristine 상태로 유지해야 합니다.

`CONFIG_MODULE_SIG_ALL`을 활성화하면 기본 동작은 build마다 다른 temporary signing key를 만들기 때문에 module이 재현되지 않습니다. 하지만 signing key 자체를 source와 함께 배포하면 module signing의 목적을 약화할 수 있습니다.

권장 접근은 재현되지 않는 signing 단계를 source 취급할 수 있도록 build를 나누는 것입니다.

재현 가능한 module signing 절차
Persistent signing key 생성 후 certificate를 kernel source에 추가`CONFIG_SYSTEM_TRUSTED_KEYS`에 certificate 지정`CONFIG_MODULE_SIG_KEY`를 빈 문자열로 두고 `CONFIG_MODULE_SIG_ALL` 비활성화Kernel과 module을 첫 번째로 buildModule detached signature를 생성해 source로 배포둘째 build에서 signature를 module에 부착

Persistent key와 detached signature를 분리해 kernel build를 반복 가능하게 만듭니다.

둘째 build는 module을 다시 build하거나 첫 번째 build output을 사용할 수 있습니다. 핵심은 key 생성과 signature 생성이라는 비결정적 결과를 명시적인 input으로 승격하는 것입니다.

----------------------------------

The build processes for some programs under the ``tools/``
subdirectory do not completely support out-of-tree builds.  This may
cause a later source package build using e.g. ``make rpm-pkg`` to
include generated files.  You should ensure the source tree is
pristine by running ``make mrproper`` or ``git clean -d -f -x`` before
building a source package.

Module signing
--------------

If you enable ``CONFIG_MODULE_SIG_ALL``, the default behaviour is to
generate a different temporary key for each build, resulting in the
modules being unreproducible.  However, including a signing key with
your source would presumably defeat the purpose of signing modules.

One approach to this is to divide up the build process so that the
unreproducible parts can be treated as sources:

1. Generate a persistent signing key.  Add the certificate for the key
   to the kernel source.

2. Set the ``CONFIG_SYSTEM_TRUSTED_KEYS`` symbol to include the
   signing key's certificate, set ``CONFIG_MODULE_SIG_KEY`` to an
   empty string, and disable ``CONFIG_MODULE_SIG_ALL``.
   Build the kernel and modules.

3. Create detached signatures for the modules, and publish them as
   sources.

4. Perform a second build that attaches the module signatures.  It
   can either rebuild the modules or use the output of step 2.

Structure randomisation
-----------------------

If you enable ``CONFIG_RANDSTRUCT``, you will need to pre-generate

RANDSTRUCT와 debug package 충돌

106-128

`CONFIG_RANDSTRUCT`를 사용하면 build마다 같은 값을 쓰도록 `scripts/basic/randstruct.seed`를 미리 생성해야 합니다. 자세한 절차는 `scripts/gen-randstruct-seed.sh`에 있습니다.

필요한 값을 모두 고정하면 반대로 generated file이 지나치게 동일해지는 경우가 있습니다. 서로 다른 kernel version의 vDSO debug information이 같아져 각 version의 debug package 사이에서 file conflict가 생길 수 있습니다.

Kernel version마다 vDSO를 다르게 만들려면 임의의 salt string을 포함합니다. 이 값은 Kconfig symbol `CONFIG_BUILD_SALT`로 지정합니다. 이는 build 비재현성 문제가 아니라 package가 구별되지 않을 정도로 재현된 결과를 관리하는 방법입니다.

the random seed in ``scripts/basic/randstruct.seed`` so the same
value is used by each build. See ``scripts/gen-randstruct-seed.sh``
for details.

Debug info conflicts
--------------------

This is not a problem of unreproducibility, but of generated files
being *too* reproducible.

Once you set all the necessary variables for a reproducible build, a
vDSO's debug information may be identical even for different kernel
versions.  This can result in file conflicts between debug information
packages for the different kernel versions.

To avoid this, you can make the vDSO different for different
kernel versions by including an arbitrary string of "salt" in it.
This is specified by the Kconfig symbol ``CONFIG_BUILD_SALT``.

Git
---

Uncommitted changes or different commit ids in git can also lead