From bdb5d53d4f50245d2b6fd3a9b4a2a0bf9ca3c7ac Mon Sep 17 00:00:00 2001 From: Simon de Vlieger Date: Mon, 3 Aug 2026 12:05:55 +0200 Subject: [PATCH] 60-ukify: skip `/proc/cmdline` in containers When running inside a container (during image builds or such), `/proc/cmdline` belongs to the host and would leak the host's root= (or a faked placeholder like root=/dev/osbuild) into the UKI. Mirror the same guard that `90-loaderentry.install` has: check `systemd-detect-virt --container` before falling back to `/proc/cmdline`, and return an empty cmdline if we are in a container to ensure both modes (`uki` and `bls`) work the same. Signed-off-by: Simon de Vlieger --- src/kernel-install/60-ukify.install.in | 13 +++++++++++++ src/kernel-install/test-kernel-install.sh | 12 +++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/kernel-install/60-ukify.install.in b/src/kernel-install/60-ukify.install.in index 9f22d083be9..2e46c88ddf6 100755 --- a/src/kernel-install/60-ukify.install.in +++ b/src/kernel-install/60-ukify.install.in @@ -22,6 +22,7 @@ import argparse import os import shlex +import subprocess import types from shutil import which from pathlib import Path @@ -195,6 +196,18 @@ def kernel_cmdline_base() -> list[str]: if os.getenv('KERNEL_INSTALL_CONF_ROOT'): return [] + # Don't read /proc/cmdline in containers it belongs to the host and would + # leak the host's root= (or a faked value) into the UKI. Mirrors + # the same guard in 90-loaderentry.install. + try: + result = subprocess.run( + ['systemd-detect-virt', '--container', '--quiet'], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + if result.returncode == 0: + return [] + except FileNotFoundError: + pass + # If we read /proc/cmdline, we need to do some additional filtering. options = Path('/proc/cmdline').read_text().split() return [opt for opt in options diff --git a/src/kernel-install/test-kernel-install.sh b/src/kernel-install/test-kernel-install.sh index 07f6da4a9dc..9904f570b52 100755 --- a/src/kernel-install/test-kernel-install.sh +++ b/src/kernel-install/test-kernel-install.sh @@ -146,7 +146,9 @@ if [ -f "$ukify" ]; then python3 - "$ukify_install" <<'PY' import os import runpy +import subprocess import sys +import unittest.mock ns = runpy.run_path(sys.argv[1], run_name='not_main') @@ -171,14 +173,22 @@ class FakePath: module_globals = ns['kernel_cmdline_base'].__globals__ module_globals['Path'] = FakePath +# Mock subprocess.run to simulate not being in a container, so the test +# works regardless of the environment (including container-based CI). os.environ.pop('KERNEL_INSTALL_CONF_ROOT', None) -assert ns['kernel_cmdline_base']() == ['root=fake', 'quiet'] +with unittest.mock.patch.object(subprocess, 'run', return_value=subprocess.CompletedProcess([], 1)): + assert ns['kernel_cmdline_base']() == ['root=fake', 'quiet'] os.environ['KERNEL_INSTALL_CONF_ROOT'] = '/conf-root' assert ns['kernel_cmdline_base']() == ['root=conf', 'quiet', 'splash'] os.environ['KERNEL_INSTALL_CONF_ROOT'] = '/empty-conf-root' assert ns['kernel_cmdline_base']() == [] + +# Test that /proc/cmdline is skipped in containers +os.environ.pop('KERNEL_INSTALL_CONF_ROOT', None) +with unittest.mock.patch.object(subprocess, 'run', return_value=subprocess.CompletedProcess([], 0)): + assert ns['kernel_cmdline_base']() == [], 'should return empty in container' PY mkdir "$D/sources/install.conf.d" -- 2.47.3