xref: /linux/Documentation/tools/sbom/sbom.rst (revision e4b4bfaa5090760925b98848aa3e0fc10b3c574f)
1*658325c9SLuis Augenstein.. SPDX-License-Identifier: GPL-2.0-only OR MIT
2*658325c9SLuis Augenstein.. Copyright (C) 2025 TNG Technology Consulting GmbH
3*658325c9SLuis Augenstein
4*658325c9SLuis AugensteinKernelSbom
5*658325c9SLuis Augenstein==========
6*658325c9SLuis Augenstein
7*658325c9SLuis AugensteinIntroduction
8*658325c9SLuis Augenstein------------
9*658325c9SLuis Augenstein
10*658325c9SLuis AugensteinKernelSbom is a Python script ``scripts/sbom/sbom.py`` that can be
11*658325c9SLuis Augensteinexecuted after a successful kernel build. When invoked, KernelSbom
12*658325c9SLuis Augensteinanalyzes all files involved in the build and generates Software Bill of
13*658325c9SLuis AugensteinMaterials (SBOM) documents in SPDX 3.0.1 format.
14*658325c9SLuis AugensteinThe generated SBOM documents capture:
15*658325c9SLuis Augenstein
16*658325c9SLuis Augenstein* **Final output artifacts**, typically the kernel image and modules
17*658325c9SLuis Augenstein* **All source files** that contributed to the build with metadata
18*658325c9SLuis Augenstein  and licensing information
19*658325c9SLuis Augenstein* **Details of the build process**, including intermediate artifacts
20*658325c9SLuis Augenstein  and the build commands linking source files to the final output
21*658325c9SLuis Augenstein  artifacts
22*658325c9SLuis Augenstein
23*658325c9SLuis AugensteinKernelSbom is originally developed in the
24*658325c9SLuis Augenstein`KernelSbom repository <https://github.com/TNG/KernelSbom>`_.
25*658325c9SLuis Augenstein
26*658325c9SLuis AugensteinRequirements
27*658325c9SLuis Augenstein------------
28*658325c9SLuis Augenstein
29*658325c9SLuis AugensteinPython 3.10 or later. No libraries or other dependencies are required.
30*658325c9SLuis Augenstein
31*658325c9SLuis AugensteinBasic Usage
32*658325c9SLuis Augenstein-----------
33*658325c9SLuis Augenstein
34*658325c9SLuis AugensteinRun the ``make sbom`` target.
35*658325c9SLuis AugensteinFor example::
36*658325c9SLuis Augenstein
37*658325c9SLuis Augenstein    $ make defconfig O=kernel_build
38*658325c9SLuis Augenstein    $ make sbom O=kernel_build -j$(nproc)
39*658325c9SLuis Augenstein
40*658325c9SLuis AugensteinThis will trigger a kernel build. After all build outputs have been
41*658325c9SLuis Augensteingenerated, KernelSbom produces three SPDX documents in the root
42*658325c9SLuis Augensteindirectory of the object tree:
43*658325c9SLuis Augenstein
44*658325c9SLuis Augenstein* ``sbom-source.spdx.json``
45*658325c9SLuis Augenstein  Describes all source files involved in the build and
46*658325c9SLuis Augenstein  associates each file with its corresponding license expression.
47*658325c9SLuis Augenstein
48*658325c9SLuis Augenstein* ``sbom-output.spdx.json``
49*658325c9SLuis Augenstein  Captures all final build outputs (kernel image and ``.ko`` module files)
50*658325c9SLuis Augenstein  and includes build metadata such as environment variables and
51*658325c9SLuis Augenstein  a hash of the ``.config`` file used for the build.
52*658325c9SLuis Augenstein
53*658325c9SLuis Augenstein* ``sbom-build.spdx.json``
54*658325c9SLuis Augenstein  Imports files from the source and output documents and describes every
55*658325c9SLuis Augenstein  intermediate build artifact. For each artifact, it records the exact
56*658325c9SLuis Augenstein  build command used and establishes the relationship between
57*658325c9SLuis Augenstein  input files and generated outputs.
58*658325c9SLuis Augenstein
59*658325c9SLuis AugensteinWhen invoking the sbom target, it is recommended to perform
60*658325c9SLuis Augensteinout-of-tree builds using ``O=<objtree>``. KernelSbom classifies files as
61*658325c9SLuis Augensteinsource files when they are located in the source tree and not in the
62*658325c9SLuis Augensteinobject tree. For in-tree builds, where the source and object trees are
63*658325c9SLuis Augensteinthe same directory, this distinction can no longer be made reliably.
64*658325c9SLuis AugensteinIn that case, KernelSbom does not generate a dedicated source SBOM.
65*658325c9SLuis AugensteinInstead, source files are included in the build SBOM.
66*658325c9SLuis Augenstein
67*658325c9SLuis AugensteinStandalone Usage
68*658325c9SLuis Augenstein----------------
69*658325c9SLuis Augenstein
70*658325c9SLuis AugensteinKernelSbom can also be used as a standalone script to generate
71*658325c9SLuis AugensteinSPDX documents for specific build outputs. For example, after a
72*658325c9SLuis Augensteinsuccessful x86 kernel build, KernelSbom can generate SPDX documents
73*658325c9SLuis Augensteinfor the ``bzImage`` kernel image::
74*658325c9SLuis Augenstein
75*658325c9SLuis Augenstein    $ SRCARCH=x86 python3 scripts/sbom/sbom.py \
76*658325c9SLuis Augenstein        --src-tree . \
77*658325c9SLuis Augenstein        --obj-tree ./kernel_build \
78*658325c9SLuis Augenstein        --roots arch/x86/boot/bzImage \
79*658325c9SLuis Augenstein        --generate-spdx \
80*658325c9SLuis Augenstein        --generate-used-files \
81*658325c9SLuis Augenstein        --prettify-json \
82*658325c9SLuis Augenstein        --debug
83*658325c9SLuis Augenstein
84*658325c9SLuis AugensteinNote that when KernelSbom is invoked outside of the ``make`` process,
85*658325c9SLuis Augensteinthe environment variables used during compilation are not available and
86*658325c9SLuis Augensteintherefore cannot be included in the generated SPDX documents. It is
87*658325c9SLuis Augensteinrecommended to set at least the ``SRCARCH`` environment variable to the
88*658325c9SLuis Augensteinarchitecture for which the build was performed.
89*658325c9SLuis Augenstein
90*658325c9SLuis AugensteinFor a full list of command-line options, run::
91*658325c9SLuis Augenstein
92*658325c9SLuis Augenstein    $ python3 scripts/sbom/sbom.py --help
93*658325c9SLuis Augenstein
94*658325c9SLuis AugensteinOutput Format
95*658325c9SLuis Augenstein-------------
96*658325c9SLuis Augenstein
97*658325c9SLuis AugensteinKernelSbom generates documents conforming to the
98*658325c9SLuis Augenstein`SPDX 3.0.1 specification <https://spdx.github.io/spdx-spec/v3.0.1/>`_
99*658325c9SLuis Augensteinserialized as JSON-LD.
100*658325c9SLuis Augenstein
101*658325c9SLuis AugensteinTo reduce file size, the output documents use the JSON-LD ``@context``
102*658325c9SLuis Augensteinto define custom prefixes for ``spdxId`` values. While this is compliant
103*658325c9SLuis Augensteinwith the SPDX specification, only a limited number of tools in the
104*658325c9SLuis Augensteincurrent SPDX ecosystem support custom JSON-LD contexts. To use such
105*658325c9SLuis Augensteintools with the generated documents, the custom JSON-LD context must
106*658325c9SLuis Augensteinbe expanded before providing the documents.
107*658325c9SLuis AugensteinSee https://lists.spdx.org/g/Spdx-tech/message/6064 for more information.
108*658325c9SLuis Augenstein
109*658325c9SLuis AugensteinHow it Works
110*658325c9SLuis Augenstein------------
111*658325c9SLuis Augenstein
112*658325c9SLuis AugensteinKernelSbom operates in two major phases:
113*658325c9SLuis Augenstein
114*658325c9SLuis Augenstein1. **Generate the cmd graph**, an acyclic directed dependency graph.
115*658325c9SLuis Augenstein2. **Generate SPDX documents** based on the cmd graph.
116*658325c9SLuis Augenstein
117*658325c9SLuis AugensteinKernelSbom begins from the root artifacts specified by the user, e.g.,
118*658325c9SLuis Augenstein``arch/x86/boot/bzImage``. For each root artifact, it collects all
119*658325c9SLuis Augensteindependencies required to build that artifact. The dependencies come
120*658325c9SLuis Augensteinfrom multiple sources:
121*658325c9SLuis Augenstein
122*658325c9SLuis Augenstein* **.cmd files**: The primary source is the ``.cmd`` file of the
123*658325c9SLuis Augenstein  generated artifact, e.g., ``arch/x86/boot/.bzImage.cmd``. These files
124*658325c9SLuis Augenstein  contain the exact command used to build the artifact and often include
125*658325c9SLuis Augenstein  an explicit list of input dependencies. By parsing the ``.cmd``
126*658325c9SLuis Augenstein  file, the full list of dependencies can be obtained.
127*658325c9SLuis Augenstein
128*658325c9SLuis Augenstein* **.incbin statements**: The second source are include binary
129*658325c9SLuis Augenstein  ``.incbin`` statements in ``.S`` assembly files.
130*658325c9SLuis Augenstein
131*658325c9SLuis Augenstein* **Hardcoded dependencies**: Unfortunately, not all build dependencies
132*658325c9SLuis Augenstein  can be found via ``.cmd`` files and ``.incbin`` statements. Some build
133*658325c9SLuis Augenstein  dependencies are directly defined in Makefiles or Kbuild files.
134*658325c9SLuis Augenstein  Parsing these files is considered too complex for the scope of this
135*658325c9SLuis Augenstein  project. Instead, the remaining gaps of the graph are filled using a
136*658325c9SLuis Augenstein  list of manually defined dependencies, see
137*658325c9SLuis Augenstein  ``scripts/sbom/sbom/cmd_graph/hardcoded_dependencies.py``. This list is
138*658325c9SLuis Augenstein  known to be incomplete. However, analysis of the cmd graph indicates a
139*658325c9SLuis Augenstein  ~99% completeness. For more information about the completeness analysis,
140*658325c9SLuis Augenstein  see `KernelSbom #95 <https://github.com/TNG/KernelSbom/issues/95>`_.
141*658325c9SLuis Augenstein
142*658325c9SLuis AugensteinGiven the list of dependency files, KernelSbom recursively processes
143*658325c9SLuis Augensteineach file, expanding the dependency chain all the way to the version
144*658325c9SLuis Augensteincontrolled source files. The result is a complete dependency graph
145*658325c9SLuis Augensteinwhere nodes represent files, and edges represent "file A was used to
146*658325c9SLuis Augensteinbuild file B" relationships.
147*658325c9SLuis Augenstein
148*658325c9SLuis AugensteinUsing the cmd graph, KernelSbom produces three SPDX documents.
149*658325c9SLuis AugensteinFor every file in the graph, KernelSbom:
150*658325c9SLuis Augenstein
151*658325c9SLuis Augenstein* Parses ``SPDX-License-Identifier`` headers,
152*658325c9SLuis Augenstein* Computes file hashes,
153*658325c9SLuis Augenstein* Estimates the file type based on extension and path,
154*658325c9SLuis Augenstein* Records build relationships between files.
155*658325c9SLuis Augenstein
156*658325c9SLuis AugensteinEach root output file is additionally associated with an SPDX Package
157*658325c9SLuis Augensteinelement that captures version information, license data, and copyright.
158*658325c9SLuis Augenstein
159*658325c9SLuis AugensteinAdvanced Usage
160*658325c9SLuis Augenstein--------------
161*658325c9SLuis Augenstein
162*658325c9SLuis AugensteinIncluding Kernel Modules
163*658325c9SLuis Augenstein~~~~~~~~~~~~~~~~~~~~~~~~
164*658325c9SLuis Augenstein
165*658325c9SLuis AugensteinThe list of all ``.ko`` kernel modules produced during a build can be
166*658325c9SLuis Augensteinextracted from the ``modules.order`` file within the object tree.
167*658325c9SLuis AugensteinFor example::
168*658325c9SLuis Augenstein
169*658325c9SLuis Augenstein    $ echo "arch/x86/boot/bzImage" > sbom-roots.txt
170*658325c9SLuis Augenstein    $ sed 's/\.o$/.ko/' ./kernel_build/modules.order >> sbom-roots.txt
171*658325c9SLuis Augenstein
172*658325c9SLuis AugensteinThen use the generated roots file::
173*658325c9SLuis Augenstein
174*658325c9SLuis Augenstein    $ SRCARCH=x86 python3 scripts/sbom/sbom.py \
175*658325c9SLuis Augenstein        --src-tree . \
176*658325c9SLuis Augenstein        --obj-tree ./kernel_build \
177*658325c9SLuis Augenstein        --roots-file sbom-roots.txt \
178*658325c9SLuis Augenstein        --generate-spdx
179*658325c9SLuis Augenstein
180*658325c9SLuis AugensteinEqual Source and Object Trees
181*658325c9SLuis Augenstein~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
182*658325c9SLuis Augenstein
183*658325c9SLuis AugensteinWhen the source tree and object tree are identical (for example, when
184*658325c9SLuis Augensteinbuilding in-tree), source files can no longer be reliably distinguished
185*658325c9SLuis Augensteinfrom generated files.
186*658325c9SLuis AugensteinIn this scenario, KernelSbom does not produce a dedicated
187*658325c9SLuis Augenstein``sbom-source.spdx.json`` document. Instead, both source files and build
188*658325c9SLuis Augensteinartifacts are included together in ``sbom-build.spdx.json``, and
189*658325c9SLuis Augenstein``sbom.used-files.txt`` lists all files referenced in the build document.
190*658325c9SLuis Augenstein
191*658325c9SLuis AugensteinUnknown Build Commands
192*658325c9SLuis Augenstein~~~~~~~~~~~~~~~~~~~~~~
193*658325c9SLuis Augenstein
194*658325c9SLuis AugensteinBecause the kernel supports a wide range of configurations and versions,
195*658325c9SLuis AugensteinKernelSbom may encounter build commands in ``.cmd`` files that it does
196*658325c9SLuis Augensteinnot yet support. By default, KernelSbom will fail if an unknown build
197*658325c9SLuis Augensteincommand is encountered.
198*658325c9SLuis Augenstein
199*658325c9SLuis AugensteinIf you still wish to generate SPDX documents despite unsupported
200*658325c9SLuis Augensteincommands, you can use the ``--do-not-fail-on-unknown-build-command``
201*658325c9SLuis Augensteinoption. KernelSbom will continue and produce the documents, although
202*658325c9SLuis Augensteinthe resulting SBOM will be incomplete.
203*658325c9SLuis Augenstein
204*658325c9SLuis AugensteinThis option should only be used when the missing portion of the
205*658325c9SLuis Augensteindependency graph is small and an incomplete SBOM is acceptable for
206*658325c9SLuis Augensteinyour use case.
207