Skip to content

Commit fce19ac

Browse files
committed
fix: include additional boot parameters
Generate hard-coded boot parameters for UKI-based variants, until parsing bootconfigs in twoliter is supported. Signed-off-by: Arnaldo Garcia Rincon <agarrcia@amazon.com>
1 parent 7d53adf commit fce19ac

4 files changed

Lines changed: 204 additions & 4 deletions

File tree

twoliter/embedded/imghelper

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,21 @@ sign_vmlinuz() {
768768
do_sign "${vmlinuz}" "${SBKEYS}/vendor.cer" CODE_SIGN_KEY
769769
}
770770

771+
# bootconfig is not yet supported for UKI images. Until that support exists,
772+
# the systemd and (for FIPS variants) FIPS bootconfig snippets shipped by
773+
# the core kit are hard-coded here as literal cmdline tokens. FIPS-ness is
774+
# derived from the variant name, which always ends in the `-fips` suffix for
775+
# FIPS variants.
776+
uki_bootconfig_cmdline() {
777+
local variant tokens
778+
variant="${1:?}"
779+
tokens="SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1 SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST=25"
780+
if [[ "${variant}" == *-fips ]]; then
781+
tokens="${tokens} fips=1 init.systemd.unit=fipscheck.target"
782+
fi
783+
echo "${tokens}"
784+
}
785+
771786
sign_systemd_boot() {
772787
local loader
773788
loader="${1:?}"

twoliter/embedded/rpm2img

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -665,10 +665,10 @@ if [[ "${UKI_IMAGE}" == "yes" ]]; then
665665
fi
666666

667667
# Build cmdline EXACTLY mirroring grub.cfg
668-
# bootconfig is not yet supported for UKI images: there is no mechanism to
669-
# attach the runtime-generated bootconfig.data blob as with GRUB's `initrd`
670-
# directive, so requesting it only produces a kernel warning at boot.
671-
uki_bootconfig=""
668+
# bootconfig is not yet supported for UKI images: see uki_bootconfig_cmdline
669+
# in imghelper for details on the hard-coded FIPS/systemd cmdline tokens
670+
# used in place of it.
671+
uki_bootconfig="$(uki_bootconfig_cmdline "${VARIANT}")"
672672

673673
# The escaped quotes around the verity table are intentional: the kernel's
674674
# dm-mod.create= value contains spaces, so the literal quote characters must
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Test `uki_bootconfig_cmdline` in `imghelper`: the function that hard-codes
4+
# the core kit's systemd and FIPS bootconfig snippets
5+
# (/boot/boot-config.d/20-*, 21-*, 10-fips.conf) as literal UKI cmdline
6+
# tokens, since bootconfig.data is not yet attachable to a UKI's boot chain.
7+
#
8+
# FIPS-ness is derived from the variant name (the `-fips` suffix convention
9+
# used across every FIPS variant under bottlerocket/variants/), not from a
10+
# separate build-arg, so this test exercises that name-based branch directly.
11+
#
12+
# Run from the repo root:
13+
# bash twoliter/embedded/tests/test_uki_bootconfig.sh
14+
15+
set -eu -o pipefail
16+
17+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18+
IMGHELPER="${SCRIPT_DIR}/../imghelper"
19+
20+
if [[ ! -f "${IMGHELPER}" ]]; then
21+
echo "test_uki_bootconfig: imghelper not found at ${IMGHELPER}" >&2
22+
exit 1
23+
fi
24+
25+
# imghelper's top-level `${VAR:?}` expansions require these to be set before
26+
# it can be sourced, even though this test only exercises
27+
# `uki_bootconfig_cmdline`.
28+
IMAGE_NAME=x VARIANT=x ARCH=x86_64 VERSION_ID=x BUILD_ID=x
29+
export IMAGE_NAME VARIANT ARCH VERSION_ID BUILD_ID
30+
31+
# shellcheck source=../imghelper
32+
. "${IMGHELPER}"
33+
34+
pass_count=0
35+
fail_count=0
36+
37+
pass() {
38+
pass_count=$((pass_count + 1))
39+
echo " ok: $1"
40+
}
41+
42+
fail() {
43+
fail_count=$((fail_count + 1))
44+
echo " FAIL: $1" >&2
45+
}
46+
47+
assert_eq() {
48+
local actual expected name
49+
actual="$1"
50+
expected="$2"
51+
name="$3"
52+
if [[ "${actual}" == "${expected}" ]]; then
53+
pass "${name}"
54+
else
55+
fail "${name}: expected '${expected}' got '${actual}'"
56+
fi
57+
}
58+
59+
# Assert that a space-separated token list contains every expected token.
60+
assert_contains_tokens() {
61+
local actual name token
62+
actual="$1"
63+
name="$2"
64+
shift 2
65+
for token in "$@"; do
66+
if [[ " ${actual} " != *" ${token} "* ]]; then
67+
fail "${name}: expected token '${token}' missing from '${actual}'"
68+
return
69+
fi
70+
done
71+
pass "${name}"
72+
}
73+
74+
echo "Test 1: UKI + FIPS variant includes systemd and FIPS tokens"
75+
out="$(uki_bootconfig_cmdline "aws-k8s-1.35-fips")"
76+
assert_contains_tokens "${out}" "fips variant: systemd tokens present" \
77+
"SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1" "SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST=25"
78+
assert_contains_tokens "${out}" "fips variant: FIPS tokens present" \
79+
"fips=1" "init.systemd.unit=fipscheck.target"
80+
81+
echo
82+
echo "Test 1b: UKI + FIPS variant with an extra flavor segment (nvidia-fips)"
83+
out="$(uki_bootconfig_cmdline "aws-k8s-1.34-nvidia-fips")"
84+
assert_contains_tokens "${out}" "nvidia-fips variant: systemd tokens present" \
85+
"SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1" "SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST=25"
86+
assert_contains_tokens "${out}" "nvidia-fips variant: FIPS tokens present" \
87+
"fips=1" "init.systemd.unit=fipscheck.target"
88+
89+
echo
90+
echo "Test 2: UKI + non-FIPS variant includes systemd tokens only"
91+
out="$(uki_bootconfig_cmdline "aws-k8s-1.35")"
92+
assert_contains_tokens "${out}" "non-fips variant: systemd tokens present" \
93+
"SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1" "SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST=25"
94+
if [[ " ${out} " == *" fips=1 "* ]] || [[ " ${out} " == *" init.systemd.unit=fipscheck.target "* ]]; then
95+
fail "non-fips variant: FIPS tokens must be absent, got '${out}'"
96+
else
97+
pass "non-fips variant: FIPS tokens absent"
98+
fi
99+
100+
echo
101+
echo "Test 2b: a variant merely containing 'fips' mid-string is not FIPS"
102+
# Guards against a naive substring match: FIPS-ness is a trailing dash-token,
103+
# not merely the presence of the substring 'fips' anywhere in the name.
104+
out="$(uki_bootconfig_cmdline "aws-fips-k8s-1.35")"
105+
if [[ " ${out} " == *" fips=1 "* ]]; then
106+
fail "mid-string 'fips' incorrectly treated as a FIPS variant, got '${out}'"
107+
else
108+
pass "mid-string 'fips' correctly not treated as a FIPS variant"
109+
fi
110+
111+
echo
112+
echo "Test 3: non-UKI images never call uki_bootconfig_cmdline (values absent)"
113+
# rpm2img only calls uki_bootconfig_cmdline inside the `UKI_IMAGE == yes`
114+
# branch; a non-UKI build never invokes it, so uki_bootconfig is never
115+
# populated there. We assert the source-level guard directly, since
116+
# rpm2img itself is not practical to run end-to-end in a unit test (it
117+
# performs real partitioning, RPM installs, and image assembly first).
118+
RPM2IMG="${SCRIPT_DIR}/../rpm2img"
119+
if [[ ! -f "${RPM2IMG}" ]]; then
120+
echo "test_uki_bootconfig: rpm2img not found at ${RPM2IMG}" >&2
121+
exit 1
122+
fi
123+
if grep -qE '^\s*if \[\[ "\$\{UKI_IMAGE\}" == "yes" \]\]; then\s*$' "${RPM2IMG}"; then
124+
# Extract the UKI-image conditional block and confirm the
125+
# uki_bootconfig_cmdline call lives inside it.
126+
uki_block="$(awk '/if \[\[ "\$\{UKI_IMAGE\}" == "yes" \]\]; then/,/^fi$/' "${RPM2IMG}")"
127+
if [[ "${uki_block}" == *"uki_bootconfig_cmdline"* ]]; then
128+
pass "uki_bootconfig_cmdline is only invoked inside the UKI_IMAGE=yes branch"
129+
else
130+
fail "uki_bootconfig_cmdline call not found inside the UKI_IMAGE=yes branch"
131+
fi
132+
else
133+
fail "could not locate the UKI_IMAGE=yes conditional in rpm2img"
134+
fi
135+
136+
echo
137+
echo "Results: ${pass_count} passed, ${fail_count} failed"
138+
if [[ "${fail_count}" -gt 0 ]]; then
139+
exit 1
140+
fi
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//! Integration test that runs the bash-side `uki_bootconfig_cmdline` test
2+
//! suite.
3+
//!
4+
//! The actual assertions live in `embedded/tests/test_uki_bootconfig.sh`,
5+
//! which sources `imghelper` as a library and exercises
6+
//! `uki_bootconfig_cmdline` across UKI+FIPS, UKI+non-FIPS, and non-UKI
7+
//! variant names. This Rust wrapper exists so the bash tests run under
8+
//! `cargo test` alongside the validator tests in the `buildsys` crate.
9+
10+
use std::path::PathBuf;
11+
use std::process::Command;
12+
13+
#[test]
14+
fn uki_bootconfig_bash_tests() {
15+
// The `embedded` directory is a symlink to `twoliter/embedded` at the
16+
// crate root, so `CARGO_MANIFEST_DIR` reaches the script either way.
17+
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
18+
let script = manifest_dir.join("embedded/tests/test_uki_bootconfig.sh");
19+
20+
assert!(
21+
script.is_file(),
22+
"test_uki_bootconfig.sh not found at {}",
23+
script.display(),
24+
);
25+
26+
let output = Command::new("bash")
27+
.arg(&script)
28+
.output()
29+
.expect("failed to invoke bash");
30+
31+
let stdout = String::from_utf8_lossy(&output.stdout);
32+
let stderr = String::from_utf8_lossy(&output.stderr);
33+
34+
// Always print so failures show what the bash runner saw.
35+
println!("--- test_uki_bootconfig.sh stdout ---\n{stdout}");
36+
if !stderr.is_empty() {
37+
println!("--- test_uki_bootconfig.sh stderr ---\n{stderr}");
38+
}
39+
40+
assert!(
41+
output.status.success(),
42+
"test_uki_bootconfig.sh failed with status {:?}",
43+
output.status,
44+
);
45+
}

0 commit comments

Comments
 (0)