lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260119064731.23879-12-luis.augenstein@tngtech.com>
Date: Mon, 19 Jan 2026 07:47:28 +0100
From: Luis Augenstein <luis.augenstein@...tech.com>
To: nathan@...nel.org,
	nsc@...nel.org
Cc: linux-kbuild@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	akpm@...ux-foundation.org,
	gregkh@...uxfoundation.org,
	maximilian.huber@...tech.com,
	Luis Augenstein <luis.augenstein@...tech.com>
Subject: [PATCH 11/14] tools/sbom: add SPDX source graph

Implement the SPDX source graph which contains all source files
involved during the build, along with the licensing information
for each file.

Co-developed-by: Maximilian Huber <maximilian.huber@...tech.com>
Signed-off-by: Maximilian Huber <maximilian.huber@...tech.com>
Signed-off-by: Luis Augenstein <luis.augenstein@...tech.com>
---
 .../sbom/sbom/spdx_graph/build_spdx_graphs.py |   8 ++
 .../sbom/sbom/spdx_graph/spdx_source_graph.py | 126 ++++++++++++++++++
 2 files changed, 134 insertions(+)
 create mode 100644 tools/sbom/sbom/spdx_graph/spdx_source_graph.py

diff --git a/tools/sbom/sbom/spdx_graph/build_spdx_graphs.py b/tools/sbom/sbom/spdx_graph/build_spdx_graphs.py
index 2af0fbe6c..a61257a90 100644
--- a/tools/sbom/sbom/spdx_graph/build_spdx_graphs.py
+++ b/tools/sbom/sbom/spdx_graph/build_spdx_graphs.py
@@ -10,6 +10,7 @@ from sbom.path_utils import PathStr
 from sbom.spdx_graph.kernel_file import KernelFileCollection
 from sbom.spdx_graph.spdx_graph_model import SpdxGraph, SpdxIdGeneratorCollection
 from sbom.spdx_graph.shared_spdx_elements import SharedSpdxElements
+from sbom.spdx_graph.spdx_source_graph import SpdxSourceGraph
 from sbom.spdx_graph.spdx_output_graph import SpdxOutputGraph
 
 
@@ -54,4 +55,11 @@ def build_spdx_graphs(
         KernelSpdxDocumentKind.OUTPUT: output_graph,
     }
 
+    if len(kernel_files.source) > 0:
+        spdx_graphs[KernelSpdxDocumentKind.SOURCE] = SpdxSourceGraph.create(
+            source_files=list(kernel_files.source.values()),
+            shared_elements=shared_elements,
+            spdx_id_generators=spdx_id_generators,
+        )
+
     return spdx_graphs
diff --git a/tools/sbom/sbom/spdx_graph/spdx_source_graph.py b/tools/sbom/sbom/spdx_graph/spdx_source_graph.py
new file mode 100644
index 000000000..16176c4ea
--- /dev/null
+++ b/tools/sbom/sbom/spdx_graph/spdx_source_graph.py
@@ -0,0 +1,126 @@
+# SPDX-License-Identifier: GPL-2.0-only OR MIT
+# Copyright (C) 2025 TNG Technology Consulting GmbH
+
+from dataclasses import dataclass
+from sbom.spdx import SpdxIdGenerator
+from sbom.spdx.core import Element, NamespaceMap, Relationship, SpdxDocument
+from sbom.spdx.simplelicensing import LicenseExpression
+from sbom.spdx.software import File, Sbom
+from sbom.spdx_graph.kernel_file import KernelFile
+from sbom.spdx_graph.shared_spdx_elements import SharedSpdxElements
+from sbom.spdx_graph.spdx_graph_model import SpdxGraph, SpdxIdGeneratorCollection
+
+
+@...aclass
+class SpdxSourceGraph(SpdxGraph):
+    """SPDX graph representing source files"""
+
+    @classmethod
+    def create(
+        cls,
+        source_files: list[KernelFile],
+        shared_elements: SharedSpdxElements,
+        spdx_id_generators: SpdxIdGeneratorCollection,
+    ) -> "SpdxSourceGraph":
+        """
+        Args:
+            source_files: List of files within the kernel source tree.
+            shared_elements: Shared SPDX elements used across multiple documents.
+            spdx_id_generators: Collection of SPDX ID generators.
+
+        Returns:
+            SpdxSourceGraph: The SPDX source graph.
+        """
+        # SpdxDocument
+        source_spdx_document = SpdxDocument(
+            spdxId=spdx_id_generators.source.generate(),
+            profileConformance=["core", "software", "simpleLicensing"],
+            namespaceMap=[
+                NamespaceMap(prefix=generator.prefix, namespace=generator.namespace)
+                for generator in [spdx_id_generators.source, spdx_id_generators.base]
+                if generator.prefix is not None
+            ],
+        )
+
+        # Sbom
+        source_sbom = Sbom(
+            spdxId=spdx_id_generators.source.generate(),
+            software_sbomType=["source"],
+        )
+
+        # Src Tree Elements
+        src_tree_element = File(
+            spdxId=spdx_id_generators.source.generate(),
+            name="$(src_tree)",
+            software_fileKind="directory",
+        )
+        src_tree_contains_relationship = Relationship(
+            spdxId=spdx_id_generators.source.generate(),
+            relationshipType="contains",
+            from_=src_tree_element,
+            to=[],
+        )
+
+        # Source file elements
+        source_file_elements: list[Element] = [file.spdx_file_element for file in source_files]
+
+        # Source file license elements
+        source_file_license_identifiers, source_file_license_relationships = source_file_license_elements(
+            source_files, spdx_id_generators.source
+        )
+
+        # Update relationships
+        source_spdx_document.rootElement = [source_sbom]
+        source_sbom.rootElement = [src_tree_element]
+        source_sbom.element = [
+            src_tree_element,
+            src_tree_contains_relationship,
+            *source_file_elements,
+            *source_file_license_identifiers,
+            *source_file_license_relationships,
+        ]
+        src_tree_contains_relationship.to = source_file_elements
+
+        source_graph = SpdxSourceGraph(
+            source_spdx_document,
+            shared_elements.agent,
+            shared_elements.creation_info,
+            source_sbom,
+        )
+        return source_graph
+
+
+def source_file_license_elements(
+    source_files: list[KernelFile], spdx_id_generator: SpdxIdGenerator
+) -> tuple[list[LicenseExpression], list[Relationship]]:
+    """
+    Creates SPDX license expressions and links them to the given source files
+    via hasDeclaredLicense relationships.
+
+    Args:
+        source_files: List of files within the kernel source tree.
+        spdx_id_generator: Generator for unique SPDX IDs.
+
+    Returns:
+        Tuple of (license expressions, hasDeclaredLicense relationships).
+    """
+    license_expressions: dict[str, LicenseExpression] = {}
+    for file in source_files:
+        if file.license_identifier is None or file.license_identifier in license_expressions:
+            continue
+        license_expressions[file.license_identifier] = LicenseExpression(
+            spdxId=spdx_id_generator.generate(),
+            simplelicensing_licenseExpression=file.license_identifier,
+        )
+
+    source_file_license_relationships = [
+        Relationship(
+            spdxId=spdx_id_generator.generate(),
+            relationshipType="hasDeclaredLicense",
+            from_=file.spdx_file_element,
+            to=[license_expressions[file.license_identifier]],
+        )
+        for file in source_files
+        if file.license_identifier is not None
+    ]
+    return ([*license_expressions.values()], source_file_license_relationships)
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ