fix: extract cmdline multi profile UKIs

When extracting `.cmdline` from multi profile UKI's we only need the
first cmdline, rest are profile specific and not the default cmdline.

Signed-off-by: Noel Georgi <git@frezbo.dev>
This commit is contained in:
Noel Georgi 2025-02-05 20:21:58 +05:30
parent 716f700da7
commit 15191aa3e3
No known key found for this signature in database
GPG Key ID: 21A9F444075C9E36
3 changed files with 35 additions and 25 deletions

View File

@ -32,30 +32,22 @@ func Extract(ukiPath string) (assetInfo AssetInfo, err error) {
assetInfo.fileCloser = peFile
for _, section := range peFile.Sections {
// read upto section.VirtualSize bytes
sectionReader := io.NewSectionReader(section, 0, int64(section.VirtualSize))
sectionMap := map[string]*io.Reader{
".initrd": &assetInfo.Initrd,
".cmdline": &assetInfo.Cmdline,
".linux": &assetInfo.Kernel,
}
switch section.Name {
case ".initrd":
assetInfo.Initrd = sectionReader
case ".cmdline":
assetInfo.Cmdline = sectionReader
case ".linux":
assetInfo.Kernel = sectionReader
for _, section := range peFile.Sections {
if reader, exists := sectionMap[section.Name]; exists && *reader == nil {
*reader = io.NewSectionReader(section, 0, int64(section.VirtualSize))
}
}
if assetInfo.Kernel == nil {
return assetInfo, fmt.Errorf("kernel not found in PE file")
}
if assetInfo.Initrd == nil {
return assetInfo, fmt.Errorf("initrd not found in PE file")
}
if assetInfo.Cmdline == nil {
return assetInfo, fmt.Errorf("cmdline not found in PE file")
for name, reader := range sectionMap {
if *reader == nil {
return assetInfo, fmt.Errorf("%s not found in PE file", name)
}
}
return assetInfo, nil

View File

@ -23,7 +23,7 @@ func TestUKIExtract(t *testing.T) {
destFile := filepath.Join(destDir, "vmlinuz.efi")
for _, section := range []string{"linux", "initrd", "cmdline"} {
for _, section := range []string{"linux", "initrd", "cmdline", "profile-default", "profile-reset", "cmdline-reset"} {
assert.NoError(t, os.WriteFile(filepath.Join(destDir, section), []byte(section), 0o644))
}
@ -46,6 +46,24 @@ func TestUKIExtract(t *testing.T) {
Measure: false,
Append: true,
},
{
Name: ".profile",
Path: filepath.Join(destDir, "profile-default"),
Measure: false,
Append: true,
},
{
Name: ".profile",
Path: filepath.Join(destDir, "profile-reset"),
Measure: false,
Append: true,
},
{
Name: ".cmdline",
Path: filepath.Join(destDir, "cmdline-reset"),
Measure: false,
Append: true,
},
}))
ukiData, err := pe.Extract(destFile)

View File

@ -145,10 +145,10 @@ func TestMultipleSections(t *testing.T) {
tmpDir := t.TempDir()
unamePath := filepath.Join(tmpDir, "uname")
require.NoError(t, os.WriteFile(unamePath, []byte("Talos-helloworld"), 0o644))
require.NoError(t, os.WriteFile(unamePath, []byte("Talos"), 0o644))
unameNewPath := filepath.Join(tmpDir, "uname-new")
require.NoError(t, os.WriteFile(unameNewPath, []byte("Talos-foobar"), 0o644))
require.NoError(t, os.WriteFile(unameNewPath, []byte("Talos-new"), 0o644))
outNative := filepath.Join(tmpDir, "uki-native.bin")
@ -174,6 +174,6 @@ func TestMultipleSections(t *testing.T) {
sectionContents := extractSection(t, outNative, ".uname")
assert.Contains(t, sectionContents, "Talos-helloworld")
assert.Contains(t, sectionContents, "Talos-foobar")
assert.Contains(t, sectionContents, "Talos")
assert.Contains(t, sectionContents, "Talos-new")
}