]> git.proxmox.com Git - efi-boot-shim.git/commitdiff
New upstream version 15.6
authorSteve McIntyre <steve@einval.com>
Wed, 22 Jun 2022 23:16:56 +0000 (00:16 +0100)
committerSteve McIntyre <steve@einval.com>
Wed, 22 Jun 2022 23:16:56 +0000 (00:16 +0100)
41 files changed:
.github/workflows/pullrequest.yml
.gitmodules
BUILDING
CODE_OF_CONDUCT.md [new file with mode: 0644]
Make.defaults
Make.rules
Makefile
MokManager.c
commit
data/sbat.csv
elf_aarch64_efi.lds
fallback.c
globals.c
gnu-efi/Make.defaults
gnu-efi/gnuefi/crt0-efi-aarch64.S
gnu-efi/gnuefi/crt0-efi-ia32.S
gnu-efi/gnuefi/crt0-efi-x86_64.S
gnu-efi/inc/efidef.h
gnu-efi/inc/efiprot.h
include/compiler.h
include/guid.h
include/mok.h
include/pe.h
include/peimage.h
include/sbat.h
include/test-data-efivars-1.h
include/test.mk
lib/Makefile
lib/console.c
lib/guid.c
mock-variables.c
mok.c
pe.c
post-process-pe.c
sbat.c
shim.c
shim.h
test-mok-mirror.c
test-sbat.c
test-str.c
test.c

index 5329496c6a8599bd8553196ae5d271e6c21b1b16..18fe5645e8c23876a6cbed919360c3f7fddca416 100644 (file)
@@ -15,88 +15,64 @@ jobs:
     name: ${{ matrix.distro }} ${{ matrix.efiarch }} cross-build
 
     strategy:
+      fail-fast: false
       matrix:
         include:
           - arch: amd64
             efiarch: aa64
             gccarch: aarch64
             makearch: aarch64
-            distro: f35
-          - arch: amd64
-            efiarch: aa64
-            gccarch: aarch64
-            makearch: aarch64
-            distro: f34
+            distro: f36
           - arch: amd64
             efiarch: aa64
             gccarch: aarch64
             makearch: aarch64
-            distro: f33
-          - arch: amd64
-            efiarch: aa64
-            gccarch: aarch64
-            makearch: aarch64
-            distro: f32
-          - arch: amd64
-            efiarch: arm
-            gccarch: arm
-            makearch: arm
             distro: f35
           - arch: amd64
             efiarch: arm
             gccarch: arm
             makearch: arm
-            distro: f34
+            distro: f36
           - arch: amd64
             efiarch: arm
             gccarch: arm
             makearch: arm
-            distro: f33
+            distro: f35
           - arch: amd64
             efiarch: arm
             gccarch: arm
             makearch: arm
-            distro: f32
-          - arch: amd64
-            efiarch: x64
-            gccarch: x86_64
-            makearch: x86_64
-            distro: f35
+            distro: f34
           - arch: amd64
             efiarch: x64
             gccarch: x86_64
             makearch: x86_64
-            distro: f34
+            distro: f36
           - arch: amd64
             efiarch: x64
             gccarch: x86_64
             makearch: x86_64
-            distro: f33
+            distro: f35
           - arch: amd64
             efiarch: x64
             gccarch: x86_64
             makearch: x86_64
-            distro: f32
-          - arch: amd64
-            efiarch: ia32
-            gccarch: x86_64
-            makearch: ia32
-            distro: f35
+            distro: f34
           - arch: amd64
             efiarch: ia32
             gccarch: x86_64
             makearch: ia32
-            distro: f34
+            distro: f36
           - arch: amd64
             efiarch: ia32
             gccarch: x86_64
             makearch: ia32
-            distro: f33
+            distro: f35
           - arch: amd64
             efiarch: ia32
             gccarch: x86_64
             makearch: ia32
-            distro: f32
+            distro: f34
 
     steps:
       - name: Checkout
@@ -142,19 +118,19 @@ jobs:
           - arch: amd64
             efiarch: x64
             makearch: x86_64
-            distro: f35
+            distro: f36
           - arch: amd64
             efiarch: x64
             makearch: x86_64
-            distro: f34
+            distro: f35
           - arch: amd64
             efiarch: x64
             makearch: x86_64
-            distro: f33
+            distro: f34
           - arch: amd64
             efiarch: x64
             makearch: x86_64
-            distro: f32
+            distro: centos9
           - arch: amd64
             efiarch: x64
             makearch: x86_64
@@ -166,19 +142,15 @@ jobs:
           - arch: amd64
             efiarch: ia32
             makearch: ia32
-            distro: f35
+            distro: f36
           - arch: amd64
             efiarch: ia32
             makearch: ia32
-            distro: f34
-          - arch: amd64
-            efiarch: ia32
-            makearch: ia32
-            distro: f33
+            distro: f35
           - arch: amd64
             efiarch: ia32
             makearch: ia32
-            distro: f32
+            distro: f34
           - arch: amd64
             efiarch: ia32
             makearch: ia32
index 1029752d340dbd5d1204efe7081baac1962f0fd8..78424fbd7e4c3269e66b6e39cac720258bb48d35 100644 (file)
@@ -1,4 +1,4 @@
 [submodule "gnu-efi"]
        path = gnu-efi
        url = https://github.com/rhboot/gnu-efi.git
-       branch = shim-15.5
+       branch = shim-15.6
index 2da9b5f045326ef4e8aaf33cca6c93e70151af5b..3b2e85d3400ebd7094ee2b29431648e0f2b02980 100644 (file)
--- a/BUILDING
+++ b/BUILDING
@@ -35,7 +35,8 @@ Variables you could set to customize the build:
   If this is set, we look for SHIM_DEVEL_DEBUG instead of SHIM_DEBUG in
   our debugger delay hook, thus meaning you can have it pause for a
   debugger only on the development branch and not the OS you need to boot
-  to scp in a new development build.
+  to scp in a new development build.  Likewise, we look for
+  SHIM_DEVEL_VERBOSE rather than SHIM_VERBOSE.
 - DISABLE_EBS_PROTECTION
   On systems where a second stage bootloader is not used, and the Linux
   Kernel is embedded in the same EFI image as shim and booted directly
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644 (file)
index 0000000..59a2c94
--- /dev/null
@@ -0,0 +1,134 @@
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+  overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+  advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+  address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+rharwood AT redhat DOT com.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior,  harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
+at [https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
+
index 18677daad5d31f8dfcc4abd7c82834d9f4313f06..dfed9c4a3c7658f6d5e5994506ecfe066f833d02 100644 (file)
@@ -84,9 +84,7 @@ ifeq ($(ARCH),aarch64)
        ARCH_GNUEFI             ?= aarch64
        ARCH_SUFFIX             ?= aa64
        ARCH_SUFFIX_UPPER       ?= AA64
-       FORMAT                  := -O binary
-       SUBSYSTEM               := 0xa
-       ARCH_LDFLAGS            += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
+       ARCH_LDFLAGS            ?=
        ARCH_CFLAGS             ?=
 endif
 ifeq ($(ARCH),arm)
index 532aab66c03b04665c1516cf1f98872520f1a7cc..7c6ec6c0227c4323b4fd9aacfeb4440670f21dab 100644 (file)
@@ -35,4 +35,7 @@ $(strip $(foreach x,$(DEFAULT_$(1)),
                $(eval override $(1)+=$(x)))))
 endef
 
+%.o : %.S
+       $(CC) $(CFLAGS) -c -o $@ $<
+
 # vim:filetype=make
index 6b50b8fea0ce72207a1da817e02bd7183980bfd6..24ac314e04fda69de8e027fdca565795c8dd8058 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 default : all
 
 NAME           = shim
-VERSION                = 15.5
+VERSION                = 15.6
 ifneq ($(origin RELEASE),undefined)
 DASHRELEASE    ?= -$(RELEASE)
 else
@@ -40,7 +40,7 @@ TARGETS += $(MMNAME) $(FBNAME)
 endif
 OBJS   = shim.o globals.o mok.o netboot.o cert.o replacements.o tpm.o version.o errlog.o sbat.o sbat_data.o pe.o httpboot.o csv.o load-options.o
 KEYS   = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer
-ORIG_SOURCES   = shim.c globals.c mok.c netboot.c replacements.c tpm.c errlog.c sbat.c pe.c httpboot.c shim.h version.h $(wildcard include/*.h)
+ORIG_SOURCES   = shim.c globals.c mok.c netboot.c replacements.c tpm.c errlog.c sbat.c pe.c httpboot.c shim.h version.h $(wildcard include/*.h) cert.S
 MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o errlog.o sbat_data.o globals.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 globals.o
@@ -108,9 +108,6 @@ shim.o: shim_cert.h
 endif
 shim.o: $(wildcard $(TOPDIR)/*.h)
 
-cert.o : $(TOPDIR)/cert.S
-       $(CC) $(CFLAGS) -c -o $@ $<
-
 sbat.%.csv : data/sbat.%.csv
        $(DOS2UNIX) $(D2UFLAGS) $< $@
        tail -c1 $@ | read -r _ || echo >> $@ # ensure a trailing newline
@@ -154,6 +151,7 @@ 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 \
                COMPILER="$(COMPILER)" \
+               CCC_CC="$(COMPILER)" \
                CC="$(CC)" \
                ARCH=$(ARCH_GNUEFI) \
                TOPDIR=$(TOPDIR)/gnu-efi \
index 1359af83705512312f19a13612deaf49c339c043..ffcd6a6eb2300307e646947913f9f7e553f31fbb 100644 (file)
@@ -1776,27 +1776,25 @@ static EFI_STATUS mok_tml_prompt(void *MokTML, UINTN MokTMLSize)
                LibDeleteVariable(L"MokListTrustedNew", &SHIM_LOCK_GUID);
                return EFI_ABORTED;
        }
-
        if (var->MokTMLState == 0) {
                efi_status = RT->SetVariable(L"MokListTrusted", &SHIM_LOCK_GUID,
                                              EFI_VARIABLE_NON_VOLATILE |
                                              EFI_VARIABLE_BOOTSERVICE_ACCESS,
-                                             1, &dbval);
+                                             0, NULL);
                if (EFI_ERROR(efi_status)) {
-                       console_notify(L"Failed to set MokListTrusted state");
+                       console_notify(L"Failed to delete MokListTrusted state");
                        return efi_status;
                }
        } else {
                efi_status = RT->SetVariable(L"MokListTrusted", &SHIM_LOCK_GUID,
                                              EFI_VARIABLE_NON_VOLATILE |
                                              EFI_VARIABLE_BOOTSERVICE_ACCESS,
-                                             0, NULL);
+                                             1, &dbval);
                if (EFI_ERROR(efi_status)) {
-                       console_notify(L"Failed to delete MokListTrusted state");
+                       console_notify(L"Failed to set MokListTrusted state");
                        return efi_status;
                }
        }
-
        return EFI_SUCCESS;
 }
 
diff --git a/commit b/commit
index ef9904932131d845e335a29f88c6fe9594c1bd7d..46059769028578832db238d04b23d5c42a5cecb2 100644 (file)
--- a/commit
+++ b/commit
@@ -1 +1 @@
-f2c598bb2218da966872ba3e0c6e7e830dca6ef0
\ No newline at end of file
+505cdb678b319fcf9a7fdee77c0f091b4147cbe5
\ No newline at end of file
index ad838f2aff3b860af0aa8b13d6b12cf418877d2e..7a5169fb39f69e097605cc826f43785453d61c45 100755 (executable)
@@ -1,2 +1,2 @@
 sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
-shim,1,UEFI shim,shim,1,https://github.com/rhboot/shim
+shim,2,UEFI shim,shim,1,https://github.com/rhboot/shim
index 42825fd939de03ef3cb03c5b6bece9b891544f1e..60c55ba5fe12cf9154a4e9a938f444ea9663c9ba 100644 (file)
@@ -3,109 +3,94 @@ OUTPUT_ARCH(aarch64)
 ENTRY(_start)
 SECTIONS
 {
-  .text 0x0 : {
-    _text = .;
-    *(.text.head)
-    *(.text)
-    *(.text.*)
-    *(.gnu.linkonce.t.*)
-    _evtext = .;
-    . = ALIGN(4096);
+  . = 0;
+  ImageBase = .;
+  .hash : { *(.hash) } /* this MUST come first! */
+  . = ALIGN(4096);
+  .eh_frame :
+  {
+    *(.eh_frame)
+  }
+  . = ALIGN(4096);
+  .text :
+  {
+   _text = .;
+   *(.text)
+   *(.text.*)
+   *(.gnu.linkonce.t.*)
+   _etext = .;
+  }
+  . = ALIGN(4096);
+  .reloc :
+  {
+   *(.reloc)
+  }
+  . = ALIGN(4096);
+  .note.gnu.build-id : {
+    *(.note.gnu.build-id)
+  }
+
+  . = ALIGN(4096);
+  .data.ident : {
+    *(.data.ident)
   }
-  _etext = .;
-  _text_size = . - _text;
-  _text_vsize = _evtext - _text;
 
   . = ALIGN(4096);
   .data :
   {
    _data = .;
-   *(.sdata)
-   *(.data)
-   *(.data1)
-   *(.data.*)
+   *(.rodata*)
    *(.got.plt)
    *(.got)
-
-   *(.dynamic)
-
+   *(.data*)
+   *(.sdata)
    /* the EFI loader doesn't seem to like a .bss section, so we stick
       it all into .data: */
-   . = ALIGN(16);
-   _bss = .;
    *(.sbss)
    *(.scommon)
    *(.dynbss)
    *(.bss)
    *(COMMON)
-   _evdata = .;
-   . = ALIGN(4096);
-   _bss_end = .;
+   *(.rel.local)
   }
-  _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);
-  .sbat :
+  .vendor_cert :
   {
-    _sbat = .;
-    *(.sbat)
-    *(.sbat.*)
-    _esbat = .;
-    . = ALIGN(4096);
-    _epsbat = .;
+   *(.vendor_cert)
   }
-  _sbat_size = _epsbat - _sbat;
-  _sbat_vsize = _esbat - _sbat;
-
   . = ALIGN(4096);
-  .rodata :
-  {
-    _rodata = .;
-    *(.rodata*)
-    *(.srodata)
-    . = ALIGN(16);
-    *(.note.gnu.build-id)
-    . = ALIGN(4096);
-    *(.vendor_cert)
-    *(.data.ident)
-    . = ALIGN(4096);
-  }
+  .dynamic  : { *(.dynamic) }
   . = ALIGN(4096);
   .rela :
   {
-    *(.rela.dyn)
-    *(.rela.plt)
-    *(.rela.got)
-    *(.rela.data)
     *(.rela.data*)
+    *(.rela.got*)
+    *(.rela.stab*)
   }
+  _edata = .;
+  _data_size = . - _data;
   . = ALIGN(4096);
-  .dyn :
+  .sbat :
   {
-    *(.dynsym)
-    *(.dynstr)
-    _evrodata = .;
-    . = ALIGN(4096);
+    _sbat = .;
+    *(.sbat)
+    *(.sbat.*)
   }
-  _erodata = .;
-  _rodata_size = . - _rodata;
-  _rodata_vsize = _evrodata - _rodata;
-  _alldata_size = . - _data;
+  _esbat = .;
+  _sbat_size = . - _sbat;
 
-  /DISCARD/ :
+  . = ALIGN(4096);
+  .dynsym   : { *(.dynsym) }
+  . = ALIGN(4096);
+  .dynstr   : { *(.dynstr) }
+  . = ALIGN(4096);
+  .ignored.reloc :
   {
-    *(.rel.reloc)
+    *(.rela.reloc)
     *(.eh_frame)
     *(.note.GNU-stack)
   }
   .comment 0 : { *(.comment) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
 }
index 8e6327be8bb983574c2b7c5773838adcfc7f2eae..da4b25cce1ae6fbe8dd980de1545c25c96b01eaf 100644 (file)
@@ -24,7 +24,7 @@ get_fallback_verbose(void)
        if (state != -1)
                return state;
 
-       efi_status = get_variable(L"FALLBACK_VERBOSE",
+       efi_status = get_variable(FALLBACK_VERBOSE_VAR_NAME,
                                  &data, &dataSize, SHIM_LOCK_GUID);
        if (EFI_ERROR(efi_status)) {
                state = 0;
@@ -1130,7 +1130,7 @@ debug_hook(void)
        register volatile int x = 0;
        extern char _etext, _edata;
 
-       efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize,
+       efi_status = get_variable(DEBUG_VAR_NAME, &data, &dataSize,
                                  SHIM_LOCK_GUID);
        if (EFI_ERROR(efi_status)) {
                return;
index 4a1f432fd61520d61f33a810a5df6238e7311a41..b4e80dd3a25547fe00d0c117a6116d81cc5a5542 100644 (file)
--- a/globals.c
+++ b/globals.c
@@ -12,6 +12,9 @@ UINT8 *vendor_authorized = NULL;
 UINT32 vendor_deauthorized_size = 0;
 UINT8 *vendor_deauthorized = NULL;
 
+UINT32 user_cert_size;
+UINT8 *user_cert;
+
 #if defined(ENABLE_SHIM_CERT)
 UINT32 build_cert_size;
 UINT8 *build_cert;
@@ -26,6 +29,7 @@ int loader_is_participating;
 UINT8 user_insecure_mode;
 UINT8 ignore_db;
 UINT8 trust_mok_list;
+UINT8 mok_policy = 0;
 
 UINT32 verbose = 0;
 
index 5ce8f7cbf0e9b4d29d4a7c79ff6a1b63b6d15c96..3b56150d85b2127394ad99aaa7e52b9b94260d8b 100755 (executable)
@@ -153,13 +153,11 @@ endif
 # Set HAVE_EFI_OBJCOPY if objcopy understands --target efi-[app|bsdrv|rtdrv],
 # otherwise we need to compose the PE/COFF header using the assembler
 #
-ifneq ($(ARCH),aarch64)
 ifneq ($(ARCH),arm)
 ifneq ($(ARCH),mips64el)
 export HAVE_EFI_OBJCOPY=y
 endif
 endif
-endif
 
 ifeq ($(ARCH),arm)
 CFLAGS += -marm
index a96b5eb8df462b6f3a4c3295169f08a567d9407c..0fefec0caebd832bf04faca4ddf0e5a6d6761d9b 100644 (file)
  * either version 2 of the License, or (at your option) any later version.
  */
 
-       .section        .text.head
-
-       /*
-        * Magic "MZ" signature for PE/COFF
-        */
-       .globl  ImageBase
-ImageBase:
-       .ascii  "MZ"
-       .skip   58                              // 'MZ' + pad + offset == 64
-       .long   pe_header - ImageBase           // Offset to the PE header.
-pe_header:
-       .ascii  "PE"
-       .short  0
-coff_header:
-       .short  0xaa64                          // AArch64
-       .short  4                               // nr_sections
-       .long   0                               // TimeDateStamp
-       .long   0                               // PointerToSymbolTable
-       .long   1                               // NumberOfSymbols
-       .short  section_table - optional_header // SizeOfOptionalHeader
-       .short  0x206                           // Characteristics.
-                                               // IMAGE_FILE_DEBUG_STRIPPED |
-                                               // IMAGE_FILE_EXECUTABLE_IMAGE |
-                                               // IMAGE_FILE_LINE_NUMS_STRIPPED
-optional_header:
-       .short  0x20b                           // PE32+ format
-       .byte   0x02                            // MajorLinkerVersion
-       .byte   0x14                            // MinorLinkerVersion
-       .long   _text_size                      // SizeOfCode
-       .long   _alldata_size                   // SizeOfInitializedData
-       .long   0                               // SizeOfUninitializedData
-       .long   _start - ImageBase              // AddressOfEntryPoint
-       .long   _start - ImageBase              // BaseOfCode
-
-extra_header_fields:
-       .quad   0                               // ImageBase
-       .long   0x1000                          // SectionAlignment
-       .long   0x200                           // FileAlignment
-       .short  0                               // MajorOperatingSystemVersion
-       .short  0                               // MinorOperatingSystemVersion
-       .short  0                               // MajorImageVersion
-       .short  0                               // MinorImageVersion
-       .short  0                               // MajorSubsystemVersion
-       .short  0                               // MinorSubsystemVersion
-       .long   0                               // Win32VersionValue
-
-       .long   _erodata - ImageBase            // SizeOfImage
-
-       // Everything before the kernel image is considered part of the header
-       .long   _start - ImageBase              // SizeOfHeaders
-       .long   0                               // CheckSum
-       .short  EFI_SUBSYSTEM                   // Subsystem
-       .short  0                               // DllCharacteristics
-       .quad   0                               // SizeOfStackReserve
-       .quad   0                               // SizeOfStackCommit
-       .quad   0                               // SizeOfHeapReserve
-       .quad   0                               // SizeOfHeapCommit
-       .long   0                               // LoaderFlags
-       .long   0x6                             // NumberOfRvaAndSizes
-
-       .quad   0                               // ExportTable
-       .quad   0                               // ImportTable
-       .quad   0                               // ResourceTable
-       .quad   0                               // ExceptionTable
-       .quad   0                               // CertificationTable
-       .quad   0                               // BaseRelocationTable
-
-       // Section table
-section_table:
-       .ascii  ".text\0\0\0"
-       .long   _evtext - _start        // VirtualSize
-       .long   _start - ImageBase      // VirtualAddress
-       .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_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
-       .long   _sbat - ImageBase       // VirtualAddress
-       .long   _sbat_size              // SizeOfRawData
-       .long   _sbat - 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)
-
-       .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)
 
+       .text
        .align          12
+
+       .globl _start
 _start:
        stp             x29, x30, [sp, #-32]!
        mov             x29, sp
@@ -164,3 +39,15 @@ _start:
 
 0:     ldp             x29, x30, [sp], #32
        ret
+
+       // hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
+       .data
+.dummy0:
+.dummy1:
+       .4byte  0
+
+#define IMAGE_REL_ABSOLUTE     0
+       .section .reloc, "a"
+       .4byte  .dummy1-.dummy0                         // Page RVA
+       .4byte  10                                      // Block Size (2*4+2)
+       .2byte  (IMAGE_REL_ABSOLUTE<<12) +  0           // reloc for dummy
index 2c567461f4b983faae0c538e67f4efaec18b3a5e..c9b3ea6781266316e410681f02b004744add5816 100644 (file)
@@ -68,10 +68,10 @@ _start:
        .data
 .dummy0:
 .dummy1:
-       .long   0
+       .4byte  0
 
 #define IMAGE_REL_ABSOLUTE     0
        .section .reloc, "a"
-       .long   .dummy1-.dummy0                         // Page RVA
-       .long   10                                      // Block Size (2*4+2)
-       .word   (IMAGE_REL_ABSOLUTE<<12) +  0           // reloc for dummy
+       .4byte  .dummy1-.dummy0                         // Page RVA
+       .4byte  10                                      // Block Size (2*4+2)
+       .2byte  (IMAGE_REL_ABSOLUTE<<12) +  0           // reloc for dummy
index 1a87dbd393b77c7ca3eb8feac033a3a6e0f0ad38..0d99c151ce7c6fa61a09178002a7e8242d56947e 100644 (file)
@@ -59,18 +59,16 @@ _start:
        call efi_main
        addq $8, %rsp
 
-.exit: 
        ret
 
        // hand-craft a dummy .reloc section so EFI knows it's a relocatable executable:
        .data
 .dummy0:
 .dummy1:
-       .long   0
+       .4byte  0
 
 #define IMAGE_REL_ABSOLUTE     0
        .section .reloc, "a"
-       .long   .dummy1-.dummy0                         // Page RVA
-       .long   10                                      // Block Size (2*4+2)
-       .word   (IMAGE_REL_ABSOLUTE<<12) +  0           // reloc for dummy
-
+       .4byte  .dummy1-.dummy0                         // Page RVA
+       .4byte  10                                      // Block Size (2*4+2)
+       .2byte  (IMAGE_REL_ABSOLUTE<<12) +  0           // reloc for dummy
index a552c7d91c38ef31dc85d7eeac2f0058821ad471..841cc9ac63a68ef36f47333d7fd35d373570d676 100644 (file)
@@ -169,12 +169,13 @@ typedef enum {
 #define EFI_MEMORY_WC           0x0000000000000002
 #define EFI_MEMORY_WT           0x0000000000000004
 #define EFI_MEMORY_WB           0x0000000000000008
-#define EFI_MEMORY_UCE          0x0000000000000010  
-
-// physical memory protection on range 
+#define EFI_MEMORY_UCE          0x0000000000000010
 #define EFI_MEMORY_WP           0x0000000000001000
+
+// physical memory protection on range
 #define EFI_MEMORY_RP           0x0000000000002000
 #define EFI_MEMORY_XP           0x0000000000004000
+#define EFI_MEMORY_RO           0x0000000000020000
 
 // range requires a runtime mapping
 #define EFI_MEMORY_RUNTIME      0x8000000000000000
index c83a574fb893cf68e3e815ecc22eedf91c18b74b..4013ab25a82a6c1cef4aa5ca141d145ea6ea1412 100644 (file)
@@ -1422,4 +1422,39 @@ typedef struct _EFI_EBC_PROTOCOL {
   EFI_EBC_GET_VERSION           GetVersion;
 } EFI_EBC_PROTOCOL;
 
+INTERFACE_DECL(_EFI_MEMORY_ATTRIBUTE_PROTOCOL);
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_GET_MEMORY_ATTRIBUTES)(
+  IN struct _EFI_MEMORY_ATTRIBUTE_PROTOCOL      *This,
+  IN EFI_PHYSICAL_ADDRESS                       BaseAddress,
+  IN UINT64                                     Length,
+  OUT UINT64                                    *Attributes
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SET_MEMORY_ATTRIBUTES)(
+  IN struct _EFI_MEMORY_ATTRIBUTE_PROTOCOL      *This,
+  IN EFI_PHYSICAL_ADDRESS                       BaseAddress,
+  IN UINT64                                     Length,
+  IN UINT64                                     Attributes
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_CLEAR_MEMORY_ATTRIBUTES)(
+  IN struct _EFI_MEMORY_ATTRIBUTE_PROTOCOL      *This,
+  IN EFI_PHYSICAL_ADDRESS                       BaseAddress,
+  IN UINT64                                     Length,
+  IN UINT64                                     Attributes
+  );
+
+typedef struct _EFI_MEMORY_ATTRIBUTE_PROTOCOL {
+  EFI_GET_MEMORY_ATTRIBUTES     GetMemoryAttributes;
+  EFI_SET_MEMORY_ATTRIBUTES     SetMemoryAttributes;
+  EFI_CLEAR_MEMORY_ATTRIBUTES   ClearMemoryAttributes;
+} EFI_MEMORY_ATTRIBUTE_PROTOCOL;
+
 #endif
index 18576724d30aa133246a0c57080497e6b1c8a440..b4bf10319eefba80fb3a9b77ee771f9d7e11d1ec 100644 (file)
 #define ALIAS(x) __attribute__((weak, alias (#x)))
 #endif
 #ifndef ALLOCFUNC
+#if defined(__COVERITY__)
+#define ALLOCFUNC(a, b)
+#else
 #define ALLOCFUNC(dealloc, dealloc_arg) __attribute__((__malloc__(dealloc, dealloc_arg)))
 #endif
+#endif
 #ifndef PRINTF
 #define PRINTF(first, args...) __attribute__((__format__(printf, first, ## args)))
 #endif
index 07a19a915ee24d1acc78a8601b126e2ab0e067f6..d9910ff1abc77100ed017e20a0ffb88e5086252f 100644 (file)
@@ -33,8 +33,8 @@ extern EFI_GUID EFI_SECURE_BOOT_DB_GUID;
 extern EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID;
 extern EFI_GUID SECURITY_PROTOCOL_GUID;
 extern EFI_GUID SECURITY2_PROTOCOL_GUID;
+extern EFI_GUID EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
 extern EFI_GUID SHIM_LOCK_GUID;
-
 extern EFI_GUID MOK_VARIABLE_STORE;
 
 #endif /* SHIM_GUID_H */
index 96da397a70f6ae0e0498573cf65b7f366488ad0a..fb19423b6352bfc32858fd2859b7dee386a82488 100644 (file)
@@ -59,6 +59,9 @@ struct mok_state_variable {
        UINT8 **addend;
        UINT32 *addend_size;
 
+       UINT8 **user_cert;
+       UINT32 *user_cert_size;
+
        /*
         * build_cert is our build-time cert.  Like addend, this is added
         * to the input variable, as part of the runtime variable, so that
@@ -97,5 +100,10 @@ struct mok_variable_config_entry {
        UINT8 data[];
 };
 
+/*
+ * bit definitions for MokPolicy
+ */
+#define MOK_POLICY_REQUIRE_NX  1
+
 #endif /* !SHIM_MOK_H_ */
 // vim:fenc=utf-8:tw=75:noet
index 43727f5e933821fc22ab7a938598ff7d0c62bb8c..ccc8798b2e9dcc79ebe25c651648c2e1e132091c 100644 (file)
@@ -14,8 +14,12 @@ EFI_STATUS
 read_header(void *data, unsigned int datasize,
            PE_COFF_LOADER_IMAGE_CONTEXT *context);
 
+EFI_STATUS verify_image(void *data, unsigned int datasize,
+                       EFI_LOADED_IMAGE *li,
+                       PE_COFF_LOADER_IMAGE_CONTEXT *context);
+
 EFI_STATUS
-handle_sbat(char *SBATBase, size_t SBATSize);
+verify_sbat_section(char *SBATBase, size_t SBATSize);
 
 EFI_STATUS
 handle_image (void *data, unsigned int datasize,
index 3b3f01a79af8106368d693ce9862421f0d569055..e97b29c4d84c0b6b6969786e39338ed79fb959b9 100644 (file)
 \r
 #include "wincert.h"\r
 \r
-#define SIGNATURE_16(A, B)        ((A) | (B << 8))\r
-#define SIGNATURE_32(A, B, C, D)  (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))\r
-#define SIGNATURE_64(A, B, C, D, E, F, G, H) \\r
-       (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32))\r
+#define SIGNATURE_16(A, B) \\r
+       ((UINT16)(((UINT16)(A)) | (((UINT16)(B)) << ((UINT16)8))))\r
+#define SIGNATURE_32(A, B, C, D)                 \\r
+       ((UINT32)(((UINT32)SIGNATURE_16(A, B)) | \\r
+                 (((UINT32)SIGNATURE_16(C, D)) << (UINT32)16)))\r
+#define SIGNATURE_64(A, B, C, D, E, F, G, H)         \\r
+       ((UINT64)((UINT64)SIGNATURE_32(A, B, C, D) | \\r
+                 ((UINT64)(SIGNATURE_32(E, F, G, H)) << (UINT64)32)))\r
 \r
 #define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1)))\r
 #define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment))))\r
@@ -236,6 +240,24 @@ typedef struct {
   EFI_IMAGE_DATA_DIRECTORY  DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];\r
 } EFI_IMAGE_OPTIONAL_HEADER64;\r
 \r
+#define EFI_IMAGE_DLLCHARACTERISTICS_RESERVED_0001         0x0001\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_RESERVED_0002         0x0002\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_RESERVED_0004         0x0004\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_RESERVED_0008         0x0008\r
+#if 0 /* This is not in the PE spec. */\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_RESERVED_0010         0x0010\r
+#endif\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA       0x0020\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE          0x0040\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY       0x0080\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_NX_COMPAT             0x0100\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_NO_ISOLATION          0x0200\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_NO_SEH                0x0400\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_NO_BIND               0x0800\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_APPCONTAINER          0x1000\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_WDM_DRIVER            0x2000\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_GUARD_CF              0x4000\r
+#define EFI_IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000\r
 \r
 ///\r
 /// @attention\r
@@ -303,16 +325,31 @@ typedef struct {
 //\r
 // Section Flags Values\r
 //\r
-#define EFI_IMAGE_SCN_TYPE_NO_PAD                  0x00000008  ///< Reserved.\r
+#define EFI_IMAGE_SCN_RESERVED_00000000            0x00000000\r
+#define EFI_IMAGE_SCN_RESERVED_00000001            0x00000001\r
+#define EFI_IMAGE_SCN_RESERVED_00000002            0x00000002\r
+#define EFI_IMAGE_SCN_RESERVED_00000004            0x00000004\r
+#define EFI_IMAGE_SCN_TYPE_NO_PAD                  0x00000008\r
+#define EFI_IMAGE_SCN_RESERVED_00000010            0x00000010\r
 #define EFI_IMAGE_SCN_CNT_CODE                     0x00000020\r
 #define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA         0x00000040\r
 #define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA       0x00000080\r
-\r
-#define EFI_IMAGE_SCN_LNK_OTHER                    0x00000100  ///< Reserved.\r
-#define EFI_IMAGE_SCN_LNK_INFO                     0x00000200  ///< Section contains comments or some other type of information.\r
-#define EFI_IMAGE_SCN_LNK_REMOVE                   0x00000800  ///< Section contents will not become part of image.\r
+#define EFI_IMAGE_SCN_LNK_OTHER                    0x00000100\r
+#define EFI_IMAGE_SCN_LNK_INFO                     0x00000200\r
+#define EFI_IMAGE_SCN_RESERVED_00000400            0x00000400\r
+#define EFI_IMAGE_SCN_LNK_REMOVE                   0x00000800\r
 #define EFI_IMAGE_SCN_LNK_COMDAT                   0x00001000\r
-\r
+#define EFI_IMAGE_SCN_RESERVED_00002000            0x00002000\r
+#define EFI_IMAGE_SCN_RESERVED_00004000            0x00004000\r
+#define EFI_IMAGE_SCN_GPREL                        0x00008000\r
+/*\r
+ * PE 9.3 says both IMAGE_SCN_MEM_PURGEABLE and IMAGE_SCN_MEM_16BIT are\r
+ * 0x00020000, but I think it's wrong. --pjones\r
+ */\r
+#define EFI_IMAGE_SCN_MEM_PURGEABLE                0x00010000 // "Reserved for future use."\r
+#define EFI_IMAGE_SCN_MEM_16BIT                    0x00020000 // "Reserved for future use."\r
+#define EFI_IMAGE_SCN_MEM_LOCKED                   0x00040000 // "Reserved for future use."\r
+#define EFI_IMAGE_SCN_MEM_PRELOAD                  0x00080000 // "Reserved for future use."\r
 #define EFI_IMAGE_SCN_ALIGN_1BYTES                 0x00100000\r
 #define EFI_IMAGE_SCN_ALIGN_2BYTES                 0x00200000\r
 #define EFI_IMAGE_SCN_ALIGN_4BYTES                 0x00300000\r
@@ -320,7 +357,14 @@ typedef struct {
 #define EFI_IMAGE_SCN_ALIGN_16BYTES                0x00500000\r
 #define EFI_IMAGE_SCN_ALIGN_32BYTES                0x00600000\r
 #define EFI_IMAGE_SCN_ALIGN_64BYTES                0x00700000\r
-\r
+#define EFI_IMAGE_SCN_ALIGN_128BYTES               0x00800000\r
+#define EFI_IMAGE_SCN_ALIGN_256BYTES               0x00900000\r
+#define EFI_IMAGE_SCN_ALIGN_512BYTES               0x00a00000\r
+#define EFI_IMAGE_SCN_ALIGN_1024BYTES              0x00b00000\r
+#define EFI_IMAGE_SCN_ALIGN_2048BYTES              0x00c00000\r
+#define EFI_IMAGE_SCN_ALIGN_4096BYTES              0x00d00000\r
+#define EFI_IMAGE_SCN_ALIGN_8192BYTES              0x00e00000\r
+#define EFI_IMAGE_SCN_LNK_NRELOC_OVFL              0x01000000\r
 #define EFI_IMAGE_SCN_MEM_DISCARDABLE              0x02000000\r
 #define EFI_IMAGE_SCN_MEM_NOT_CACHED               0x04000000\r
 #define EFI_IMAGE_SCN_MEM_NOT_PAGED                0x08000000\r
index 8551b74a273dc7d77a82c6732512c9ef7bc22ac3..aca4359870f9b7ab4ba755a866c781ea4587e1ff 100644 (file)
@@ -8,8 +8,35 @@
 
 #define SBAT_VAR_SIG "sbat,"
 #define SBAT_VAR_VERSION "1,"
-#define SBAT_VAR_DATE "2021030218"
-#define SBAT_VAR SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_DATE "\n"
+#define SBAT_VAR_ORIGINAL_DATE "2021030218"
+#define SBAT_VAR_ORIGINAL \
+       SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_ORIGINAL_DATE "\n"
+
+#if defined(ENABLE_SHIM_DEVEL)
+#define SBAT_VAR_PREVIOUS_DATE "2022020101"
+#define SBAT_VAR_PREVIOUS_REVOCATIONS "component,2\n"
+#define SBAT_VAR_PREVIOUS \
+       SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_PREVIOUS_DATE "\n" \
+       SBAT_VAR_PREVIOUS_REVOCATIONS
+
+#define SBAT_VAR_LATEST_DATE "2022050100"
+#define SBAT_VAR_LATEST_REVOCATIONS "component,2\nothercomponent,2\n"
+#define SBAT_VAR_LATEST \
+       SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_LATEST_DATE "\n" \
+       SBAT_VAR_LATEST_REVOCATIONS
+#else /* !ENABLE_SHIM_DEVEL */
+#define SBAT_VAR_PREVIOUS_DATE SBAT_VAR_ORIGINAL_DATE
+#define SBAT_VAR_PREVIOUS_REVOCATIONS
+#define SBAT_VAR_PREVIOUS \
+       SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_PREVIOUS_DATE "\n" \
+       SBAT_VAR_PREVIOUS_REVOCATIONS
+
+#define SBAT_VAR_LATEST_DATE "2022052400"
+#define SBAT_VAR_LATEST_REVOCATIONS "shim,2\ngrub,2\n"
+#define SBAT_VAR_LATEST \
+       SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_LATEST_DATE "\n" \
+       SBAT_VAR_LATEST_REVOCATIONS
+#endif /* ENABLE_SHIM_DEVEL */
 
 #define UEFI_VAR_NV_BS \
        (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
 #define SBAT_VAR_ATTRS UEFI_VAR_NV_BS
 #endif
 
+#define SBAT_POLICY L"SbatPolicy"
+#define SBAT_POLICY8 "SbatPolicy"
+
+#define SBAT_POLICY_LATEST     1
+#define SBAT_POLICY_PREVIOUS   2
+#define SBAT_POLICY_RESET      3
+
 extern UINTN _sbat, _esbat;
 
 struct sbat_var_entry {
@@ -51,7 +85,8 @@ 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);
+bool preserve_sbat_uefi_variable(UINT8 *sbat, UINTN sbatsize,
+                                UINT32 attributes, char *sbar_var);
 
 struct sbat_section_entry {
        const CHAR8 *component_name;
index 55090edec3b23977b467d34ef12edf55fa69871e..2831bd231dde0688831e18bbe94386f7fe6850e7 100644 (file)
@@ -102,5 +102,9 @@ static const unsigned char test_data_efivars_1_SbatLevelRT[] = {
        0x32, 0x31, 0x30, 0x33, 0x30, 0x32, 0x31, 0x38, 0x0a
 };
 
+static const unsigned char test_data_efivars_1_MokListTrustedRT[] ={
+       0x01
+};
+
 #endif /* !TEST_DATA_EFIVARS_1_H_ */
 // vim:fenc=utf-8:tw=75:noet
index 1a4fc2204c2629ecf39cd95459460495bf23c4fc..e965c6000a5be161f76a80377f90e617999282bb 100644 (file)
@@ -50,6 +50,9 @@ CFLAGS = $(OPTIMIZATIONS) -std=gnu11 \
 # of the "include" directory
 CFLAGS += -isystem $(shell $(CC) $(ARCH_CFLAGS) -print-file-name=include-fixed)
 
+# And on Debian also check the multi-arch include path
+CFLAGS += -isystem /usr/include/$(shell $(CC) $(ARCH_CFLAGS) -print-multiarch)
+
 export CFLAGS_LTO CFLAGS_GCOV
 
 libefi-test.a :
index a4a4855bce9b1c6619c68cbe21f1e0dc25370a26..f81c5c9bd305b3974604ea81d0b84691f800ba95 100644 (file)
@@ -41,6 +41,10 @@ CFLAGS               = $(FEATUREFLAGS) \
                  $(INCLUDES) \
                  $(DEFINES)
 
+ifneq ($(origin ENABLE_SHIM_DEVEL),undefined)
+CFLAGS += -DENABLE_SHIM_DEVEL
+endif
+
 lib.a: $(LIBFILES)
        $(AR) rcs lib.a $(LIBFILES)
 
index 7be5d5437f5bfe3110520b547d9519c217b0b788..6bbb8a7ce28d9b4d96a8e38b455fbc71811fecb7 100644 (file)
@@ -122,6 +122,30 @@ console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...)
        return ret;
 }
 
+static struct {
+       CHAR16 up_left;
+       CHAR16 up_right;
+       CHAR16 down_left;
+       CHAR16 down_right;
+       CHAR16 horizontal;
+       CHAR16 vertical;
+} boxdraw[2] = {
+       {
+               BOXDRAW_UP_LEFT,
+               BOXDRAW_UP_RIGHT,
+               BOXDRAW_DOWN_LEFT,
+               BOXDRAW_DOWN_RIGHT,
+               BOXDRAW_HORIZONTAL,
+               BOXDRAW_VERTICAL
+       }, {
+               '+',
+               '+',
+               '+',
+               '+',
+               '-',
+               '|'
+       }
+};
 
 void
 console_print_box_at(CHAR16 *str_arr[], int highlight,
@@ -133,6 +157,7 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
        SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
        UINTN rows, cols;
        CHAR16 *Line;
+       bool char_set;
 
        if (lines == 0)
                return;
@@ -181,10 +206,16 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
                return;
        }
 
-       SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL);
+       /* test if boxdraw characters work */
+       co->SetCursorPosition(co, start_col, start_row);
+       Line[0] = boxdraw[0].up_left;
+       Line[1] = L'\0';
+       char_set = co->OutputString(co, Line) == 0 ? 0 : 1;
+
+       SetMem16 (Line, size_cols * 2, boxdraw[char_set].horizontal);
 
-       Line[0] = BOXDRAW_DOWN_RIGHT;
-       Line[size_cols - 1] = BOXDRAW_DOWN_LEFT;
+       Line[0] = boxdraw[char_set].down_right;
+       Line[size_cols - 1] = boxdraw[char_set].down_left;
        Line[size_cols] = L'\0';
        co->SetCursorPosition(co, start_col, start_row);
        co->OutputString(co, Line);
@@ -204,8 +235,8 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
                int line = i - start;
 
                SetMem16 (Line, size_cols*2, L' ');
-               Line[0] = BOXDRAW_VERTICAL;
-               Line[size_cols - 1] = BOXDRAW_VERTICAL;
+               Line[0] = boxdraw[char_set].vertical;
+               Line[size_cols - 1] = boxdraw[char_set].vertical;
                Line[size_cols] = L'\0';
                if (line >= 0 && line < lines) {
                        CHAR16 *s = str_arr[line];
@@ -227,9 +258,9 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
                                               EFI_BACKGROUND_BLUE);
 
        }
-       SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL);
-       Line[0] = BOXDRAW_UP_RIGHT;
-       Line[size_cols - 1] = BOXDRAW_UP_LEFT;
+       SetMem16 (Line, size_cols * 2, boxdraw[char_set].horizontal);
+       Line[0] = boxdraw[char_set].up_right;
+       Line[size_cols - 1] = boxdraw[char_set].up_left;
        Line[size_cols] = L'\0';
        co->SetCursorPosition(co, start_col, i);
        co->OutputString(co, Line);
@@ -522,7 +553,6 @@ console_mode_handle(VOID)
 
        efi_status = BS->LocateProtocol(&gop_guid, NULL, (void **)&gop);
        if (EFI_ERROR(efi_status)) {
-               console_error(L"Locate graphic output protocol fail", efi_status);
                return;
        }
 
@@ -702,7 +732,7 @@ setup_verbosity(VOID)
        UINTN verbose_check_size;
 
        verbose_check_size = sizeof(verbose);
-       efi_status = get_variable(L"SHIM_VERBOSE", &verbose_check_ptr,
+       efi_status = get_variable(VERBOSE_VAR_NAME, &verbose_check_ptr,
                                  &verbose_check_size, SHIM_LOCK_GUID);
        if (!EFI_ERROR(efi_status)) {
                verbose = *(__typeof__(verbose) *)verbose_check_ptr;
index 143e0bbd3eb2a3f2cf8be25b4cce23c90d3c64b8..e100c92ed1bd4d2c80f4e730e4192eeb6bf4a301 100644 (file)
@@ -32,6 +32,6 @@ EFI_GUID EFI_SECURE_BOOT_DB_GUID =  { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc,
 EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID = SIMPLE_FILE_SYSTEM_PROTOCOL;
 EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } };
 EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
-
+EFI_GUID EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID = { 0xf4560cf6, 0x40ec, 0x4b4a, {0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89} };
 EFI_GUID SHIM_LOCK_GUID = {0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } };
 EFI_GUID MOK_VARIABLE_STORE = {0xc451ed2b, 0x9694, 0x45d3, {0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89} };
index e9bce544a8461703f2f8d53b3c32294c3e870f15..030445499ee251e501faf70e9e6dcf023cd25421 100644 (file)
@@ -445,7 +445,7 @@ free_var(struct mock_variable *var)
 static bool
 mock_sv_attrs_match(UINT32 old, UINT32 new)
 {
-       UINT32 mask = ~EFI_VARIABLE_APPEND_WRITE;
+       UINT32 mask = ~((UINT32)EFI_VARIABLE_APPEND_WRITE);
 
        return (old & mask) == (new & mask);
 }
diff --git a/mok.c b/mok.c
index 289628535974628875ea94ea04eed98fc35606e4..63ddfcaaea3cfa7606a805bda0d86ec95b594e9b 100644 (file)
--- a/mok.c
+++ b/mok.c
@@ -84,6 +84,7 @@ categorize_deauthorized(struct mok_state_variable *v)
 #define MOK_MIRROR_DELETE_FIRST        0x02
 #define MOK_VARIABLE_MEASURE   0x04
 #define MOK_VARIABLE_LOG       0x08
+#define MOK_VARIABLE_INVERSE   0x10
 
 struct mok_state_variable mok_state_variable_data[] = {
        {.name = L"MokList",
@@ -97,6 +98,8 @@ struct mok_state_variable mok_state_variable_data[] = {
         .categorize_addend = categorize_authorized,
         .addend = &vendor_authorized,
         .addend_size = &vendor_authorized_size,
+        .user_cert = &user_cert,
+        .user_cert_size = &user_cert_size,
 #if defined(ENABLE_SHIM_CERT)
         .build_cert = &build_cert,
         .build_cert_size = &build_cert_size,
@@ -176,10 +179,24 @@ struct mok_state_variable mok_state_variable_data[] = {
         .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
         .flags = MOK_MIRROR_DELETE_FIRST |
                  MOK_VARIABLE_MEASURE |
+                 MOK_VARIABLE_INVERSE |
                  MOK_VARIABLE_LOG,
         .pcr = 14,
         .state = &trust_mok_list,
        },
+       {.name = L"MokPolicy",
+        .name8 = "MokPolicy",
+        .rtname = L"MokPolicyRT",
+        .rtname8 = "MokPolicyRT",
+        .guid = &SHIM_LOCK_GUID,
+        .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                    EFI_VARIABLE_NON_VOLATILE,
+        .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
+        .flags = MOK_MIRROR_DELETE_FIRST |
+                 MOK_VARIABLE_LOG,
+        .pcr = 14,
+        .state = &mok_policy,
+       },
        { NULL, }
 };
 size_t n_mok_state_variables = sizeof(mok_state_variable_data) / sizeof(mok_state_variable_data[0]);
@@ -586,7 +603,8 @@ mirror_one_mok_variable(struct mok_state_variable *v,
                        dprint(L"FullDataSize:0x%lx FullData:0x%llx\n",
                               FullDataSize, FullData);
                }
-
+               if (v->user_cert_size)
+                       FullDataSize += *v->user_cert_size;
        }
 
        /*
@@ -700,6 +718,10 @@ mirror_one_mok_variable(struct mok_state_variable *v,
                        dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
                               FullDataSize, FullData, p, p-(uintptr_t)FullData);
                }
+               if (v->user_cert_size) {
+                       CopyMem(p, *v->user_cert, *v->user_cert_size);
+                       p += *v->user_cert_size;
+               }
        }
 
        /*
@@ -846,7 +868,16 @@ EFI_STATUS import_one_mok_state(struct mok_state_variable *v,
                efi_status = get_variable_attr(v->name,
                                               &v->data, &v->data_size,
                                               *v->guid, &attrs);
-               if (efi_status == EFI_NOT_FOUND) {
+               if (efi_status == EFI_NOT_FOUND &&
+                   v->flags & MOK_VARIABLE_INVERSE) {
+                       v->data = AllocateZeroPool(4);
+                       if (!v->data) {
+                               perror(L"Out of memory\n");
+                               return EFI_OUT_OF_RESOURCES;
+                       }
+                       v->data[0] = 0x01;
+                       v->data_size = 1;
+               } else if (efi_status == EFI_NOT_FOUND) {
                        v->data = NULL;
                        v->data_size = 0;
                } else if (EFI_ERROR(efi_status)) {
@@ -868,6 +899,11 @@ EFI_STATUS import_one_mok_state(struct mok_state_variable *v,
                                       attrs, v->no_attr);
                                delete = TRUE;
                        }
+                       if (v->flags & MOK_VARIABLE_INVERSE) {
+                               FreePool(v->data);
+                               v->data = NULL;
+                               v->data_size = 0;
+                       }
                }
        }
        if (delete == TRUE) {
diff --git a/pe.c b/pe.c
index 92c2804b42dd621384266543644e29f4f503c3b8..ba3e2bbc444e3457366988ebffe8782c05ab9f0e 100644 (file)
--- a/pe.c
+++ b/pe.c
@@ -696,6 +696,7 @@ read_header(void *data, unsigned int datasize,
        EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
        unsigned long HeaderWithoutDataDir, SectionHeaderOffset, OptHeaderSize;
        unsigned long FileAlignment = 0;
+       UINT16 DllFlags;
 
        if (datasize < sizeof (PEHdr->Pe32)) {
                perror(L"Invalid image\n");
@@ -790,13 +791,21 @@ read_header(void *data, unsigned int datasize,
                context->EntryPoint = PEHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint;
                context->RelocDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
                context->SecDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+               DllFlags = PEHdr->Pe32Plus.OptionalHeader.DllCharacteristics;
        } else {
                context->ImageAddress = PEHdr->Pe32.OptionalHeader.ImageBase;
                context->EntryPoint = PEHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
                context->RelocDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
                context->SecDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+               DllFlags = PEHdr->Pe32.OptionalHeader.DllCharacteristics;
        }
 
+       if ((mok_policy & MOK_POLICY_REQUIRE_NX) &&
+           !(DllFlags & EFI_IMAGE_DLLCHARACTERISTICS_NX_COMPAT)) {
+               perror(L"Policy requires NX, but image does not support NX\n");
+               return EFI_UNSUPPORTED;
+        }
+
        context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
 
        if (context->ImageSize < context->SizeOfHeaders) {
@@ -820,7 +829,7 @@ read_header(void *data, unsigned int datasize,
 }
 
 EFI_STATUS
-handle_sbat(char *SBATBase, size_t SBATSize)
+verify_sbat_section(char *SBATBase, size_t SBATSize)
 {
        unsigned int i;
        EFI_STATUS efi_status;
@@ -834,7 +843,12 @@ handle_sbat(char *SBATBase, size_t SBATSize)
 
        if (SBATBase == NULL || SBATSize == 0) {
                dprint(L"No .sbat section data\n");
-               return EFI_SECURITY_VIOLATION;
+               /*
+                * SBAT is mandatory for binaries loaded by shim, but optional
+                * for binaries loaded outside of shim but verified via the
+                * protocol.
+                */
+               return in_protocol ? EFI_SUCCESS : EFI_SECURITY_VIOLATION;
        }
 
        sbat_size = SBATSize + 1;
@@ -873,6 +887,201 @@ err:
        return efi_status;
 }
 
+static inline uint64_t
+shim_mem_attrs_to_uefi_mem_attrs (uint64_t attrs)
+{
+       uint64_t ret = EFI_MEMORY_RP |
+                      EFI_MEMORY_RO |
+                      EFI_MEMORY_XP;
+
+       if (attrs & MEM_ATTR_R)
+               ret &= ~EFI_MEMORY_RP;
+
+       if (attrs & MEM_ATTR_W)
+               ret &= ~EFI_MEMORY_RO;
+
+       if (attrs & MEM_ATTR_X)
+               ret &= ~EFI_MEMORY_XP;
+
+       return ret;
+}
+
+static inline uint64_t
+uefi_mem_attrs_to_shim_mem_attrs (uint64_t attrs)
+{
+       uint64_t ret = MEM_ATTR_R |
+                      MEM_ATTR_W |
+                      MEM_ATTR_X;
+
+       if (attrs & EFI_MEMORY_RP)
+               ret &= ~MEM_ATTR_R;
+
+       if (attrs & EFI_MEMORY_RO)
+               ret &= ~MEM_ATTR_W;
+
+       if (attrs & EFI_MEMORY_XP)
+               ret &= ~MEM_ATTR_X;
+
+       return ret;
+}
+
+static EFI_STATUS
+get_mem_attrs (uintptr_t addr, size_t size, uint64_t *attrs)
+{
+       EFI_MEMORY_ATTRIBUTE_PROTOCOL *proto = NULL;
+       EFI_PHYSICAL_ADDRESS physaddr = addr;
+       EFI_STATUS efi_status;
+
+       efi_status = LibLocateProtocol(&EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID,
+                                      (VOID **)&proto);
+       if (EFI_ERROR(efi_status) || !proto)
+               return efi_status;
+
+       if (physaddr & 0xfff || size & 0xfff || size == 0 || attrs == NULL) {
+               dprint(L"%a called on 0x%llx-0x%llx and attrs 0x%llx\n",
+                      __func__, (unsigned long long)physaddr,
+                      (unsigned long long)(physaddr+size-1),
+                      attrs);
+               return EFI_SUCCESS;
+       }
+
+       efi_status = proto->GetMemoryAttributes(proto, physaddr, size, attrs);
+       *attrs = uefi_mem_attrs_to_shim_mem_attrs (*attrs);
+
+       return efi_status;
+}
+
+static EFI_STATUS
+update_mem_attrs(uintptr_t addr, uint64_t size,
+                uint64_t set_attrs, uint64_t clear_attrs)
+{
+       EFI_MEMORY_ATTRIBUTE_PROTOCOL *proto = NULL;
+       EFI_PHYSICAL_ADDRESS physaddr = addr;
+       EFI_STATUS efi_status, ret;
+       uint64_t before = 0, after = 0, uefi_set_attrs, uefi_clear_attrs;
+
+       efi_status = LibLocateProtocol(&EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID,
+                                      (VOID **)&proto);
+       if (EFI_ERROR(efi_status) || !proto)
+               return efi_status;
+
+       efi_status = get_mem_attrs (addr, size, &before);
+       if (EFI_ERROR(efi_status))
+               dprint(L"get_mem_attrs(0x%llx, 0x%llx, 0x%llx) -> 0x%lx\n",
+                      (unsigned long long)addr, (unsigned long long)size,
+                      &before, efi_status);
+
+       if (physaddr & 0xfff || size & 0xfff || size == 0) {
+               dprint(L"%a called on 0x%llx-0x%llx (size 0x%llx) +%a%a%a -%a%a%a\n",
+                      __func__, (unsigned long long)physaddr,
+                      (unsigned long long)(physaddr + size - 1),
+                      (unsigned long long)size,
+                      (set_attrs & MEM_ATTR_R) ? "r" : "",
+                      (set_attrs & MEM_ATTR_W) ? "w" : "",
+                      (set_attrs & MEM_ATTR_X) ? "x" : "",
+                      (clear_attrs & MEM_ATTR_R) ? "r" : "",
+                      (clear_attrs & MEM_ATTR_W) ? "w" : "",
+                      (clear_attrs & MEM_ATTR_X) ? "x" : "");
+               return 0;
+       }
+
+       uefi_set_attrs = shim_mem_attrs_to_uefi_mem_attrs (set_attrs);
+       dprint("translating set_attrs from 0x%lx to 0x%lx\n", set_attrs, uefi_set_attrs);
+       uefi_clear_attrs = shim_mem_attrs_to_uefi_mem_attrs (clear_attrs);
+       dprint("translating clear_attrs from 0x%lx to 0x%lx\n", clear_attrs, uefi_clear_attrs);
+       efi_status = EFI_SUCCESS;
+       if (uefi_set_attrs)
+               efi_status = proto->SetMemoryAttributes(proto, physaddr, size, uefi_set_attrs);
+       if (!EFI_ERROR(efi_status) && uefi_clear_attrs)
+               efi_status = proto->ClearMemoryAttributes(proto, physaddr, size, uefi_clear_attrs);
+       ret = efi_status;
+
+       efi_status = get_mem_attrs (addr, size, &after);
+       if (EFI_ERROR(efi_status))
+               dprint(L"get_mem_attrs(0x%llx, %llu, 0x%llx) -> 0x%lx\n",
+                      (unsigned long long)addr, (unsigned long long)size,
+                      &after, efi_status);
+
+       dprint(L"set +%a%a%a -%a%a%a on 0x%llx-0x%llx before:%c%c%c after:%c%c%c\n",
+              (set_attrs & MEM_ATTR_R) ? "r" : "",
+              (set_attrs & MEM_ATTR_W) ? "w" : "",
+              (set_attrs & MEM_ATTR_X) ? "x" : "",
+              (clear_attrs & MEM_ATTR_R) ? "r" : "",
+              (clear_attrs & MEM_ATTR_W) ? "w" : "",
+              (clear_attrs & MEM_ATTR_X) ? "x" : "",
+              (unsigned long long)addr, (unsigned long long)(addr + size - 1),
+              (before & MEM_ATTR_R) ? 'r' : '-',
+              (before & MEM_ATTR_W) ? 'w' : '-',
+              (before & MEM_ATTR_X) ? 'x' : '-',
+              (after & MEM_ATTR_R) ? 'r' : '-',
+              (after & MEM_ATTR_W) ? 'w' : '-',
+              (after & MEM_ATTR_X) ? 'x' : '-');
+
+       return ret;
+}
+
+EFI_STATUS verify_image(void *data, unsigned int datasize,
+                       EFI_LOADED_IMAGE *li,
+                       PE_COFF_LOADER_IMAGE_CONTEXT *context)
+{
+       EFI_STATUS efi_status;
+       UINT8 sha1hash[SHA1_DIGEST_SIZE];
+       UINT8 sha256hash[SHA256_DIGEST_SIZE];
+
+       /*
+        * The binary header contains relevant context and section pointers
+        */
+       efi_status = read_header(data, datasize, context);
+       if (EFI_ERROR(efi_status)) {
+               perror(L"Failed to read header: %r\n", efi_status);
+               return efi_status;
+       }
+
+       /*
+        * Perform the image verification before we start copying data around
+        * in order to load it.
+        */
+       if (secure_mode()) {
+               efi_status = verify_buffer(data, datasize,
+                                          context, sha256hash, sha1hash);
+               if (EFI_ERROR(efi_status)) {
+                       if (verbose)
+                               console_print(L"Verification failed: %r\n", efi_status);
+                       else
+                               console_error(L"Verification failed", efi_status);
+                       return efi_status;
+               } else if (verbose)
+                       console_print(L"Verification succeeded\n");
+       }
+
+       /*
+        * Calculate the hash for the TPM measurement.
+        * XXX: We're computing these twice in secure boot mode when the
+        *  buffers already contain the previously computed hashes. Also,
+        *  this is only useful for the TPM1.2 case. We should try to fix
+        *  this in a follow-up.
+        */
+       efi_status = generate_hash(data, datasize, context, sha256hash,
+                                  sha1hash);
+       if (EFI_ERROR(efi_status))
+               return efi_status;
+
+       /* Measure the binary into the TPM */
+#ifdef REQUIRE_TPM
+       efi_status =
+#endif
+       tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize,
+                  (EFI_PHYSICAL_ADDRESS)(UINTN)context->ImageAddress,
+                  li->FilePath, sha1hash, 4);
+#ifdef REQUIRE_TPM
+       if (efi_status != EFI_SUCCESS) {
+               return efi_status;
+       }
+#endif
+
+       return EFI_SUCCESS;
+}
+
 /*
  * Once the image has been loaded it needs to be validated and relocated
  */
@@ -888,6 +1097,7 @@ handle_image (void *data, unsigned int datasize,
        int i;
        EFI_IMAGE_SECTION_HEADER *Section;
        char *base, *end;
+       UINT32 size;
        PE_COFF_LOADER_IMAGE_CONTEXT context;
        unsigned int alignment, alloc_size;
        int found_entry_point = 0;
@@ -904,7 +1114,31 @@ handle_image (void *data, unsigned int datasize,
        }
 
        /*
-        * We only need to verify the binary if we're in secure mode
+        * Perform the image verification before we start copying data around
+        * in order to load it.
+        */
+       if (secure_mode ()) {
+               efi_status = verify_buffer(data, datasize, &context, sha256hash,
+                                          sha1hash);
+
+               if (EFI_ERROR(efi_status)) {
+                       if (verbose)
+                               console_print(L"Verification failed: %r\n", efi_status);
+                       else
+                               console_error(L"Verification failed", efi_status);
+                       return efi_status;
+               } else {
+                       if (verbose)
+                               console_print(L"Verification succeeded\n");
+               }
+       }
+
+       /*
+        * Calculate the hash for the TPM measurement.
+        * XXX: We're computing these twice in secure boot mode when the
+        *  buffers already contain the previously computed hashes. Also,
+        *  this is only useful for the TPM1.2 case. We should try to fix
+        *  this in a follow-up.
         */
        efi_status = generate_hash(data, datasize, &context, sha256hash,
                                   sha1hash);
@@ -954,6 +1188,11 @@ handle_image (void *data, unsigned int datasize,
        }
 
        buffer = (void *)ALIGN_VALUE((unsigned long)*alloc_address, alignment);
+       dprint(L"Loading 0x%llx bytes at 0x%llx\n",
+              (unsigned long long)context.ImageSize,
+              (unsigned long long)(uintptr_t)buffer);
+       update_mem_attrs((uintptr_t)buffer, alloc_size, MEM_ATTR_R|MEM_ATTR_W,
+                        MEM_ATTR_X);
 
        CopyMem(buffer, data, context.SizeOfHeaders);
 
@@ -980,9 +1219,6 @@ handle_image (void *data, unsigned int datasize,
 
        EFI_IMAGE_SECTION_HEADER *RelocSection = NULL;
 
-       char *SBATBase = NULL;
-       size_t SBATSize = 0;
-
        /*
         * Copy the executable's sections to their desired offsets
         */
@@ -993,6 +1229,20 @@ handle_image (void *data, unsigned int datasize,
                    !Section->Misc.VirtualSize)
                        continue;
 
+               /*
+                * Skip sections that aren't marked readable.
+                */
+               if (!(Section->Characteristics & EFI_IMAGE_SCN_MEM_READ))
+                       continue;
+
+               if (!(Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) &&
+                   (Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) &&
+                   (Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) &&
+                   (mok_policy & MOK_POLICY_REQUIRE_NX)) {
+                       perror(L"Section %d is writable and executable\n", i);
+                       return EFI_UNSUPPORTED;
+               }
+
                base = ImageAddress (buffer, context.ImageSize,
                                     Section->VirtualAddress);
                end = ImageAddress (buffer, context.ImageSize,
@@ -1027,33 +1277,6 @@ handle_image (void *data, unsigned int datasize,
                                        RelocBaseEnd == end) {
                                RelocSection = Section;
                        }
-               } else if (CompareMem(Section->Name, ".sbat\0\0\0", 8) == 0) {
-                       if (SBATBase || SBATSize) {
-                               perror(L"Image has multiple SBAT sections\n");
-                               return EFI_UNSUPPORTED;
-                       }
-
-                       if (Section->NumberOfRelocations != 0 ||
-                           Section->PointerToRelocations != 0) {
-                               perror(L"SBAT section has relocations\n");
-                               return EFI_UNSUPPORTED;
-                       }
-
-                       /* The virtual size corresponds to the size of the SBAT
-                        * metadata and isn't necessarily a multiple of the file
-                        * alignment. The on-disk size is a multiple of the file
-                        * alignment and is zero padded. Make sure that the
-                        * on-disk size is at least as large as virtual size,
-                        * and ignore the section if it isn't. */
-                       if (Section->SizeOfRawData &&
-                           Section->SizeOfRawData >= Section->Misc.VirtualSize &&
-                           base && end) {
-                               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);
-                       }
                }
 
                if (Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) {
@@ -1084,32 +1307,15 @@ handle_image (void *data, unsigned int datasize,
                                return EFI_UNSUPPORTED;
                        }
 
-                       if (Section->SizeOfRawData > 0)
-                               CopyMem(base, data + Section->PointerToRawData,
-                                       Section->SizeOfRawData);
-
-                       if (Section->SizeOfRawData < Section->Misc.VirtualSize)
-                               ZeroMem(base + Section->SizeOfRawData,
-                                       Section->Misc.VirtualSize - Section->SizeOfRawData);
-               }
-       }
-
-       if (secure_mode ()) {
-               efi_status = handle_sbat(SBATBase, SBATSize);
+                       size = Section->Misc.VirtualSize;
+                       if (size > Section->SizeOfRawData)
+                               size = Section->SizeOfRawData;
 
-               if (!EFI_ERROR(efi_status))
-                       efi_status = verify_buffer(data, datasize,
-                                                  &context, sha256hash, sha1hash);
+                       if (size > 0)
+                               CopyMem(base, data + Section->PointerToRawData, size);
 
-               if (EFI_ERROR(efi_status)) {
-                       if (verbose)
-                               console_print(L"Verification failed: %r\n", efi_status);
-                       else
-                               console_error(L"Verification failed", efi_status);
-                       return efi_status;
-               } else {
-                       if (verbose)
-                               console_print(L"Verification succeeded\n");
+                       if (size < Section->Misc.VirtualSize)
+                               ZeroMem(base + size, Section->Misc.VirtualSize - size);
                }
        }
 
@@ -1133,6 +1339,50 @@ handle_image (void *data, unsigned int datasize,
                }
        }
 
+       /*
+        * Now set the page permissions appropriately.
+        */
+       Section = context.FirstSection;
+       for (i = 0; i < context.NumberOfSections; i++, Section++) {
+               uint64_t set_attrs = MEM_ATTR_R;
+               uint64_t clear_attrs = MEM_ATTR_W|MEM_ATTR_X;
+               uintptr_t addr;
+               uint64_t length;
+
+               /*
+                * Skip discardable sections with zero size
+                */
+               if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE) &&
+                   !Section->Misc.VirtualSize)
+                       continue;
+
+               /*
+                * Skip sections that aren't marked readable.
+                */
+               if (!(Section->Characteristics & EFI_IMAGE_SCN_MEM_READ))
+                       continue;
+
+               base = ImageAddress (buffer, context.ImageSize,
+                                    Section->VirtualAddress);
+               end = ImageAddress (buffer, context.ImageSize,
+                                   Section->VirtualAddress
+                                    + Section->Misc.VirtualSize - 1);
+
+               addr = (uintptr_t)base;
+               length = (uintptr_t)end - (uintptr_t)base + 1;
+
+               if (Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) {
+                       set_attrs |= MEM_ATTR_W;
+                       clear_attrs &= ~MEM_ATTR_W;
+               }
+               if (Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) {
+                       set_attrs |= MEM_ATTR_X;
+                       clear_attrs &= ~MEM_ATTR_X;
+               }
+               update_mem_attrs(addr, length, set_attrs, clear_attrs);
+       }
+
+
        /*
         * grub needs to know its location and size in memory, so fix up
         * the loaded image protocol values
index 8414a5faca5990a2f029caf3b9a182bbdda1c988..de8f4a38baa8ef565be4900a282bd0af40ae2ed1 100644 (file)
@@ -11,6 +11,7 @@
 #include <getopt.h>
 #include <inttypes.h>
 #include <limits.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -41,6 +42,8 @@ static int verbosity;
                0;                                               \
        })
 
+static bool set_nx_compat = false;
+
 typedef uint8_t UINT8;
 typedef uint16_t UINT16;
 typedef uint32_t UINT32;
@@ -174,7 +177,7 @@ load_pe(const char *const file, void *const data, const size_t datasize,
        }
 
        if (FileAlignment % 2 != 0)
-               errx(1, "%s: Invalid file alignment %ld", file, FileAlignment);
+               errx(1, "%s: Invalid file alignment %zu", file, FileAlignment);
 
        if (FileAlignment == 0)
                FileAlignment = 0x200;
@@ -190,7 +193,7 @@ load_pe(const char *const file, void *const data, const size_t datasize,
              ctx->NumberOfRvaAndSizes, EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES);
        if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < ctx->NumberOfRvaAndSizes)
                errx(1, "%s: invalid number of RVAs (%lu entries, max is %d)",
-                    file, ctx->NumberOfRvaAndSizes,
+                    file, (unsigned long)ctx->NumberOfRvaAndSizes,
                     EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES);
 
        if (mul(sizeof(EFI_IMAGE_DATA_DIRECTORY),
@@ -233,12 +236,12 @@ load_pe(const char *const file, void *const data, const size_t datasize,
                if (mul(ctx->NumberOfRvaAndSizes,
                        sizeof(EFI_IMAGE_DATA_DIRECTORY), &sz1))
                        debug(ERROR,
-                             "ctx->NumberOfRvaAndSizes (%zu) * sizeof(EFI_IMAGE_DATA_DIRECTORY) overflows\n",
-                             ctx->NumberOfRvaAndSizes);
+                             "ctx->NumberOfRvaAndSizes (%ld) * sizeof(EFI_IMAGE_DATA_DIRECTORY) overflows\n",
+                             (unsigned long)ctx->NumberOfRvaAndSizes);
                else
                        debug(ERROR,
-                             "ctx->NumberOfRvaAndSizes (%zu) * sizeof(EFI_IMAGE_DATA_DIRECTORY) = %zu\n",
-                             ctx->NumberOfRvaAndSizes, sz1);
+                             "ctx->NumberOfRvaAndSizes (%ld) * sizeof(EFI_IMAGE_DATA_DIRECTORY) = %zu\n",
+                             (unsigned long)ctx->NumberOfRvaAndSizes, sz1);
                debug(ERROR,
                      "space after image header:%zu data directory size:%zu\n",
                      sz0, sz1);
@@ -271,7 +274,7 @@ load_pe(const char *const file, void *const data, const size_t datasize,
        if (sub(ctx->SizeOfHeaders, SectionHeaderOffset, &sz0) ||
            div(sz0, EFI_IMAGE_SIZEOF_SECTION_HEADER, &sz0) ||
            (sz0 < ctx->NumberOfSections)) {
-               debug(ERROR, "(%zu - %zu) / %d >= %d\n", ctx->SizeOfHeaders,
+               debug(ERROR, "(%zu - %zu) / %d >= %d\n", (size_t)ctx->SizeOfHeaders,
                      SectionHeaderOffset, EFI_IMAGE_SIZEOF_SECTION_HEADER,
                      ctx->NumberOfSections);
                errx(1, "%s: image sections overflow section headers", file);
@@ -330,6 +333,33 @@ load_pe(const char *const file, void *const data, const size_t datasize,
                errx(1, "%s: Security directory extends past end", file);
 }
 
+static void
+set_dll_characteristics(PE_COFF_LOADER_IMAGE_CONTEXT *ctx)
+{
+       uint16_t oldflags, newflags;
+
+       if (image_is_64_bit(ctx->PEHdr)) {
+               oldflags = ctx->PEHdr->Pe32Plus.OptionalHeader.DllCharacteristics;
+       } else {
+               oldflags = ctx->PEHdr->Pe32.OptionalHeader.DllCharacteristics;
+       }
+
+       if (set_nx_compat)
+               newflags = oldflags | EFI_IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
+       else
+               newflags = oldflags & ~(uint16_t)EFI_IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
+       if (oldflags == newflags)
+               return;
+
+       debug(INFO, "Updating DLL Characteristics from 0x%04hx to 0x%04hx\n",
+             oldflags, newflags);
+       if (image_is_64_bit(ctx->PEHdr)) {
+               ctx->PEHdr->Pe32Plus.OptionalHeader.DllCharacteristics = newflags;
+       } else {
+               ctx->PEHdr->Pe32.OptionalHeader.DllCharacteristics = newflags;
+       }
+}
+
 static void
 fix_timestamp(PE_COFF_LOADER_IMAGE_CONTEXT *ctx)
 {
@@ -417,6 +447,8 @@ handle_one(char *f)
 
        load_pe(f, map, sz, &ctx);
 
+       set_dll_characteristics(&ctx);
+
        fix_timestamp(&ctx);
 
        fix_checksum(&ctx, map, sz);
@@ -426,7 +458,7 @@ handle_one(char *f)
                warn("msync(%p, %zu, MS_SYNC) failed", map, sz);
                failed = 1;
        }
-       munmap(map, sz);
+       rc = munmap(map, sz);
        if (rc < 0) {
                warn("munmap(%p, %zu) failed", map, sz);
                failed = 1;
@@ -449,6 +481,8 @@ static void __attribute__((__noreturn__)) usage(int status)
        fprintf(out, "Options:\n");
        fprintf(out, "       -q    Be more quiet\n");
        fprintf(out, "       -v    Be more verbose\n");
+       fprintf(out, "       -N    Disable the NX compatibility flag\n");
+       fprintf(out, "       -n    Enable the NX compatibility flag\n");
        fprintf(out, "       -h    Print this help text and exit\n");
 
        exit(status);
@@ -464,6 +498,12 @@ int main(int argc, char **argv)
                {.name = "usage",
                 .val = '?',
                 },
+               {.name = "disable-nx-compat",
+                .val = 'N',
+               },
+               {.name = "enable-nx-compat",
+                .val = 'n',
+               },
                {.name = "quiet",
                 .val = 'q',
                },
@@ -474,12 +514,18 @@ int main(int argc, char **argv)
        };
        int longindex = -1;
 
-       while ((i = getopt_long(argc, argv, "hqsv", options, &longindex)) != -1) {
+       while ((i = getopt_long(argc, argv, "hNnqv", options, &longindex)) != -1) {
                switch (i) {
                case 'h':
                case '?':
                        usage(longindex == -1 ? 1 : 0);
                        break;
+               case 'N':
+                       set_nx_compat = false;
+                       break;
+               case 'n':
+                       set_nx_compat = true;
+                       break;
                case 'q':
                        verbosity = MAX(verbosity - 1, MIN_VERBOSITY);
                        break;
diff --git a/sbat.c b/sbat.c
index 6b7eb20a8b6e699ac7082945337af0e7fc4596f4..f1d6e98dcdef400495b3e230d4813e68432e34e1 100644 (file)
--- a/sbat.c
+++ b/sbat.c
@@ -113,13 +113,14 @@ cleanup_sbat_section_entries(size_t n, struct sbat_section_entry **entries)
 }
 
 EFI_STATUS
-verify_single_entry(struct sbat_section_entry *entry, struct sbat_var_entry *sbat_var_entry)
+verify_single_entry(struct sbat_section_entry *entry, struct sbat_var_entry *sbat_var_entry, bool *found)
 {
        UINT16 sbat_gen, sbat_var_gen;
 
        if (strcmp((const char *)entry->component_name, (const char *)sbat_var_entry->component_name) == 0) {
                dprint(L"component %a has a matching SBAT variable entry, verifying\n",
                        entry->component_name);
+               *found = true;
 
                /*
                 * atoi returns zero for failed conversion, so essentially
@@ -172,10 +173,13 @@ verify_sbat_helper(list_t *local_sbat_var, size_t n, struct sbat_section_entry *
 
        for (i = 0; i < n; i++) {
                list_for_each(pos, local_sbat_var) {
+                       bool found = false;
                        sbat_var_entry = list_entry(pos, struct sbat_var_entry, list);
-                       efi_status = verify_single_entry(entries[i], sbat_var_entry);
+                       efi_status = verify_single_entry(entries[i], sbat_var_entry, &found);
                        if (EFI_ERROR(efi_status))
                                goto out;
+                       if (found)
+                               break;
                }
        }
 
@@ -285,6 +289,7 @@ parse_sbat_var(list_t *entries)
        UINT8 *data = 0;
        UINTN datasize;
        EFI_STATUS efi_status;
+       list_t *pos = NULL;
 
        if (!entries) {
                dprint(L"entries is NULL\n");
@@ -301,7 +306,20 @@ parse_sbat_var(list_t *entries)
         * We've intentionally made sure there's a NUL byte on all variable
         * allocations, so use that here.
         */
-       return parse_sbat_var_data(entries, data, datasize+1);
+       efi_status = parse_sbat_var_data(entries, data, datasize+1);
+       if (EFI_ERROR(efi_status))
+               return efi_status;
+
+       dprint(L"SBAT variable entries:\n");
+       list_for_each(pos, entries) {
+               struct sbat_var_entry *entry;
+
+               entry = list_entry(pos, struct sbat_var_entry, list);
+               dprint(L"%a, %a, %a\n", entry->component_name,
+                      entry->component_generation, entry->sbat_datestamp);
+       }
+
+       return efi_status;
 }
 
 static bool
@@ -315,12 +333,64 @@ check_sbat_var_attributes(UINT32 attributes)
 #endif
 }
 
+static char *
+nth_sbat_field(char *str, size_t limit, int n)
+{
+       size_t i;
+       for (i = 0; i < limit && str[i] != '\0'; i++) {
+               if (n == 0)
+                       return &str[i];
+               if (str[i] == ',')
+                       n--;
+       }
+       return &str[i];
+}
+
 bool
-preserve_sbat_uefi_variable(UINT8 *sbat, UINTN sbatsize, UINT32 attributes)
+preserve_sbat_uefi_variable(UINT8 *sbat, UINTN sbatsize, UINT32 attributes,
+               char *sbat_var)
 {
-       return check_sbat_var_attributes(attributes) &&
-              sbatsize >= strlen(SBAT_VAR_SIG "1") &&
-              !strncmp((const char *)sbat, SBAT_VAR_SIG, strlen(SBAT_VAR_SIG));
+       char *sbatc = (char *)sbat;
+       char *current_version, *new_version,
+            *current_datestamp, *new_datestamp;
+       int current_version_len, new_version_len;
+
+       /* current metadata is not currupt somehow */
+       if (!check_sbat_var_attributes(attributes) ||
+               sbatsize < strlen(SBAT_VAR_ORIGINAL) ||
+              strncmp(sbatc, SBAT_VAR_SIG, strlen(SBAT_VAR_SIG)))
+               return false;
+
+       /* current metadata version not newer */
+       current_version = nth_sbat_field(sbatc, sbatsize, 1);
+       new_version = nth_sbat_field(sbat_var, strlen(sbat_var)+1, 1);
+       current_datestamp = nth_sbat_field(sbatc, sbatsize, 2);
+       new_datestamp = nth_sbat_field(sbat_var, strlen(sbat_var)+1, 2);
+
+       current_version_len = current_datestamp - current_version - 1;
+       new_version_len = new_datestamp - new_version - 1;
+
+       if (current_version_len > new_version_len ||
+           (current_version_len == new_version_len &&
+           strncmp(current_version, new_version, new_version_len) > 0))
+               return true;
+
+       /* current datestamp is not newer or idential */
+       if (strncmp(current_datestamp, new_datestamp,
+           strlen(SBAT_VAR_ORIGINAL_DATE)) >= 0)
+                return true;
+
+       return false;
+}
+
+static void
+clear_sbat_policy()
+{
+       EFI_STATUS efi_status = EFI_SUCCESS;
+
+       efi_status = del_variable(SBAT_POLICY, SHIM_LOCK_GUID);
+       if (EFI_ERROR(efi_status))
+               console_error(L"Could not reset SBAT Policy", efi_status);
 }
 
 EFI_STATUS
@@ -330,7 +400,49 @@ set_sbat_uefi_variable(void)
        UINT32 attributes = 0;
 
        UINT8 *sbat = NULL;
+       UINT8 *sbat_policy = NULL;
        UINTN sbatsize = 0;
+       UINTN sbat_policysize = 0;
+
+       char *sbat_var = NULL;
+       bool reset_sbat = false;
+
+       efi_status = get_variable_attr(SBAT_POLICY, &sbat_policy,
+                                      &sbat_policysize, SHIM_LOCK_GUID,
+                                      &attributes);
+       if (EFI_ERROR(efi_status)) {
+               dprint("Default sbat policy: previous\n");
+               sbat_var = SBAT_VAR_PREVIOUS;
+       } else {
+               switch (*sbat_policy) {
+                       case SBAT_POLICY_LATEST:
+                               dprint("Custom sbat policy: latest\n");
+                               sbat_var = SBAT_VAR_LATEST;
+                               clear_sbat_policy();
+                               break;
+                       case SBAT_POLICY_PREVIOUS:
+                               dprint("Custom sbat policy: previous\n");
+                               sbat_var = SBAT_VAR_PREVIOUS;
+                               break;
+                       case SBAT_POLICY_RESET:
+                               if (secure_mode()) {
+                                       console_print(L"Cannot reset SBAT policy: Secure Boot is enabled.\n");
+                                       sbat_var = SBAT_VAR_PREVIOUS;
+                               } else {
+                                       dprint(L"Custom SBAT policy: reset OK\n");
+                                       reset_sbat = true;
+                                       sbat_var = SBAT_VAR_ORIGINAL;
+                               }
+                               clear_sbat_policy();
+                               break;
+                       default:
+                               console_error(L"SBAT policy state %llu is invalid",
+                                             EFI_INVALID_PARAMETER);
+                               sbat_var = SBAT_VAR_PREVIOUS;
+                               clear_sbat_policy();
+                               break;
+               }
+       }
 
        efi_status = get_variable_attr(SBAT_VAR_NAME, &sbat, &sbatsize,
                                       SHIM_LOCK_GUID, &attributes);
@@ -342,8 +454,9 @@ set_sbat_uefi_variable(void)
         */
        if (EFI_ERROR(efi_status)) {
                dprint(L"SBAT read failed %r\n", efi_status);
-       } else if (preserve_sbat_uefi_variable(sbat, sbatsize, attributes)) {
-               dprint(L"%s variable is %d bytes, attributes are 0x%08x\n",
+       } else if (preserve_sbat_uefi_variable(sbat, sbatsize, attributes, sbat_var)
+                  && !reset_sbat) {
+               dprint(L"preserving %s variable it is %d bytes, attributes are 0x%08x\n",
                       SBAT_VAR_NAME, sbatsize, attributes);
                FreePool(sbat);
                return EFI_SUCCESS;
@@ -365,7 +478,7 @@ set_sbat_uefi_variable(void)
 
        /* set variable */
        efi_status = set_variable(SBAT_VAR_NAME, SHIM_LOCK_GUID, SBAT_VAR_ATTRS,
-                                 sizeof(SBAT_VAR)-1, SBAT_VAR);
+                                 strlen(sbat_var), sbat_var);
        if (EFI_ERROR(efi_status)) {
                dprint(L"%s variable writing failed %r\n", SBAT_VAR_NAME,
                                efi_status);
@@ -380,10 +493,10 @@ set_sbat_uefi_variable(void)
                return efi_status;
        }
 
-       if (sbatsize != strlen(SBAT_VAR) ||
-           strncmp((const char *)sbat, SBAT_VAR, strlen(SBAT_VAR)) != 0) {
+       if (sbatsize != strlen(sbat_var) ||
+           strncmp((const char *)sbat, sbat_var, strlen(sbat_var)) != 0) {
                dprint("new sbatsize is %d, expected %d\n", sbatsize,
-                      strlen(SBAT_VAR));
+                      strlen(sbat_var));
                efi_status = EFI_INVALID_PARAMETER;
        } else {
                dprint(L"%s variable initialization succeeded\n", SBAT_VAR_NAME);
diff --git a/shim.c b/shim.c
index 604c0db150035d718634b9a16de41b017473615a..fdd205ef995f28278e49da0819be7bb15f152f7b 100644 (file)
--- a/shim.c
+++ b/shim.c
@@ -559,9 +559,9 @@ verify_one_signature(WIN_CERTIFICATE_EFI_PKCS *sig,
  * Check that the signature is valid and matches the binary
  */
 EFI_STATUS
-verify_buffer (char *data, int datasize,
-              PE_COFF_LOADER_IMAGE_CONTEXT *context,
-              UINT8 *sha256hash, UINT8 *sha1hash)
+verify_buffer_authenticode (char *data, int datasize,
+                           PE_COFF_LOADER_IMAGE_CONTEXT *context,
+                           UINT8 *sha256hash, UINT8 *sha1hash)
 {
        EFI_STATUS ret_efi_status;
        size_t size = datasize;
@@ -695,6 +695,71 @@ verify_buffer (char *data, int datasize,
        return ret_efi_status;
 }
 
+/*
+ * Check that the binary is permitted to load by SBAT.
+ */
+EFI_STATUS
+verify_buffer_sbat (char *data, int datasize,
+                   PE_COFF_LOADER_IMAGE_CONTEXT *context)
+{
+       int i;
+       EFI_IMAGE_SECTION_HEADER *Section;
+       char *SBATBase = NULL;
+       size_t SBATSize = 0;
+
+       Section = context->FirstSection;
+       for (i = 0; i < context->NumberOfSections; i++, Section++) {
+               if (CompareMem(Section->Name, ".sbat\0\0\0", 8) != 0)
+                       continue;
+
+               if (SBATBase || SBATSize) {
+                       perror(L"Image has multiple SBAT sections\n");
+                       return EFI_UNSUPPORTED;
+               }
+
+               if (Section->NumberOfRelocations != 0 ||
+                   Section->PointerToRelocations != 0) {
+                       perror(L"SBAT section has relocations\n");
+                       return EFI_UNSUPPORTED;
+               }
+
+               /* The virtual size corresponds to the size of the SBAT
+                * metadata and isn't necessarily a multiple of the file
+                * alignment. The on-disk size is a multiple of the file
+                * alignment and is zero padded. Make sure that the
+                * on-disk size is at least as large as virtual size,
+                * and ignore the section if it isn't. */
+               if (Section->SizeOfRawData &&
+                   Section->SizeOfRawData >= Section->Misc.VirtualSize) {
+                       SBATBase = ImageAddress(data, datasize,
+                                               Section->PointerToRawData);
+                       SBATSize = Section->SizeOfRawData;
+                       dprint(L"sbat section base:0x%lx size:0x%lx\n",
+                              SBATBase, SBATSize);
+               }
+       }
+
+       return verify_sbat_section(SBATBase, SBATSize);
+}
+
+/*
+ * Check that the signature is valid and matches the binary and that
+ * the binary is permitted to load by SBAT.
+ */
+EFI_STATUS
+verify_buffer (char *data, int datasize,
+              PE_COFF_LOADER_IMAGE_CONTEXT *context,
+              UINT8 *sha256hash, UINT8 *sha1hash)
+{
+       EFI_STATUS efi_status;
+
+       efi_status = verify_buffer_sbat(data, datasize, context);
+       if (EFI_ERROR(efi_status))
+               return efi_status;
+
+       return verify_buffer_authenticode(data, datasize, context, sha256hash, sha1hash);
+}
+
 static int
 is_removable_media_path(EFI_LOADED_IMAGE *li)
 {
@@ -988,17 +1053,12 @@ restore_loaded_image(VOID)
 /*
  * Load and run an EFI executable
  */
-EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
+EFI_STATUS read_image(EFI_HANDLE image_handle, CHAR16 *ImagePath,
+                     CHAR16 **PathName, void **data, int *datasize)
 {
        EFI_STATUS efi_status;
-       EFI_IMAGE_ENTRY_POINT entry_point;
-       EFI_PHYSICAL_ADDRESS alloc_address;
-       UINTN alloc_pages;
-       CHAR16 *PathName = NULL;
        void *sourcebuffer = NULL;
        UINT64 sourcesize = 0;
-       void *data = NULL;
-       int datasize = 0;
 
        /*
         * We need to refer to the loaded image protocol on the running
@@ -1014,11 +1074,11 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
        /*
         * Build a new path from the existing one plus the executable name
         */
-       efi_status = generate_path_from_image_path(shim_li, ImagePath, &PathName);
+       efi_status = generate_path_from_image_path(shim_li, ImagePath, PathName);
        if (EFI_ERROR(efi_status)) {
                perror(L"Unable to generate path %s: %r\n", ImagePath,
                       efi_status);
-               goto done;
+               return efi_status;
        }
 
        if (findNetboot(shim_li->DeviceHandle)) {
@@ -1034,8 +1094,8 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
                               efi_status);
                        return efi_status;
                }
-               data = sourcebuffer;
-               datasize = sourcesize;
+               *data = sourcebuffer;
+               *datasize = sourcesize;
        } else if (find_httpboot(shim_li->DeviceHandle)) {
                efi_status = httpboot_fetch_buffer (image_handle,
                                                    &sourcebuffer,
@@ -1045,26 +1105,45 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
                               efi_status);
                        return efi_status;
                }
-               data = sourcebuffer;
-               datasize = sourcesize;
+               *data = sourcebuffer;
+               *datasize = sourcesize;
        } else {
                /*
                 * Read the new executable off disk
                 */
-               efi_status = load_image(shim_li, &data, &datasize, PathName);
+               efi_status = load_image(shim_li, data, datasize, *PathName);
                if (EFI_ERROR(efi_status)) {
                        perror(L"Failed to load image %s: %r\n",
                               PathName, efi_status);
                        PrintErrors();
                        ClearErrors();
-                       goto done;
+                       return efi_status;
                }
        }
 
-       if (datasize < 0) {
+       if (*datasize < 0)
                efi_status = EFI_INVALID_PARAMETER;
+
+       return efi_status;
+}
+
+/*
+ * Load and run an EFI executable
+ */
+EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
+{
+       EFI_STATUS efi_status;
+       EFI_IMAGE_ENTRY_POINT entry_point;
+       EFI_PHYSICAL_ADDRESS alloc_address;
+       UINTN alloc_pages;
+       CHAR16 *PathName = NULL;
+       void *data = NULL;
+       int datasize = 0;
+
+       efi_status = read_image(image_handle, ImagePath, &PathName, &data,
+                               &datasize);
+       if (EFI_ERROR(efi_status))
                goto done;
-       }
 
        /*
         * We need to modify the loaded image protocol entry before running
@@ -1312,6 +1391,127 @@ uninstall_shim_protocols(void)
 #endif
 }
 
+EFI_STATUS
+load_cert_file(EFI_HANDLE image_handle, CHAR16 *filename, CHAR16 *PathName)
+{
+       EFI_STATUS efi_status;
+       EFI_LOADED_IMAGE li;
+       PE_COFF_LOADER_IMAGE_CONTEXT context;
+       EFI_IMAGE_SECTION_HEADER *Section;
+       EFI_SIGNATURE_LIST *certlist;
+       void *pointer;
+       UINT32 original;
+       int datasize = 0;
+       void *data = NULL;
+       int i;
+
+       efi_status = read_image(image_handle, filename, &PathName,
+                               &data, &datasize);
+       if (EFI_ERROR(efi_status))
+               return efi_status;
+
+       memset(&li, 0, sizeof(li));
+       memcpy(&li.FilePath[0], filename, MIN(StrSize(filename), sizeof(li.FilePath)));
+
+       efi_status = verify_image(data, datasize, &li, &context);
+       if (EFI_ERROR(efi_status))
+               return efi_status;
+
+       Section = context.FirstSection;
+       for (i = 0; i < context.NumberOfSections; i++, Section++) {
+               if (CompareMem(Section->Name, ".db\0\0\0\0\0", 8) == 0) {
+                       original = user_cert_size;
+                       if (Section->SizeOfRawData < sizeof(EFI_SIGNATURE_LIST)) {
+                               continue;
+                       }
+                       pointer = ImageAddress(data, datasize,
+                                              Section->PointerToRawData);
+                       if (!pointer) {
+                               continue;
+                       }
+                       certlist = pointer;
+                       user_cert_size += certlist->SignatureListSize;;
+                       user_cert = ReallocatePool(user_cert, original,
+                                                  user_cert_size);
+                       memcpy(user_cert + original, pointer,
+                              certlist->SignatureListSize);
+               }
+       }
+       FreePool(data);
+       return EFI_SUCCESS;
+}
+
+/* Read additional certificates from files (after verifying signatures) */
+EFI_STATUS
+load_certs(EFI_HANDLE image_handle)
+{
+       EFI_STATUS efi_status;
+       EFI_LOADED_IMAGE *li = NULL;
+       CHAR16 *PathName = NULL;
+       EFI_FILE *root, *dir;
+       EFI_FILE_INFO *info;
+       EFI_HANDLE device;
+       EFI_FILE_IO_INTERFACE *drive;
+       UINTN buffersize = 0;
+       void *buffer = NULL;
+
+       efi_status = gBS->HandleProtocol(image_handle, &EFI_LOADED_IMAGE_GUID,
+                                        (void **)&li);
+       if (EFI_ERROR(efi_status)) {
+               perror(L"Unable to init protocol\n");
+               return efi_status;
+       }
+
+       efi_status = generate_path_from_image_path(li, L"", &PathName);
+       if (EFI_ERROR(efi_status))
+               goto done;
+
+       device = li->DeviceHandle;
+       efi_status = gBS->HandleProtocol(device, &EFI_SIMPLE_FILE_SYSTEM_GUID,
+                                        (void **)&drive);
+       if (EFI_ERROR(efi_status)) {
+               perror(L"Failed to find fs: %r\n", efi_status);
+               goto done;
+       }
+
+       efi_status = drive->OpenVolume(drive, &root);
+       if (EFI_ERROR(efi_status)) {
+               perror(L"Failed to open fs: %r\n", efi_status);
+               goto done;
+       }
+
+       efi_status = root->Open(root, &dir, PathName, EFI_FILE_MODE_READ, 0);
+       if (EFI_ERROR(efi_status)) {
+               perror(L"Failed to open %s - %r\n", PathName, efi_status);
+               goto done;
+       }
+
+       while (1) {
+               int old = buffersize;
+               efi_status = dir->Read(dir, &buffersize, buffer);
+               if (efi_status == EFI_BUFFER_TOO_SMALL) {
+                       buffer = ReallocatePool(buffer, old, buffersize);
+                       continue;
+               } else if (EFI_ERROR(efi_status)) {
+                       perror(L"Failed to read directory %s - %r\n", PathName,
+                              efi_status);
+                       goto done;
+               }
+
+               info = (EFI_FILE_INFO *)buffer;
+               if (buffersize == 0 || !info)
+                       goto done;
+
+               if (StrnCaseCmp(info->FileName, L"shim_certificate", 16) == 0) {
+                       load_cert_file(image_handle, info->FileName, PathName);
+               }
+       }
+done:
+       FreePool(buffer);
+       FreePool(PathName);
+       return efi_status;
+}
+
 EFI_STATUS
 shim_init(void)
 {
@@ -1385,17 +1585,10 @@ debug_hook(void)
        register volatile UINTN x = 0;
        extern char _text, _data;
 
-       const CHAR16 * const debug_var_name =
-#ifdef ENABLE_SHIM_DEVEL
-               L"SHIM_DEVEL_DEBUG";
-#else
-               L"SHIM_DEBUG";
-#endif
-
        if (x)
                return;
 
-       efi_status = get_variable(debug_var_name, &data, &dataSize,
+       efi_status = get_variable(DEBUG_VAR_NAME, &data, &dataSize,
                                  SHIM_LOCK_GUID);
        if (EFI_ERROR(efi_status)) {
                return;
@@ -1409,7 +1602,7 @@ debug_hook(void)
 
        console_print(L"Pausing for debugger attachment.\n");
        console_print(L"To disable this, remove the EFI variable %s-%g .\n",
-                     debug_var_name, &SHIM_LOCK_GUID);
+                     DEBUG_VAR_NAME, &SHIM_LOCK_GUID);
        x = 1;
        while (x++) {
                /* Make this so it can't /totally/ DoS us. */
@@ -1542,7 +1735,7 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
                        goto die;
                }
 
-               efi_status = handle_sbat(sbat_start, sbat_end - sbat_start - 1);
+               efi_status = verify_sbat_section(sbat_start, sbat_end - sbat_start - 1);
                if (EFI_ERROR(efi_status)) {
                        perror(L"Verifiying shim SBAT data failed: %r\n",
                               efi_status);
@@ -1554,6 +1747,13 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
 
        init_openssl();
 
+       if (secure_mode()) {
+               efi_status = load_certs(global_image_handle);
+               if (EFI_ERROR(efi_status)) {
+                       LogError(L"Failed to load addon certificates\n");
+               }
+       }
+
        /*
         * Before we do anything else, validate our non-volatile,
         * boot-services-only state variables are what we think they are.
diff --git a/shim.h b/shim.h
index 69442da3fdd8ddc801280231c0513be26cb51c12..b5272b9c9e92aa5a03e7a86e22794a605fe6d7d1 100644 (file)
--- a/shim.h
+++ b/shim.h
 #include "Cryptlib/Include/OpenSslSupport.h"
 #endif
 
+#define MEM_ATTR_R     4
+#define MEM_ATTR_W     2
+#define MEM_ATTR_X     1
+
 INTERFACE_DECL(_SHIM_LOCK);
 
 typedef
@@ -248,6 +252,9 @@ extern UINT8 *vendor_authorized;
 extern UINT32 vendor_deauthorized_size;
 extern UINT8 *vendor_deauthorized;
 
+extern UINT32 user_cert_size;
+extern UINT8 *user_cert;
+
 #if defined(ENABLE_SHIM_CERT)
 extern UINT32 build_cert_size;
 extern UINT8 *build_cert;
@@ -256,6 +263,8 @@ extern UINT8 *build_cert;
 extern UINT8 user_insecure_mode;
 extern UINT8 ignore_db;
 extern UINT8 trust_mok_list;
+extern UINT8 mok_policy;
+
 extern UINT8 in_protocol;
 extern void *load_options;
 extern UINT32 load_options_size;
@@ -284,6 +293,16 @@ verify_buffer (char *data, int datasize,
 #define LogError(fmt, ...)
 #endif
 
+#ifdef ENABLE_SHIM_DEVEL
+#define FALLBACK_VERBOSE_VAR_NAME L"FALLBACK_DEVEL_VERBOSE"
+#define VERBOSE_VAR_NAME L"SHIM_DEVEL_VERBOSE"
+#define DEBUG_VAR_NAME L"SHIM_DEVEL_DEBUG"
+#else
+#define FALLBACK_VERBOSE_VAR_NAME L"FALLBACK_VERBOSE"
+#define VERBOSE_VAR_NAME L"SHIM_VERBOSE"
+#define DEBUG_VAR_NAME L"SHIM_DEBUG"
+#endif
+
 char *translate_slashes(char *out, const char *str);
 
 #endif /* SHIM_H_ */
index 3479ddf82bdbf0cfeb11691ad3db6aeab50de0a3..f34f62a972f083e0630511f9b77d5d55a54a928d 100644 (file)
@@ -184,6 +184,10 @@ test_mok_mirror_0(void)
                 .data_size = sizeof(test_data_efivars_1_SbatLevelRT),
                 .data = test_data_efivars_1_SbatLevelRT
                },
+               {.name = "MokListTrustedRT",
+                .data_size = sizeof(test_data_efivars_1_MokListTrustedRT),
+                .data = test_data_efivars_1_MokListTrustedRT
+               },
                {.name = { 0, },
                 .data_size = 0,
                 .data = NULL,
index b64aa1e90452c8aae2b1231a40516ba6979aac64..72bebe7ae631770a34628c114040e69d2267eb96 100644 (file)
 
 list_t sbat_var;
 
+BOOLEAN
+secure_mode() {
+       return 1;
+}
+
 #if 0
 /*
  * Mock test helpers
@@ -965,11 +970,96 @@ err:
 int
 test_preserve_sbat_uefi_variable_good(void)
 {
-       char sbat[] = "sbat,1,\ncomponent,2,\n";
+       char sbat[] =    "sbat,1,2021030218\ncomponent,2,\n";
+       char sbatvar[] = "sbat,1,2021030218\ncomponent,2,\n";
+       size_t sbat_size = sizeof(sbat);
+       UINT32 attributes = SBAT_VAR_ATTRS;
+
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
+               return 0;
+       else
+               return -1;
+}
+
+int
+test_preserve_sbat_uefi_variable_version_newer(void)
+{
+       char sbat[] =    "sbat,2,2022030218\ncomponent,2,\n";
+       char sbatvar[] = "sbat,1,2021030218\ncomponent,2,\n";
+       size_t sbat_size = sizeof(sbat);
+       UINT32 attributes = SBAT_VAR_ATTRS;
+
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
+               return 0;
+       else
+               return -1;
+}
+
+int
+test_preserve_sbat_uefi_variable_version_newerlonger(void)
+{
+       char sbat[] =    "sbat,10,2022030218\ncomponent,2,\n";
+       char sbatvar[] = "sbat,2,2021030218\ncomponent,2,\n";
+       size_t sbat_size = sizeof(sbat);
+       UINT32 attributes = SBAT_VAR_ATTRS;
+
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
+               return 0;
+       else
+               return -1;
+}
+
+int
+test_preserve_sbat_uefi_variable_version_older(void)
+{
+       char sbat[] =    "sbat,1,2021030218\ncomponent,2,\n";
+       char sbatvar[] = "sbat,2,2022030218\ncomponent,2,\n";
+       size_t sbat_size = sizeof(sbat);
+       UINT32 attributes = SBAT_VAR_ATTRS;
+
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
+               return -1;
+       else
+               return 0;
+}
+
+int
+test_preserve_sbat_uefi_variable_version_olderlonger(void)
+{
+       char sbat[] =    "sbat,2,2021030218\ncomponent,2,\n";
+       char sbatvar[] = "sbat,10,2022030218\ncomponent,2,\n";
+       size_t sbat_size = sizeof(sbat);
+       UINT32 attributes = SBAT_VAR_ATTRS;
+
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
+               return -1;
+       else
+               return 0;
+}
+
+
+int
+test_preserve_sbat_uefi_variable_newer(void)
+{
+       char sbat[] =    "sbat,1,2021030218\ncomponent,2,\n";
+       char sbatvar[] = "sbat,1,2025030218\ncomponent,5,\ncomponent,3";
+       size_t sbat_size = sizeof(sbat);
+       UINT32 attributes = SBAT_VAR_ATTRS;
+
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
+               return -1;
+       else
+               return 0;
+}
+int
+test_preserve_sbat_uefi_variable_older(void)
+{
+       char sbat[] =    "sbat,1,2025030218\ncomponent,2,\ncomponent,3";
+       char sbatvar[] = "sbat,1,2020030218\ncomponent,1,\n";
        size_t sbat_size = sizeof(sbat);
        UINT32 attributes = SBAT_VAR_ATTRS;
 
-       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes))
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
                return 0;
        else
                return -1;
@@ -978,11 +1068,12 @@ test_preserve_sbat_uefi_variable_good(void)
 int
 test_preserve_sbat_uefi_variable_bad_sig(void)
 {
-       char sbat[] = "bad_sig,1,\ncomponent,2,\n";
+       char sbat[] = "bad_sig,1,2021030218\ncomponent,2,\n";
+       char sbatvar[] = "sbat,1,2021030218\n";
        size_t sbat_size = sizeof(sbat);
        UINT32 attributes = SBAT_VAR_ATTRS;
 
-       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes))
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
                return -1;
        else
                return 0;
@@ -991,11 +1082,12 @@ test_preserve_sbat_uefi_variable_bad_sig(void)
 int
 test_preserve_sbat_uefi_variable_bad_attr(void)
 {
-       char sbat[] = "sbat,1,\ncomponent,2,\n";
+       char sbat[] = "sbat,1,2021030218\ncomponent,2,\n";
+       char sbatvar[] = "sbat,1,2021030218\n";
        size_t sbat_size = sizeof(sbat);
        UINT32 attributes = 0;
 
-       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes))
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
                return -1;
        else
                return 0;
@@ -1005,10 +1097,11 @@ int
 test_preserve_sbat_uefi_variable_bad_short(void)
 {
        char sbat[] = "sba";
+       char sbatvar[] = "sbat,1,2021030218\n";
        size_t sbat_size = sizeof(sbat);
        UINT32 attributes = SBAT_VAR_ATTRS;
 
-       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes))
+       if (preserve_sbat_uefi_variable(sbat, sbat_size, attributes, sbatvar))
                return -1;
        else
                return 0;
@@ -1052,9 +1145,15 @@ main(void)
        test(test_parse_and_verify);
 
        test(test_preserve_sbat_uefi_variable_good);
+       test(test_preserve_sbat_uefi_variable_newer);
+       test(test_preserve_sbat_uefi_variable_older);
        test(test_preserve_sbat_uefi_variable_bad_sig);
        test(test_preserve_sbat_uefi_variable_bad_attr);
        test(test_preserve_sbat_uefi_variable_bad_short);
+       test(test_preserve_sbat_uefi_variable_version_newer);
+       test(test_preserve_sbat_uefi_variable_version_newerlonger);
+       test(test_preserve_sbat_uefi_variable_version_older);
+       test(test_preserve_sbat_uefi_variable_version_olderlonger);
 
        return 0;
 }
index 9cb831deef9f0a1bc9e4af30dd64ff8c05c6ab3a..30f8dd0b4e7dbddfe801c014113198b13c8cc60d 100644 (file)
@@ -926,12 +926,15 @@ static int
 test_strncpy(void)
 {
        char s[] = "0123456789abcdef\0000";
-       char s0[4096+4096];
-       char *s1 = &s0[4096];
+       char s0[4096];
+       char s1[4096];
 
        memset(s0, 0, sizeof(s0));
        memcpy(s0, s, sizeof(s));
-
+#if __GNUC_PREREQ(8, 1)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wstringop-truncation"
+#endif
        memset(s1, 0, 4096);
        assert_equal_return(strncpy(s1, s0, 0), s1, -1, "got %p expected %p\n");
        assert_equal_return(strlen(s1), 0, -1, "got %d expected %d\n");
@@ -1030,7 +1033,9 @@ test_strncpy(void)
        assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
        assert_equal_return(s1[17], '0', -1, "got %#02hhx expected %02hhx\n");
        assert_equal_return(s1[18], '1', -1, "got %#02hhx expected %02hhx\n");
-
+#if __GNUC_PREREQ(8, 1)
+# pragma GCC diagnostic pop
+#endif
        return 0;
 }
 
@@ -1038,12 +1043,12 @@ static int
 test_strcat(void)
 {
        char s[] = "0123456789abcdef\0000";
-       char s0[8192];
-       char *s1 = &s0[4096];
+       char s0[4096];
+       char s1[4096];
        char *s2;
        char s3[] = "0123456789abcdef0123456789abcdef\000\000\000\000\000";
 
-       memset(s0, 0, 8192);
+       memset(s0, 0, sizeof(s0));
        memcpy(s0, s, sizeof(s));
 
        memset(s1, 0, 4096);
diff --git a/test.c b/test.c
index 46cab533534079cdcab05e565b3eaebfdb5af9e0..c7978fa2cb8ebe853b74bbae56844130995aac6b 100644 (file)
--- a/test.c
+++ b/test.c
@@ -259,6 +259,12 @@ console_print(const CHAR16 *fmt, ...)
        return 0;
 }
 
+void
+console_error(CHAR16 *err, EFI_STATUS efi_status)
+{
+       return;
+}
+
 #ifndef HAVE_START_IMAGE
 EFI_STATUS
 start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)