diff --git a/man/ukify.xml b/man/ukify.xml index 31e54c473a6..28103ea2d43 100644 --- a/man/ukify.xml +++ b/man/ukify.xml @@ -366,6 +366,19 @@ SignKernel=/ is true, and the binary has already been signed, the signature will be appended anyway. + + + SBAT=TEXT|@PATH + + + SBAT metadata associated with the UKI or addon. SBAT policies are useful to revoke + whole groups of UKIs or addons with a single, static policy update that does not take space in + DBX/MOKX. If not specified manually, a default metadata entry consisting of + uki,1,UKI,uki,1,https://www.freedesktop.org/software/systemd/man/systemd-stub.html + will be used, to ensure it is always possible to revoke UKIs and addons. For more information on + SBAT see Shim's documentation. + + @@ -412,27 +425,6 @@ - - - [Addon:<replaceable>NAME</replaceable>] section - - Currently, these options only apply when building PE addons. - - - - SBAT=TEXT|@PATH - - - SBAT metadata associated with the addon. SBAT policies are useful to revoke whole - groups of addons with a single, static policy update that does not take space in DBX/MOKX. If not - specified manually, a default metadata entry consisting of - uki.addon.systemd,1,UKI Addon,uki.addon.systemd,1,https://www.freedesktop.org/software/systemd/man/systemd-stub.html - will be used, to ensure it is always possible to revoke addons. For more information on SBAT see - Shim's documentation. - - - - @@ -457,6 +449,8 @@ --linux=/lib/modules/6.0.9-300.fc37.x86_64/vmlinuz \ --initrd=early_cpio \ --initrd=/some/path/initramfs-6.0.9-300.fc37.x86_64.img \ + --sbat='sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md + uki.author.myimage,1,UKI for System,uki.author.myimage,1,https://www.freedesktop.org/software/systemd/man/systemd-stub.html' \ --pcr-private-key=pcr-private-initrd-key.pem \ --pcr-public-key=pcr-public-initrd-key.pem \ --phases='enter-initrd' \ diff --git a/src/ukify/test/test_ukify.py b/src/ukify/test/test_ukify.py index a6778bb694d..f79a13a36f8 100755 --- a/src/ukify/test/test_ukify.py +++ b/src/ukify/test/test_ukify.py @@ -454,7 +454,14 @@ def test_addon(tmpdir): 'build', f'--output={output}', '--cmdline=ARG1 ARG2 ARG3', + """--sbat=sbat,1,foo +foo,1 +bar,2 +""", '--section=.test:CONTENTZ', + """--sbat=sbat,1,foo +baz,3 +""" ] if stub := os.getenv('EFI_ADDON'): args += [f'--stub={stub}'] @@ -473,9 +480,21 @@ def test_addon(tmpdir): # let's check that objdump likes the resulting file dump = subprocess.check_output(['objdump', '-h', output], text=True) - for sect in 'text cmdline test'.split(): + for sect in 'text cmdline test sbat'.split(): assert re.search(fr'^\s*\d+\s+.{sect}\s+0', dump, re.MULTILINE) + pe = pefile.PE(output, fast_load=True) + found = False + + for section in pe.sections: + if section.Name.rstrip(b"\x00").decode() == ".sbat": + assert found is False + split = section.get_data().rstrip(b"\x00").decode().splitlines() + assert split == ["sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md", "foo,1", "bar,2", "baz,3"] + found = True + + assert found is True + def unbase64(filename): tmp = tempfile.NamedTemporaryFile() diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py index de356d993cb..9ee591d5931 100755 --- a/src/ukify/ukify.py +++ b/src/ukify/ukify.py @@ -601,10 +601,10 @@ def pe_add_sections(uki: UKI, output: str): pe.write(output) -def merge_sbat(input: [pathlib.Path]) -> str: +def merge_sbat(input_pe: [pathlib.Path], input_text: [str]) -> str: sbat = [] - for f in input: + for f in input_pe: try: pe = pefile.PE(f, fast_load=True) except pefile.PEFormatError: @@ -621,6 +621,15 @@ def merge_sbat(input: [pathlib.Path]) -> str: # needs to be first. sbat += split[1:] + for t in input_text: + if t.startswith('@'): + t = pathlib.Path(t[1:]).read_text() + split = t.splitlines() + if not split[0].startswith('sbat,'): + print(f"{t} does not contain a valid SBAT section, skipping.") + continue + sbat += split[1:] + return 'sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md\n' + '\n'.join(sbat) + "\n\x00" def signer_sign(cmd): @@ -755,11 +764,15 @@ def make_uki(opts): # UKI or addon creation - addons don't use the stub so we add SBAT manually if linux is not None: - # Merge the .sbat sections from the stub and the kernel, so that revocation can be done on either. - uki.add_section(Section.create('.sbat', merge_sbat([opts.stub, linux]), measure=False)) + # Merge the .sbat sections from stub, kernel and parameter, so that revocation can be done on either. + uki.add_section(Section.create('.sbat', merge_sbat([opts.stub, linux], opts.sbat), measure=True)) uki.add_section(Section.create('.linux', linux, measure=True)) - elif opts.sbat: - uki.add_section(Section.create('.sbat', opts.sbat, measure=False)) + else: + if not opts.sbat: + opts.sbat = ["""sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md +uki,1,UKI,uki,1,https://www.freedesktop.org/software/systemd/man/systemd-stub.html +"""] + uki.add_section(Section.create('.sbat', merge_sbat([], opts.sbat), measure=False)) if sign_args_present: unsigned = tempfile.NamedTemporaryFile(prefix='uki') @@ -1131,11 +1144,10 @@ CONFIG_ITEMS = [ ConfigItem( '--sbat', metavar = 'TEXT|@PATH', - help = 'SBAT policy [.sbat section] for addons', - default = """sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md -uki.addon,1,UKI Addon,uki.addon,1,https://www.freedesktop.org/software/systemd/man/systemd-stub.html -""", - config_key = 'Addon/SBAT', + help = 'SBAT policy [.sbat section]', + default = [], + action = 'append', + config_key = 'UKI/SBAT', ), ConfigItem(