diff options
author | Steve McIntyre <steve@einval.com> | 2021-03-31 18:24:24 +0100 |
---|---|---|
committer | Steve McIntyre <steve@einval.com> | 2021-03-31 18:24:24 +0100 |
commit | 8119f7183f5f0bebb168fec5239855552020cf66 (patch) | |
tree | 19f2bf9871d671b570a5ccaabc89ffd743b4cd10 | |
parent | 031e5cce385d3f96b1caa1d53495332a7eb03749 (diff) | |
download | efi-boot-shim-upstream/15.4.tar.gz efi-boot-shim-upstream/15.4.zip |
New upstream version 15.4upstream/15.4
-rw-r--r-- | .github/workflows/pullrequest.yml | 24 | ||||
-rw-r--r-- | Make.defaults | 1 | ||||
-rw-r--r-- | Makefile | 52 | ||||
-rw-r--r-- | commit | 2 | ||||
-rw-r--r-- | csv.c | 5 | ||||
-rw-r--r-- | elf_aarch64_efi.lds | 85 | ||||
-rw-r--r-- | elf_arm_efi.lds | 85 | ||||
-rwxr-xr-x | gnu-efi/Make.defaults | 2 | ||||
-rw-r--r-- | gnu-efi/gnuefi/crt0-efi-aarch64.S | 38 | ||||
-rw-r--r-- | gnu-efi/gnuefi/crt0-efi-arm.S | 62 | ||||
-rw-r--r-- | include/sbat.h | 17 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | pe.c | 2 | ||||
-rw-r--r-- | sbat.c | 60 | ||||
-rw-r--r-- | shim.c | 15 | ||||
-rw-r--r-- | test-sbat.c | 85 |
16 files changed, 366 insertions, 171 deletions
diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 41ca282c..5329496c 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -110,14 +110,24 @@ jobs: id: update-submodules run: | make update + - name: Make a build directory for ${{ matrix.distro }} for ${{ matrix.efiarch }} + id: builddir + run: | + rm -rf build-${{ matrix.distro }}-${{ matrix.efiarch }} + mkdir build-${{ matrix.distro }}-${{ matrix.efiarch }} + cd build-${{ matrix.distro }}-${{ matrix.efiarch }} - name: Do the build on ${{ matrix.distro }} for ${{ matrix.efiarch }} id: build run: | - make -s CROSS_COMPILE=${{ matrix.gccarch }}-linux-gnu- ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true clean all || make CROSS_COMPILE=${{ matrix.gccarch }}-linux-gnu- ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true clean all + pwd + cd build-${{ matrix.distro }}-${{ matrix.efiarch }} + make TOPDIR=.. -f ../Makefile CROSS_COMPILE=${{ matrix.gccarch }}-linux-gnu- ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true all - name: Install on ${{ matrix.distro }} for ${{ matrix.efiarch }} id: install run: | - make -s CROSS_COMPILE=${{ matrix.gccarch }}-linux-gnu- ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true install || make CROSS_COMPILE=${{ matrix.gccarch }}-linux-gnu- ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true install + pwd + cd build-${{ matrix.distro }}-${{ matrix.efiarch }} + make TOPDIR=.. -f ../Makefile CROSS_COMPILE=${{ matrix.gccarch }}-linux-gnu- ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true install echo 'results:' find /destdir -type f @@ -190,17 +200,21 @@ jobs: id: update-submodules run: | make update + - name: Do 'make clean' on ${{ matrix.distro }} for ${{ matrix.efiarch }} + id: clean + run: | + make ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true clean - name: Run tests on ${{ matrix.distro }} for ${{ matrix.efiarch }} id: test run: | - make -s ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true test || make ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true test + make ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true test - name: Do the build on ${{ matrix.distro }} for ${{ matrix.efiarch }} id: build run: | - make -s ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true clean all || make ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true clean all + make ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true all - name: Install on ${{ matrix.distro }} for ${{ matrix.efiarch }} id: install run: | - make -s ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true install || make ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true install + make ARCH=${{ matrix.makearch }} PREFIX=/usr DESTDIR=/destdir EFIDIR=test ENABLE_SHIM_HASH=true install echo 'results:' find /destdir -type f diff --git a/Make.defaults b/Make.defaults index b7721547..a775083e 100644 --- a/Make.defaults +++ b/Make.defaults @@ -1,6 +1,7 @@ # load the local configuration if it exists -include Make.local +-include $(TOPDIR)/Make.local COMPILER ?= gcc CC = $(CROSS_COMPILE)$(COMPILER) @@ -1,7 +1,7 @@ default : all NAME = shim -VERSION = 15.3 +VERSION = 15.4 ifneq ($(origin RELEASE),undefined) DASHRELEASE ?= -$(RELEASE) else @@ -45,7 +45,7 @@ MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o errlog.o sbat_data.o ORIG_MOK_SOURCES = MokManager.c PasswordCrypt.c crypt_blowfish.c shim.h $(wildcard include/*.h) FALLBACK_OBJS = fallback.o tpm.o errlog.o sbat_data.o ORIG_FALLBACK_SRCS = fallback.c -SBATPATH = data/sbat.csv +SBATPATH = $(TOPDIR)/data/sbat.csv ifeq ($(SOURCE_DATE_EPOCH),) UNAME=$(shell uname -s -m -p -i -o) @@ -111,7 +111,7 @@ sbat.%.csv : data/sbat.%.csv $(DOS2UNIX) $(D2UFLAGS) $< $@ tail -c1 $@ | read -r _ || echo >> $@ # ensure a trailing newline -VENDOR_SBATS := $(foreach x,$(wildcard data/sbat.*.csv),$(notdir $(x))) +VENDOR_SBATS := $(sort $(foreach x,$(wildcard $(TOPDIR)/data/sbat.*.csv data/sbat.*.csv),$(notdir $(x)))) sbat_data.o : | $(SBATPATH) $(VENDOR_SBATS) sbat_data.o : /dev/null @@ -146,21 +146,23 @@ $(MMSONAME): $(MOK_OBJS) $(LIBS) gnu-efi/$(ARCH_GNUEFI)/gnuefi/libgnuefi.a gnu-efi/$(ARCH_GNUEFI)/lib/libefi.a: CFLAGS+=-DGNU_EFI_USE_EXTERNAL_STDARG gnu-efi/$(ARCH_GNUEFI)/gnuefi/libgnuefi.a gnu-efi/$(ARCH_GNUEFI)/lib/libefi.a: + mkdir -p gnu-efi/lib gnu-efi/gnuefi $(MAKE) -C gnu-efi \ ARCH=$(ARCH_GNUEFI) TOPDIR=$(TOPDIR)/gnu-efi \ + -f $(TOPDIR)/gnu-efi/Makefile \ lib gnuefi inc Cryptlib/libcryptlib.a: for i in Hash Hmac Cipher Rand Pk Pem SysCall; do mkdir -p Cryptlib/$$i; done - $(MAKE) VPATH=$(TOPDIR)/Cryptlib -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile + $(MAKE) TOPDIR=$(TOPDIR) VPATH=$(TOPDIR)/Cryptlib -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile Cryptlib/OpenSSL/libopenssl.a: for i in x509v3 x509 txt_db stack sha rsa rc4 rand pkcs7 pkcs12 pem ocsp objects modes md5 lhash kdf hmac evp err dso dh conf comp cmac buffer bn bio async/arch asn1 aes; do mkdir -p Cryptlib/OpenSSL/crypto/$$i; done - $(MAKE) VPATH=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile + $(MAKE) TOPDIR=$(TOPDIR) VPATH=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile lib/lib.a: | $(TOPDIR)/lib/Makefile $(wildcard $(TOPDIR)/include/*.[ch]) - if [ ! -d lib ]; then mkdir lib ; fi - $(MAKE) VPATH=$(TOPDIR)/lib -C lib -f $(TOPDIR)/lib/Makefile lib.a + mkdir -p lib + $(MAKE) VPATH=$(TOPDIR)/lib TOPDIR=$(TOPDIR) -C lib -f $(TOPDIR)/lib/Makefile buildid : $(TOPDIR)/buildid.c $(HOSTCC) -I/usr/include -Og -g3 -Wall -Werror -Wextra -o $@ $< -lelf @@ -223,6 +225,7 @@ endif install-as-data : install-deps $(INSTALL) -d -m 0755 $(DESTDIR)/$(DATATARGETDIR) $(INSTALL) -m 0644 $(SHIMNAME) $(DESTDIR)/$(DATATARGETDIR)/ + $(INSTALL) -m 0644 $(BOOTCSVNAME) $(DESTDIR)/$(DATATARGETDIR)/ ifneq ($(origin ENABLE_SHIM_HASH),undefined) $(INSTALL) -m 0644 $(SHIMHASHNAME) $(DESTDIR)/$(DATATARGETDIR)/ endif @@ -239,7 +242,7 @@ ifneq ($(OBJCOPY_GTE224),1) $(error objcopy >= 2.24 is required) endif $(OBJCOPY) -D -j .text -j .sdata -j .data -j .data.ident \ - -j .dynamic -j .dynsym -j .rel* \ + -j .dynamic -j .rodata -j .rel* \ -j .rela* -j .reloc -j .eh_frame \ -j .vendor_cert -j .sbat \ $(FORMAT) $< $@ @@ -256,7 +259,7 @@ ifneq ($(OBJCOPY_GTE224),1) $(error objcopy >= 2.24 is required) endif $(OBJCOPY) -D -j .text -j .sdata -j .data \ - -j .dynamic -j .dynsym -j .rel* \ + -j .dynamic -j .rodata -j .rel* \ -j .rela* -j .reloc -j .eh_frame -j .sbat \ -j .debug_info -j .debug_abbrev -j .debug_aranges \ -j .debug_line -j .debug_str -j .debug_ranges \ @@ -275,35 +278,46 @@ else endif test : - @make -f include/test.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" all + @make -f $(TOPDIR)/include/test.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" all $(patsubst %.c,%,$(wildcard test-*.c)) : - @make -f include/test.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" $@ + @make -f $(TOPDIR)/include/test.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" $@ .PHONY : $(patsubst %.c,%,$(wildcard test-*.c)) test clean-test-objs: - @make -f include/test.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" clean + @make -f $(TOPDIR)/include/test.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" clean clean-gnu-efi: - $(MAKE) -C gnu-efi \ - ARCH=$(ARCH_GNUEFI) TOPDIR=$(TOPDIR)/gnu-efi \ - clean + @if [ -d gnu-efi ] ; then \ + $(MAKE) -C gnu-efi \ + ARCH=$(ARCH_GNUEFI) TOPDIR=$(TOPDIR)/gnu-efi \ + -f $(TOPDIR)/gnu-efi/Makefile \ + clean ; \ + fi + +clean-lib-objs: + @if [ -d lib ] ; then \ + $(MAKE) -C lib TOPDIR=$(TOPDIR) -f $(TOPDIR)/lib/Makefile clean ; \ + fi clean-shim-objs: - $(MAKE) -C lib -f $(TOPDIR)/lib/Makefile clean @rm -rvf $(TARGET) *.o $(SHIM_OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb $(BOOTCSVNAME) @rm -vf *.debug *.so *.efi *.efi.* *.tar.* version.c buildid @rm -vf Cryptlib/*.[oa] Cryptlib/*/*.[oa] @if [ -d .git ] ; then git clean -f -d -e 'Cryptlib/OpenSSL/*'; fi clean-openssl-objs: - $(MAKE) -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile clean + @if [ -d Cryptlib/OpenSSL ] ; then \ + $(MAKE) -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile clean ; \ + fi clean-cryptlib-objs: - $(MAKE) -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile clean + @if [ -d Cryptlib ] ; then \ + $(MAKE) -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile clean ; \ + fi -clean: clean-shim-objs clean-test-objs clean-gnu-efi clean-openssl-objs clean-cryptlib-objs +clean: clean-shim-objs clean-test-objs clean-gnu-efi clean-openssl-objs clean-cryptlib-objs clean-lib-objs GITTAG = $(VERSION) @@ -1 +1 @@ -630b8dedfd8434353bce80ff89f63fd3113b086d
\ No newline at end of file +20e4d9486fcae54ee44d2323ae342ffe68c920e6
\ No newline at end of file @@ -55,8 +55,11 @@ parse_csv_data(char *data, char *data_end, size_t n_columns, list_t *list) size_t max = 0; char *end = data_end; - if (!data || !end || end <= data || !n_columns || !list) + if (!data || !end || end <= data || !n_columns || !list) { + dprint(L"data:0x%lx end:0x%lx n_columns:%lu list:0x%lx\n", + data, end, n_columns, list); return EFI_INVALID_PARAMETER; + } max = (uintptr_t)end - (uintptr_t)line + (end > line ? 1 : 0); diff --git a/elf_aarch64_efi.lds b/elf_aarch64_efi.lds index feb4ead9..353b24a0 100644 --- a/elf_aarch64_efi.lds +++ b/elf_aarch64_efi.lds @@ -9,24 +9,12 @@ SECTIONS *(.text) *(.text.*) *(.gnu.linkonce.t.*) - *(.srodata) - *(.rodata*) - . = ALIGN(16); - _etext = .; - } - - . = ALIGN(4096); - .dynamic : { *(.dynamic) } - - . = ALIGN(4096); - .note.gnu.build-id : { - *(.note.gnu.build-id) - } - - . = ALIGN(4096); - .data.ident : { - *(.data.ident) + _evtext = .; + . = ALIGN(4096); } + _etext = .; + _text_size = . - _text; + _text_vsize = _evtext - _text; . = ALIGN(4096); .data : @@ -39,6 +27,8 @@ SECTIONS *(.got.plt) *(.got) + *(.dynamic) + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ . = ALIGN(16); @@ -48,44 +38,61 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - . = ALIGN(16); + _evdata = .; + . = ALIGN(4096); _bss_end = .; } + _edata = .; + _data_vsize = _evdata - _data; + _data_size = . - _data; + /* + * Note that _sbat must be the beginning of the data, and _esbat must be the + * end and must be before any section padding. The sbat self-check uses + * _esbat to find the bounds of the data, and if the padding is included, the + * CSV parser (correctly) rejects the data as having NUL values in one of the + * required columns. + */ . = ALIGN(4096); - .vendor_cert : + .sbat : { - *(.vendor_cert) + _sbat = .; + *(.sbat) + *(.sbat.*) + _esbat = .; + . = ALIGN(4096); + _epsbat = .; } + _sbat_size = _epsbat - _sbat; + _sbat_vsize = _esbat - _sbat; + . = ALIGN(4096); - .rela : + .rodata : { + _rodata = .; *(.rela.dyn) *(.rela.plt) *(.rela.got) *(.rela.data) *(.rela.data*) + + *(.rodata*) + *(.srodata) + *(.dynsym) + *(.dynstr) + . = ALIGN(16); + *(.note.gnu.build-id) + . = ALIGN(4096); + *(.vendor_cert) + *(.data.ident) + _evrodata = .; + . = ALIGN(4096); } - _edata = .; - _data_size = . - _data; - . = ALIGN(4096); - .sbat : - { - _sbat = .; - *(.sbat) - *(.sbat.*) - } - _esbat = .; - _sbat_vsize = . - _sbat; - . = ALIGN(4096); - _sbat_size = . - _sbat; + _erodata = .; + _rodata_size = . - _rodata; + _rodata_vsize = _evrodata - _rodata; _alldata_size = . - _data; - . = ALIGN(4096); - .dynsym : { *(.dynsym) } - . = ALIGN(4096); - .dynstr : { *(.dynstr) } - . = ALIGN(4096); /DISCARD/ : { *(.rel.reloc) diff --git a/elf_arm_efi.lds b/elf_arm_efi.lds index d7de181f..e4e29bdf 100644 --- a/elf_arm_efi.lds +++ b/elf_arm_efi.lds @@ -9,22 +9,12 @@ SECTIONS *(.text) *(.text.*) *(.gnu.linkonce.t.*) - *(.srodata) - *(.rodata*) - . = ALIGN(16); - _etext = .; - } - .dynamic : { *(.dynamic) } - - . = ALIGN(4096); - .note.gnu.build-id : { - *(.note.gnu.build-id) - } - - . = ALIGN(4096); - .data.ident : { - *(.data.ident) + _evtext = .; + . = ALIGN(4096); } + _etext = .; + _text_size = . - _text; + _text_vsize = _evtext - _text; . = ALIGN(4096); .data : @@ -33,10 +23,12 @@ SECTIONS *(.sdata) *(.data) *(.data1) - *(.data*) + *(.data.*) *(.got.plt) *(.got) + *(.dynamic) + /* the EFI loader doesn't seem to like a .bss section, so we stick it all into .data: */ . = ALIGN(16); @@ -46,44 +38,61 @@ SECTIONS *(.dynbss) *(.bss) *(COMMON) - . = ALIGN(16); + _evdata = .; + . = ALIGN(4096); _bss_end = .; } + _edata = .; + _data_vsize = _evdata - _data; + _data_size = . - _data; + /* + * Note that _sbat must be the beginning of the data, and _esbat must be the + * end and must be before any section padding. The sbat self-check uses + * _esbat to find the bounds of the data, and if the padding is included, the + * CSV parser (correctly) rejects the data as having NUL values in one of the + * required columns. + */ . = ALIGN(4096); - .vendor_cert : + .sbat : { - *(.vendor_cert) + _sbat = .; + *(.sbat) + *(.sbat.*) + _esbat = .; + . = ALIGN(4096); + _epsbat = .; } + _sbat_size = _epsbat - _sbat; + _sbat_vsize = _esbat - _sbat; + . = ALIGN(4096); - .rel : + .rodata : { + _rodata = .; *(.rel.dyn) *(.rel.plt) *(.rel.got) *(.rel.data) *(.rel.data*) + + *(.rodata*) + *(.srodata) + *(.dynsym) + *(.dynstr) + . = ALIGN(16); + *(.note.gnu.build-id) + . = ALIGN(4096); + *(.vendor_cert) + *(.data.ident) + _evrodata = .; + . = ALIGN(4096); } - _edata = .; - _data_size = . - _data; - . = ALIGN(4096); - .sbat : - { - _sbat = .; - *(.sbat) - *(.sbat.*) - } - _esbat = .; - _sbat_vsize = . - _sbat; - . = ALIGN(4096); - _sbat_size = . - _sbat; + _erodata = .; + _rodata_size = . - _rodata; + _rodata_vsize = _evrodata - _rodata; _alldata_size = . - _data; - . = ALIGN(4096); - .dynsym : { *(.dynsym) } - . = ALIGN(4096); - .dynstr : { *(.dynstr) } - . = ALIGN(4096); /DISCARD/ : { *(.rel.reloc) diff --git a/gnu-efi/Make.defaults b/gnu-efi/Make.defaults index 362bd1f8..fd1d123d 100755 --- a/gnu-efi/Make.defaults +++ b/gnu-efi/Make.defaults @@ -92,7 +92,7 @@ endif # # Where to build the package # -OBJDIR := $(TOPDIR)/$(ARCH) +OBJDIR := $(abspath .)/$(ARCH) # # Variables below derived from variables above diff --git a/gnu-efi/gnuefi/crt0-efi-aarch64.S b/gnu-efi/gnuefi/crt0-efi-aarch64.S index b41b8e76..a96b5eb8 100644 --- a/gnu-efi/gnuefi/crt0-efi-aarch64.S +++ b/gnu-efi/gnuefi/crt0-efi-aarch64.S @@ -31,7 +31,7 @@ pe_header: .short 0 coff_header: .short 0xaa64 // AArch64 - .short 3 // nr_sections + .short 4 // nr_sections .long 0 // TimeDateStamp .long 0 // PointerToSymbolTable .long 1 // NumberOfSymbols @@ -44,7 +44,7 @@ optional_header: .short 0x20b // PE32+ format .byte 0x02 // MajorLinkerVersion .byte 0x14 // MinorLinkerVersion - .long _data - _start // SizeOfCode + .long _text_size // SizeOfCode .long _alldata_size // SizeOfInitializedData .long 0 // SizeOfUninitializedData .long _start - ImageBase // AddressOfEntryPoint @@ -62,7 +62,7 @@ extra_header_fields: .short 0 // MinorSubsystemVersion .long 0 // Win32VersionValue - .long _esbat - ImageBase // SizeOfImage + .long _erodata - ImageBase // SizeOfImage // Everything before the kernel image is considered part of the header .long _start - ImageBase // SizeOfHeaders @@ -86,19 +86,22 @@ extra_header_fields: // Section table section_table: .ascii ".text\0\0\0" - .long _data - _start // VirtualSize + .long _evtext - _start // VirtualSize .long _start - ImageBase // VirtualAddress - .long _data - _start // SizeOfRawData + .long _etext - _start // SizeOfRawData .long _start - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) + /* + * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_CNT_CODE + */ .long 0x60000020 // Characteristics (section flags) .ascii ".data\0\0\0" - .long _data_size // VirtualSize + .long _data_vsize // VirtualSize .long _data - ImageBase // VirtualAddress .long _data_size // SizeOfRawData .long _data - ImageBase // PointerToRawData @@ -107,9 +110,12 @@ section_table: .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) + /* + * EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + */ .long 0xc0000040 // Characteristics (section flags) - .ascii ".sbat\0\0\0" + .ascii ".sbat\0\0\0" .long _sbat_vsize // VirtualSize .long _sbat - ImageBase // VirtualAddress .long _sbat_size // SizeOfRawData @@ -119,6 +125,24 @@ section_table: .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) + /* + * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_ALIGN_8BYTES | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + */ + .long 0x40400040 // Characteristics (section flags) + + .ascii ".rodata\0" + .long _rodata_vsize // VirtualSize + .long _rodata - ImageBase // VirtualAddress + .long _rodata_size // SizeOfRawData + .long _rodata - ImageBase // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + /* + * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_ALIGN_8BYTES | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + */ .long 0x40400040 // Characteristics (section flags) .align 12 diff --git a/gnu-efi/gnuefi/crt0-efi-arm.S b/gnu-efi/gnuefi/crt0-efi-arm.S index 6401363c..1efc21c3 100644 --- a/gnu-efi/gnuefi/crt0-efi-arm.S +++ b/gnu-efi/gnuefi/crt0-efi-arm.S @@ -31,7 +31,7 @@ pe_header: .short 0 coff_header: .short 0x1c2 // Mixed ARM/Thumb - .short 3 // nr_sections + .short 4 // nr_sections .long 0 // TimeDateStamp .long 0 // PointerToSymbolTable .long 1 // NumberOfSymbols @@ -45,17 +45,17 @@ optional_header: .short 0x10b // PE32+ format .byte 0x02 // MajorLinkerVersion .byte 0x14 // MinorLinkerVersion - .long _data - _start // SizeOfCode + .long _text_size // SizeOfCode .long _alldata_size // SizeOfInitializedData .long 0 // SizeOfUninitializedData .long _start - ImageBase // AddressOfEntryPoint .long _start - ImageBase // BaseOfCode - .long 0 // BaseOfData + .long _data - ImageBase // BaseOfData extra_header_fields: .long 0 // ImageBase - .long 0x20 // SectionAlignment - .long 0x8 // FileAlignment + .long 0x800 // SectionAlignment + .long 0x200 // FileAlignment .short 0 // MajorOperatingSystemVersion .short 0 // MinorOperatingSystemVersion .short 0 // MajorImageVersion @@ -64,7 +64,7 @@ extra_header_fields: .short 0 // MinorSubsystemVersion .long 0 // Win32VersionValue - .long _esbat - ImageBase // SizeOfImage + .long _erodata - ImageBase // SizeOfImage // Everything before the kernel image is considered part of the header .long _start - ImageBase // SizeOfHeaders @@ -88,6 +88,7 @@ extra_header_fields: // Section table section_table: +#if 0 /* * The EFI application loader requires a relocation section * because EFI applications must be relocatable. This is a @@ -105,23 +106,37 @@ section_table: .short 0 // NumberOfRelocations .short 0 // NumberOfLineNumbers .long 0x42100040 // Characteristics (section flags) +#endif - - .ascii ".text" - .byte 0 - .byte 0 - .byte 0 // end of 0 padding of section name - .long _edata - _start // VirtualSize + .ascii ".text\0\0\0" + .long _evtext - _start // VirtualSize .long _start - ImageBase // VirtualAddress - .long _edata - _start // SizeOfRawData + .long _etext - _start // SizeOfRawData .long _start - ImageBase // PointerToRawData .long 0 // PointerToRelocations (0 for executables) .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) - .long 0xe0500020 // Characteristics (section flags) + /* + * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_CNT_CODE + */ + .long 0x60000020 // Characteristics (section flags) + + .ascii ".data\0\0\0" + .long _data_vsize // VirtualSize + .long _data - ImageBase // VirtualAddress + .long _data_size // SizeOfRawData + .long _data - ImageBase // PointerToRawData + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + /* + * EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + */ + .long 0xc0000040 // Characteristics (section flags) .ascii ".sbat\0\0\0" .long _sbat_vsize // VirtualSize @@ -133,9 +148,28 @@ section_table: .long 0 // PointerToLineNumbers (0 for executables) .short 0 // NumberOfRelocations (0 for executables) .short 0 // NumberOfLineNumbers (0 for executables) + /* + * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_ALIGN_8BYTES | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + */ + .long 0x40400040 // Characteristics (section flags) + + .ascii ".rodata\0" + .long _rodata_vsize // VirtualSize + .long _rodata - ImageBase // VirtualAddress + .long _rodata_size // SizeOfRawData + .long _rodata - ImageBase // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + /* + * EFI_IMAGE_SCN_MEM_READ | EFI_IMAGE_SCN_ALIGN_8BYTES | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + */ .long 0x40400040 // Characteristics (section flags) + .align 11 _start: stmfd sp!, {r0-r2, lr} diff --git a/include/sbat.h b/include/sbat.h index 5db82379..8551b74a 100644 --- a/include/sbat.h +++ b/include/sbat.h @@ -20,16 +20,16 @@ (UEFI_VAR_NV_BS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) #if defined(ENABLE_SHIM_DEVEL) -#define SBAT_VAR_NAME L"SBAT_DEVEL" -#define SBAT_VAR_NAME8 "SBAT_DEVEL" -#define SBAT_RT_VAR_NAME L"SbatRT_DEVEL" -#define SBAT_RT_VAR_NAME8 "SbatRT_DEVEL" +#define SBAT_VAR_NAME L"SbatLevel_DEVEL" +#define SBAT_VAR_NAME8 "SbatLevel_DEVEL" +#define SBAT_RT_VAR_NAME L"SbatLevelRT_DEVEL" +#define SBAT_RT_VAR_NAME8 "SbatLevelRT_DEVEL" #define SBAT_VAR_ATTRS UEFI_VAR_NV_BS_RT #else -#define SBAT_VAR_NAME L"SBAT" -#define SBAT_VAR_NAME8 "SBAT" -#define SBAT_RT_VAR_NAME L"SbatRT" -#define SBAT_RT_VAR_NAME8 "SbatRT" +#define SBAT_VAR_NAME L"SbatLevel" +#define SBAT_VAR_NAME8 "SbatLevel" +#define SBAT_RT_VAR_NAME L"SbatLevelRT" +#define SBAT_RT_VAR_NAME8 "SbatLevelRT" #define SBAT_VAR_ATTRS UEFI_VAR_NV_BS #endif @@ -51,6 +51,7 @@ extern list_t sbat_var; EFI_STATUS parse_sbat_var(list_t *entries); void cleanup_sbat_var(list_t *entries); EFI_STATUS set_sbat_uefi_variable(void); +bool preserve_sbat_uefi_variable(UINT8 *sbat, UINTN sbatsize, UINT32 attributes); struct sbat_section_entry { const CHAR8 *component_name; diff --git a/lib/Makefile b/lib/Makefile index 6d83f789..a4a4855b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,6 +1,6 @@ TARGET = lib.a -LIBFILES_UNSORTED := $(foreach x,$(wildcard *.c),$(patsubst %.c,%.o,$(x))) +LIBFILES_UNSORTED := $(patsubst %.c,%.o,$(subst $(TOPDIR)/lib/,,$(wildcard $(TOPDIR)/lib/*.c))) LIBFILES := $(sort $(LIBFILES_UNSORTED)) CRYPTDIR = $(TOPDIR)/Cryptlib @@ -1054,6 +1054,8 @@ handle_image (void *data, unsigned int datasize, SBATBase = base; /* +1 because of size vs last byte location */ SBATSize = end - base + 1; + dprint(L"sbat section base:0x%lx size:0x%lx\n", + SBATBase, SBATSize); } } @@ -18,14 +18,20 @@ parse_sbat_section(char *section_base, size_t section_size, size_t n; char *strtab; - if (!section_base || !section_size || !n_entries || !entriesp) + if (!section_base || !section_size || !n_entries || !entriesp) { + dprint(L"section_base:0x%lx section_size:0x%lx\n", + section_base, section_size); + dprint(L"n_entries:0x%lx entriesp:0x%lx\n", + n_entries, entriesp); return EFI_INVALID_PARAMETER; + } INIT_LIST_HEAD(&csv); efi_status = parse_csv_data(section_base, end, SBAT_SECTION_COLUMNS, &csv); if (EFI_ERROR(efi_status)) { + dprint(L"parse_csv_data failed: %r\n", efi_status); return efi_status; } @@ -38,6 +44,8 @@ parse_sbat_section(char *section_base, size_t section_size, if (row->n_columns < SBAT_SECTION_COLUMNS) { efi_status = EFI_INVALID_PARAMETER; + dprint(L"row->n_columns:%lu SBAT_SECTION_COLUMNS:%lu\n", + row->n_columns, SBAT_SECTION_COLUMNS); goto err; } @@ -45,6 +53,7 @@ parse_sbat_section(char *section_base, size_t section_size, allocsz += sizeof(struct sbat_section_entry); for (i = 0; i < row->n_columns; i++) { if (row->columns[i][0] == '\000') { + dprint(L"row[%lu].columns[%lu][0] == '\\000'\n", n, i); efi_status = EFI_INVALID_PARAMETER; goto err; } @@ -120,8 +129,8 @@ verify_single_entry(struct sbat_section_entry *entry, struct sbat_var_entry *sba sbat_var_gen = atoi((const char *)sbat_var_entry->component_generation); if (sbat_gen < sbat_var_gen) { - dprint(L"component %a, generation %d, was revoked by SBAT variable", - entry->component_name, sbat_gen); + dprint(L"component %a, generation %d, was revoked by %s variable\n", + entry->component_name, sbat_gen, SBAT_VAR_NAME); LogError(L"image did not pass SBAT verification\n"); return EFI_SECURITY_VIOLATION; } @@ -139,7 +148,7 @@ cleanup_sbat_var(list_t *entries) list_for_each_safe(pos, tmp, entries) { entry = list_entry(pos, struct sbat_var_entry, list); - if ((uintptr_t)entry < (uintptr_t)first && entry != NULL) + if (first == NULL || (uintptr_t)entry < (uintptr_t)first) first = entry; list_del(&entry->list); @@ -157,7 +166,7 @@ verify_sbat_helper(list_t *local_sbat_var, size_t n, struct sbat_section_entry * struct sbat_var_entry *sbat_var_entry; if (list_empty(local_sbat_var)) { - dprint(L"SBAT variable not present\n"); + dprint(L"%s variable not present\n", SBAT_VAR_NAME); return EFI_SUCCESS; } @@ -239,10 +248,10 @@ parse_sbat_var_data(list_t *entry_list, UINT8 *data, UINTN datasize) INIT_LIST_HEAD(entry_list); - entries = (struct sbat_var_entry **)strtab; - strtab += sizeof(struct sbat_var_entry *) * n; entry = (struct sbat_var_entry *)strtab; strtab += sizeof(struct sbat_var_entry) * n; + entries = (struct sbat_var_entry **)strtab; + strtab += sizeof(struct sbat_var_entry *) * n; n = 0; list_for_each(pos, &csv) { @@ -277,8 +286,10 @@ parse_sbat_var(list_t *entries) UINTN datasize; EFI_STATUS efi_status; - if (!entries) + if (!entries) { + dprint(L"entries is NULL\n"); return EFI_INVALID_PARAMETER; + } efi_status = get_variable(SBAT_VAR_NAME, &data, &datasize, SHIM_LOCK_GUID); if (EFI_ERROR(efi_status)) { @@ -304,6 +315,14 @@ check_sbat_var_attributes(UINT32 attributes) #endif } +bool +preserve_sbat_uefi_variable(UINT8 *sbat, UINTN sbatsize, UINT32 attributes) +{ + return check_sbat_var_attributes(attributes) && + sbatsize >= strlen(SBAT_VAR_SIG "1") && + !strncmp((const char *)sbat, SBAT_VAR_SIG, strlen(SBAT_VAR_SIG)); +} + EFI_STATUS set_sbat_uefi_variable(void) { @@ -316,19 +335,16 @@ set_sbat_uefi_variable(void) efi_status = get_variable_attr(SBAT_VAR_NAME, &sbat, &sbatsize, SHIM_LOCK_GUID, &attributes); /* - * Always set the SBAT UEFI variable if it fails to read. + * Always set the SbatLevel UEFI variable if it fails to read. * - * Don't try to set the SBAT UEFI variable if attributes match and - * the signature matches. + * Don't try to set the SbatLevel UEFI variable if attributes match + * and the signature matches. */ if (EFI_ERROR(efi_status)) { dprint(L"SBAT read failed %r\n", efi_status); - } else if (check_sbat_var_attributes(attributes) && - sbatsize >= strlen(SBAT_VAR_SIG "1") && - strncmp((const char *)sbat, SBAT_VAR_SIG, - strlen(SBAT_VAR_SIG))) { - dprint("SBAT variable is %d bytes, attributes are 0x%08x\n", - sbatsize, attributes); + } else if (preserve_sbat_uefi_variable(sbat, sbatsize, attributes)) { + dprint(L"%s variable is %d bytes, attributes are 0x%08x\n", + SBAT_VAR_NAME, sbatsize, attributes); FreePool(sbat); return EFI_SUCCESS; } else { @@ -341,7 +357,8 @@ set_sbat_uefi_variable(void) efi_status = set_variable(SBAT_VAR_NAME, SHIM_LOCK_GUID, attributes, 0, ""); if (EFI_ERROR(efi_status)) { - dprint(L"SBAT variable delete failed %r\n", efi_status); + dprint(L"%s variable delete failed %r\n", SBAT_VAR_NAME, + efi_status); return efi_status; } } @@ -350,7 +367,8 @@ set_sbat_uefi_variable(void) efi_status = set_variable(SBAT_VAR_NAME, SHIM_LOCK_GUID, SBAT_VAR_ATTRS, sizeof(SBAT_VAR)-1, SBAT_VAR); if (EFI_ERROR(efi_status)) { - dprint(L"SBAT variable writing failed %r\n", efi_status); + dprint(L"%s variable writing failed %r\n", SBAT_VAR_NAME, + efi_status); return efi_status; } @@ -358,7 +376,7 @@ set_sbat_uefi_variable(void) efi_status = get_variable(SBAT_VAR_NAME, &sbat, &sbatsize, SHIM_LOCK_GUID); if (EFI_ERROR(efi_status)) { - dprint(L"SBAT read failed %r\n", efi_status); + dprint(L"%s read failed %r\n", SBAT_VAR_NAME, efi_status); return efi_status; } @@ -368,7 +386,7 @@ set_sbat_uefi_variable(void) strlen(SBAT_VAR)); efi_status = EFI_INVALID_PARAMETER; } else { - dprint(L"SBAT variable initialization succeeded\n"); + dprint(L"%s variable initialization succeeded\n", SBAT_VAR_NAME); } FreePool(sbat); @@ -1895,7 +1895,7 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) L"shim_init() failed", L"import of SBAT data failed", L"SBAT self-check failed", - L"SBAT UEFI variable setting failed", + SBAT_VAR_NAME L" UEFI variable setting failed", NULL }; enum { @@ -1935,12 +1935,12 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) efi_status = set_sbat_uefi_variable(); if (EFI_ERROR(efi_status) && secure_mode()) { - perror(L"SBAT variable initialization failed\n"); + perror(L"%s variable initialization failed\n", SBAT_VAR_NAME); msg = SET_SBAT; goto die; } else if (EFI_ERROR(efi_status)) { - dprint(L"SBAT variable initialization failed: %r\n", - efi_status); + dprint(L"%s variable initialization failed: %r\n", + SBAT_VAR_NAME, efi_status); } if (secure_mode()) { @@ -1950,19 +1950,20 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) INIT_LIST_HEAD(&sbat_var); efi_status = parse_sbat_var(&sbat_var); if (EFI_ERROR(efi_status)) { - perror(L"Parsing SBAT variable failed: %r\n", - efi_status); + perror(L"Parsing %s variable failed: %r\n", + SBAT_VAR_NAME, efi_status); msg = IMPORT_SBAT; goto die; } - efi_status = handle_sbat(sbat_start, sbat_end - sbat_start); + efi_status = handle_sbat(sbat_start, sbat_end - sbat_start - 1); if (EFI_ERROR(efi_status)) { perror(L"Verifiying shim SBAT data failed: %r\n", efi_status); msg = SBAT_SELF_CHECK; goto die; } + dprint(L"SBAT self-check succeeded\n"); } init_openssl(); diff --git a/test-sbat.c b/test-sbat.c index 780e5cbe..b64aa1e9 100644 --- a/test-sbat.c +++ b/test-sbat.c @@ -319,6 +319,7 @@ test_parse_sbat_section_too_many_elem(void) struct sbat_section_entry *test_entries[] = { &test_section_entry1, &test_section_entry2, }; + int rc = -1; status = parse_sbat_section(section_base, section_size, &n, &entries); assert_equal_return(status, EFI_SUCCESS, -1, "got %#hhx expected %#hhx\n"); @@ -341,10 +342,10 @@ test_parse_sbat_section_too_many_elem(void) #undef mkassert } assert_equal_goto(n, 2, fail, "got %zu expected %d\n"); - return 0; + rc = 0; fail: cleanup_sbat_section_entries(n, entries); - return -1; + return rc; } /* @@ -439,14 +440,19 @@ test_verify_sbat_null_sbat_section(void) list_t test_sbat_var; size_t n = 0; struct sbat_section_entry **entries = NULL; + int rc = -1; INIT_LIST_HEAD(&test_sbat_var); status = parse_sbat_var_data(&test_sbat_var, sbat_var_data, sizeof(sbat_var_data)); - assert_equal_return(status, EFI_SUCCESS, -1, "got %#x expected %#x\n"); + assert_equal_goto(status, EFI_SUCCESS, err, "got %#x expected %#x\n"); - status = verify_sbat_helper(&sbat_var, n, entries); - assert_equal_return(status, EFI_SUCCESS, -1, "got %#x expected %#x\n"); - return 0; + status = verify_sbat_helper(&test_sbat_var, n, entries); + assert_equal_goto(status, EFI_SUCCESS, err, "got %#x expected %#x\n"); + rc = 0; +err: + cleanup_sbat_var(&test_sbat_var); + + return rc; } #if 0 @@ -902,6 +908,7 @@ test_parse_and_verify(void) struct sbat_section_entry *test_entries[] = { &test_section_entry1, &test_section_entry2, }; + int rc = -1; status = parse_sbat_section(sbat_section, sizeof(sbat_section)-1, &n_section_entries, §ion_entries); @@ -940,16 +947,71 @@ test_parse_and_verify(void) INIT_LIST_HEAD(&sbat_var); status = parse_sbat_var_data(&sbat_var, sbat_var_alloced, sbat_var_data_size); + free(sbat_var_alloced); if (status != EFI_SUCCESS || list_empty(&sbat_var)) return -1; status = verify_sbat(n_section_entries, section_entries); + assert_equal_goto(status, EFI_SECURITY_VIOLATION, err, "expected %#x got %#x\n"); - assert_equal_return(status, EFI_SECURITY_VIOLATION, -1, "expected %#x got %#x\n"); - cleanup_sbat_var(&sbat_var); + rc = 0; +err: cleanup_sbat_section_entries(n_section_entries, section_entries); + cleanup_sbat_var(&sbat_var); - return 0; + return rc; +} + +int +test_preserve_sbat_uefi_variable_good(void) +{ + char sbat[] = "sbat,1,\ncomponent,2,\n"; + size_t sbat_size = sizeof(sbat); + UINT32 attributes = SBAT_VAR_ATTRS; + + if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes)) + return 0; + else + return -1; +} + +int +test_preserve_sbat_uefi_variable_bad_sig(void) +{ + char sbat[] = "bad_sig,1,\ncomponent,2,\n"; + size_t sbat_size = sizeof(sbat); + UINT32 attributes = SBAT_VAR_ATTRS; + + if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes)) + return -1; + else + return 0; +} + +int +test_preserve_sbat_uefi_variable_bad_attr(void) +{ + char sbat[] = "sbat,1,\ncomponent,2,\n"; + size_t sbat_size = sizeof(sbat); + UINT32 attributes = 0; + + if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes)) + return -1; + else + return 0; +} + +int +test_preserve_sbat_uefi_variable_bad_short(void) +{ + char sbat[] = "sba"; + size_t sbat_size = sizeof(sbat); + UINT32 attributes = SBAT_VAR_ATTRS; + + if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes)) + return -1; + else + return 0; } int @@ -989,6 +1051,11 @@ main(void) #endif test(test_parse_and_verify); + test(test_preserve_sbat_uefi_variable_good); + test(test_preserve_sbat_uefi_variable_bad_sig); + test(test_preserve_sbat_uefi_variable_bad_attr); + test(test_preserve_sbat_uefi_variable_bad_short); + return 0; } |