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