stages/kernel-cmdline: add max cmdline option

Add an additional option called `kernel_line_size`
to allow setting a maximum cmdline size check
value for custom kernels or other restrictions.

This will override the arch defaults, if not set,
then the size map is checked, and if the current
architecture is not in the map, fallback to
4096, which is the max value allowed for
COMMAND_LINE_SIZE.

Signed-off-by: Albert Esteve <aesteve@redhat.com>
This commit is contained in:
Albert Esteve 2025-02-07 14:41:22 +01:00 committed by Simon de Vlieger
parent 7645d717e6
commit a6b64860b3
3 changed files with 71 additions and 1 deletions

View file

@ -29,7 +29,8 @@ MAX_SIZE_MAP = {
def main(tree, options):
root_fs_uuid = options.get("root_fs_uuid", "")
additional = options.get("kernel_opts", "")
max_cmdline_size = MAX_SIZE_MAP.get(platform.machine().lower(), 4096)
max_cmdline_size = options.get("kernel_cmdline_size",
MAX_SIZE_MAP.get(platform.machine().lower(), 4096))
params = []

View file

@ -30,6 +30,12 @@
"description": "Additional kernel boot options",
"type": "string",
"default": ""
},
"kernel_cmdline_size": {
"description": "Sets a custom maximum kernel cmdline size",
"type": "integer",
"minimum": 256,
"maximum": 4096
}
}
}

View file

@ -0,0 +1,63 @@
#!/usr/bin/python3
from unittest import mock
import pytest # type: ignore
from osbuild import testutil
STAGE_NAME = "org.osbuild.kernel-cmdline"
@pytest.mark.parametrize("options, expected", [
({"kernel_opts": "--custom-opt=some"}, "--custom-opt=some"),
({"root_fs_uuid": "some-uuid"}, "root=UUID=some-uuid"),
({"root_fs_uuid": "other-uuid", "kernel_opts": "--custom-opt=other"},
"root=UUID=other-uuid --custom-opt=other"),
])
def test_kernel_cmdline(tmp_path, stage_module, options, expected):
tree = tmp_path / "tree"
tree.mkdir()
stage_module.main(tree, options)
cmdline_file = tree / "etc" / "kernel" / "cmdline"
assert cmdline_file.exists()
assert cmdline_file.read_text() == expected
@pytest.mark.parametrize("options, arch", [
({"kernel_opts": "a" * 2049}, "x86_64"),
({"kernel_opts": "a" * 1025}, "arm"),
({"kernel_opts": "a" * 2049}, "aarch64"),
({"kernel_opts": "a" * 257, "kernel_cmdline_size": 256}, "any"),
])
@mock.patch("platform.machine")
def test_kernel_opts_size_check(mock_machine, tmp_path, stage_module, options, arch):
tree = tmp_path / "tree"
tree.mkdir()
mock_machine.return_value = arch
with pytest.raises(ValueError) as e:
stage_module.main(tree, options)
assert str(e.value).startswith("The size of the kernel cmdline options cannot be larger than")
@pytest.mark.parametrize("options, expected_error", [
({"kernel_cmdline_size": 256}, ""),
({"kernel_cmdline_size": 4096}, ""),
({"kernel_cmdline_size": "not integer"}, "is not of type 'integer'"),
({"kernel_cmdline_size": 0}, "is less than the minimum of 256"),
({"kernel_cmdline_size": 4097}, "is greater than the maximum of 4096"),
])
def test_schema_validation_kernel_cmdline(stage_schema, options, expected_error):
test_input = {
"type": STAGE_NAME,
"options": options
}
res = stage_schema.validate(test_input)
if not expected_error:
assert res.valid
else:
assert not res.valid
testutil.assert_jsonschema_error_contains(res, expected_error, expected_num_errs=1)