Skip to content

Commit

Permalink
Align efi-stub sections
Browse files Browse the repository at this point in the history
  • Loading branch information
brandsimon committed Aug 11, 2023
1 parent a0b8b07 commit 9b95e23
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
15 changes: 15 additions & 0 deletions src/verity_squash_root/efi.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import math
from collections import OrderedDict
from configparser import ConfigParser
from pathlib import Path
Expand Down Expand Up @@ -47,9 +48,22 @@ def calculate_efi_stub_end(stub: Path) -> int:
return int(words[2], 16) + int(words[3], 16)


def calculate_efi_stub_alignment(stub: Path) -> int:
result = exec_binary(["objdump", "-p", str(stub)])
lines = result[0].decode().split("\n")
for line in lines:
words = line.split()
if len(words) == 2:
if words[0] == "SectionAlignment":
return int(words[1], 16)
raise ValueError("Efistub SectionAlignment not found")


# TODO: use systemd-ukify when Debian 13 is stable
def create_efi_executable(stub: Path, cmdline_file: Path, linux: Path,
initrd: Path, dest: Path):
offset = calculate_efi_stub_end(stub)
alignment = calculate_efi_stub_alignment(stub)
sections = OrderedDict()
sections["osrel"] = Path("/etc/os-release")
sections["cmdline"] = cmdline_file
Expand All @@ -62,6 +76,7 @@ def create_efi_executable(stub: Path, cmdline_file: Path, linux: Path,

cmd = ["objcopy"]
for name, file in sections.items():
offset = alignment * math.ceil(offset / alignment)
size = file.stat().st_size
cmd += ["--add-section", ".{}={}".format(name, str(file)),
"--change-section-vma", ".{}={}".format(name, hex(offset))]
Expand Down
31 changes: 25 additions & 6 deletions tests/unit/efi.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import math
import unittest
from .test_helper import get_test_files_path
from pathlib import Path
Expand All @@ -6,7 +7,7 @@
from verity_squash_root.file_op import read_from
from verity_squash_root.efi import file_matches_slot_or_is_broken, sign, \
create_efi_executable, build_and_sign_kernel, get_cmdline, \
calculate_efi_stub_end
calculate_efi_stub_end, calculate_efi_stub_alignment

TEST_FILES_DIR = get_test_files_path("efi")

Expand Down Expand Up @@ -62,31 +63,49 @@ def test__calculate_efi_stub_end(self):
calculate_efi_stub_end(TEST_FILES_DIR / "stub_slot_a.efi"),
74064)

def test__calculate_efi_stub_alignment(self):
self.assertEqual(
calculate_efi_stub_alignment(TEST_FILES_DIR / "stub_slot_a.efi"),
512)

def test__calculate_efi_stub_alignment__not_found(self):
with self.assertRaises(ValueError) as e_ctx:
calculate_efi_stub_alignment(Path("/usr/lib/ld-linux-x86-64.so.2"))
self.assertEqual(
str(e_ctx.exception), "Efistub SectionAlignment not found")

@mock.patch("verity_squash_root.efi.calculate_efi_stub_alignment")
@mock.patch("verity_squash_root.efi.exec_binary")
@mock.patch("verity_squash_root.efi.calculate_efi_stub_end")
def test__create_efi_executable(self, calc_mock, exec_mock):
def test__create_efi_executable(self, calc_mock, exec_mock, align_mock):
def align(x):
return 2048 * math.ceil(x / 2048)

align_mock.return_value = 2048
calc_mock.return_value = 74064
create_efi_executable(
TEST_FILES_DIR / "stub_slot_a.efi",
TEST_FILES_DIR / "cmdline",
TEST_FILES_DIR / "vmlinuz",
TEST_FILES_DIR / "initrd",
Path("/tmp/file.efi"))
align_mock.assert_called_once_with(TEST_FILES_DIR / "stub_slot_a.efi")
calc_mock.assert_called_once_with(TEST_FILES_DIR / "stub_slot_a.efi")
osrel_size = Path("/etc/os-release").stat().st_size

exec_mock.assert_called_once_with([
'objcopy',
'--add-section', '.osrel=/etc/os-release',
'--change-section-vma', '.osrel=0x12150',
'--change-section-vma', '.osrel=0x12800',
'--add-section', '.cmdline={}'.format(TEST_FILES_DIR / "cmdline"),
'--change-section-vma', '.cmdline={}'.format(
hex(74064 + osrel_size)),
hex(align(0x12800 + osrel_size))),
'--add-section', '.initrd={}'.format(TEST_FILES_DIR / "initrd"),
'--change-section-vma', '.initrd={}'.format(
hex(74232 + osrel_size)),
hex(align(0x13000 + osrel_size))),
'--add-section', '.linux={}'.format(TEST_FILES_DIR / "vmlinuz"),
'--change-section-vma', '.linux={}'.format(
hex(76280 + osrel_size)),
hex(align(0x13800 + osrel_size))),
str(TEST_FILES_DIR / "stub_slot_a.efi"),
str(Path("/tmp/file.efi"))])

Expand Down

0 comments on commit 9b95e23

Please sign in to comment.