mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-10-04 20:59:04 +00:00
Release shimversion 15.8-1~deb12u1
-----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEzrtSMB1hfpEDkP4WWHl5VzRCaE4FAmY2t7IRHHN0ZXZlQGVp bnZhbC5jb20ACgkQWHl5VzRCaE6LrQ//ZVPsTgt+cha/BTK71nKSY9CjkeLdxlJO wbBPvcDUZmNjI6snpjYfMNDsB9B3uOcxQ/8GvQUmUvp/EWu17qzFLpF4C+MFd7cY xJVF29tUxCM2Ug00wmskV8RI6pVmbSmI6YKknNMPuBBbaN58/tE6WESaSNKerHYH B/26C7+1rB92gK2RqqQqQIavpsDZL+nTHfFlAbp4cewCgR7otuIx1i8dW/4Ewrh9 vMECv0664teGdf7nebShKgwutLtVSdvk2L+YMMd1l+FbcU6fhduLENZz/dc3WGLf 4QqYRkHC8JMK7eDSAXzUc2ghIUmJT8xPrU/7I4I2Zsc+86XNOZGmiu6cTnocW/QT 3+T9o2uNWDK+p2P0uP5Fp/Z9gfIzXzkMs7UALc5CTC1PHhUg6I1f+tcVfkef7Afx 4dZwA/sF/sgg2931AJqCz1eQC+btEAmMRvcXAtsxK1OBdoSZMZ37nA6E+wdlyako PJEXe9842WHuynG4JaRCndoMfoNswxC40DEqzn6n+kXvlZeRggR039BGfEKORdtK fuMbHBuvpHOxo51GjyFHbGVh/8GhCxub4YWOgidPUBzheQMTVTuWmWujLAVGpAs9 oZ+4v2n3yrfDPMvT9HtTHXG66Gisz25l24hL4enJPuBf7ti2bPCBuTAor1WcqWto hEeOYwszGJw= =Krhw -----END PGP SIGNATURE----- Merge tag 'debian/15.8-1_deb12u1' into proxmox/bookworm Release shimversion 15.8-1~deb12u1
This commit is contained in:
commit
437ba3a444
8
.github/workflows/pullrequest.yml
vendored
8
.github/workflows/pullrequest.yml
vendored
@ -135,10 +135,6 @@ jobs:
|
||||
efiarch: x64
|
||||
makearch: x86_64
|
||||
distro: centos8
|
||||
- arch: amd64
|
||||
efiarch: x64
|
||||
makearch: x86_64
|
||||
distro: centos7
|
||||
- arch: amd64
|
||||
efiarch: ia32
|
||||
makearch: ia32
|
||||
@ -155,10 +151,6 @@ jobs:
|
||||
efiarch: ia32
|
||||
makearch: ia32
|
||||
distro: centos8
|
||||
- arch: amd64
|
||||
efiarch: ia32
|
||||
makearch: ia32
|
||||
distro: centos7
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -33,7 +33,12 @@ Make.local
|
||||
/.cache/
|
||||
/certdb/
|
||||
/compile_commands.json
|
||||
/compile_commands.events.json
|
||||
/cov-int/
|
||||
/crash-*
|
||||
/fuzz-*
|
||||
!/fuzz-*.c
|
||||
/leak-*
|
||||
/post-process-pe
|
||||
/random.bin
|
||||
/sbat.*.csv
|
||||
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,4 +1,4 @@
|
||||
[submodule "gnu-efi"]
|
||||
path = gnu-efi
|
||||
url = https://github.com/rhboot/gnu-efi.git
|
||||
branch = shim-15.6
|
||||
branch = shim-15.8
|
||||
|
3
BUILDING
3
BUILDING
@ -78,6 +78,9 @@ Variables you could set to customize the build:
|
||||
- OSLABEL
|
||||
This is the label that will be put in BOOT$(EFI_ARCH).CSV for your OS.
|
||||
By default this is the same value as EFIDIR .
|
||||
- POST_PROCESS_PE_FLAGS
|
||||
This allows you to add flags to the invocation of "post-process-pe", for
|
||||
example to disable the NX compatibility flag.
|
||||
|
||||
Vendor SBAT data:
|
||||
It will sometimes be requested by reviewers that a build includes extra
|
||||
|
@ -11,7 +11,8 @@ INCLUDES = -I$(CRYPTDIR) -I$(CRYPTDIR)/Include \
|
||||
-isystem $(TOPDIR)/include/system \
|
||||
-isystem $(shell $(CC) -print-file-name=include)
|
||||
|
||||
WARNFLAGS += -Wno-unused-parameter
|
||||
WARNFLAGS += -Wno-unused-parameter \
|
||||
-Wno-unused-but-set-variable
|
||||
|
||||
CFLAGS = $(FEATUREFLAGS) \
|
||||
$(OPTIMIZATIONS) \
|
||||
|
@ -23,7 +23,7 @@ FEATUREFLAGS += -nostdinc
|
||||
WARNFLAGS += -Wno-empty-body \
|
||||
-Wno-implicit-fallthrough \
|
||||
$(if $(findstring gcc,$(CC)),-Wno-old-style-declaration) \
|
||||
$(if $(findstring gcc,$(CC)),-Wno-unused-but-set-variable) \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-unused-parameter
|
||||
|
||||
CFLAGS = $(FEATUREFLAGS) \
|
||||
|
@ -15,6 +15,20 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
#include <OpenSslSupport.h>
|
||||
|
||||
//
|
||||
// Extra header to record the memory buffer size from malloc routine.
|
||||
//
|
||||
#define CRYPTMEM_HEAD_SIGNATURE EFI_SIGNATURE_32('c','m','h','d')
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
UINT32 Reserved;
|
||||
UINTN Size;
|
||||
} CRYPTMEM_HEAD;
|
||||
|
||||
#define CRYPTMEM_OVERHEAD sizeof(CRYPTMEM_HEAD)
|
||||
|
||||
#define MIN(a, b) ({(a) < (b) ? (a) : (b);})
|
||||
|
||||
//
|
||||
// -- Memory-Allocation Routines --
|
||||
//
|
||||
@ -22,27 +36,84 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
/* Allocates memory blocks */
|
||||
void *malloc (size_t size)
|
||||
{
|
||||
return AllocatePool ((UINTN) size);
|
||||
CRYPTMEM_HEAD *PoolHdr;
|
||||
UINTN NewSize;
|
||||
VOID *Data;
|
||||
|
||||
//
|
||||
// Adjust the size by the buffer header overhead
|
||||
//
|
||||
NewSize = (UINTN)(size) + CRYPTMEM_OVERHEAD;
|
||||
|
||||
Data = AllocatePool (NewSize);
|
||||
if (Data != NULL) {
|
||||
PoolHdr = (CRYPTMEM_HEAD *)Data;
|
||||
//
|
||||
// Record the memory brief information
|
||||
//
|
||||
PoolHdr->Signature = CRYPTMEM_HEAD_SIGNATURE;
|
||||
PoolHdr->Size = size;
|
||||
|
||||
return (VOID *)(PoolHdr + 1);
|
||||
} else {
|
||||
//
|
||||
// The buffer allocation failed.
|
||||
//
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reallocate memory blocks */
|
||||
void *realloc (void *ptr, size_t size)
|
||||
{
|
||||
//
|
||||
// BUG: hardcode OldSize == size! We have no any knowledge about
|
||||
// memory size of original pointer ptr.
|
||||
//
|
||||
return ReallocatePool (ptr, (UINTN) size, (UINTN) size);
|
||||
CRYPTMEM_HEAD *OldPoolHdr;
|
||||
CRYPTMEM_HEAD *NewPoolHdr;
|
||||
UINTN OldSize;
|
||||
UINTN NewSize;
|
||||
VOID *Data;
|
||||
|
||||
NewSize = (UINTN)size + CRYPTMEM_OVERHEAD;
|
||||
Data = AllocatePool (NewSize);
|
||||
if (Data != NULL) {
|
||||
NewPoolHdr = (CRYPTMEM_HEAD *)Data;
|
||||
NewPoolHdr->Signature = CRYPTMEM_HEAD_SIGNATURE;
|
||||
NewPoolHdr->Size = size;
|
||||
if (ptr != NULL) {
|
||||
//
|
||||
// Retrieve the original size from the buffer header.
|
||||
//
|
||||
OldPoolHdr = (CRYPTMEM_HEAD *)ptr - 1;
|
||||
ASSERT (OldPoolHdr->Signature == CRYPTMEM_HEAD_SIGNATURE);
|
||||
OldSize = OldPoolHdr->Size;
|
||||
|
||||
//
|
||||
// Duplicate the buffer content.
|
||||
//
|
||||
CopyMem ((VOID *)(NewPoolHdr + 1), ptr, MIN (OldSize, size));
|
||||
FreePool ((VOID *)OldPoolHdr);
|
||||
}
|
||||
|
||||
return (VOID *)(NewPoolHdr + 1);
|
||||
} else {
|
||||
//
|
||||
// The buffer allocation failed.
|
||||
//
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* De-allocates or frees a memory block */
|
||||
void free (void *ptr)
|
||||
{
|
||||
CRYPTMEM_HEAD *PoolHdr;
|
||||
|
||||
//
|
||||
// In Standard C, free() handles a null pointer argument transparently. This
|
||||
// is not true of FreePool() below, so protect it.
|
||||
//
|
||||
if (ptr != NULL) {
|
||||
FreePool (ptr);
|
||||
PoolHdr = (CRYPTMEM_HEAD *)ptr - 1;
|
||||
ASSERT (PoolHdr->Signature == CRYPTMEM_HEAD_SIGNATURE);
|
||||
FreePool (PoolHdr);
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +139,8 @@ CFLAGS = $(FEATUREFLAGS) \
|
||||
$(INCLUDES) \
|
||||
$(DEFINES)
|
||||
|
||||
POST_PROCESS_PE_FLAGS =
|
||||
|
||||
ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined)
|
||||
DEFINES += -DOVERRIDE_SECURITY_POLICY
|
||||
endif
|
||||
@ -186,6 +188,9 @@ endif
|
||||
ifneq ($(origin VENDOR_DBX_FILE), undefined)
|
||||
DEFINES += -DVENDOR_DBX_FILE=\"$(VENDOR_DBX_FILE)\"
|
||||
endif
|
||||
ifneq ($(origin SBAT_AUTOMATIC_DATE), undefined)
|
||||
DEFINES += -DSBAT_AUTOMATIC_DATE=$(SBAT_AUTOMATIC_DATE)
|
||||
endif
|
||||
|
||||
LDFLAGS = --hash-style=sysv -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(LOCAL_EFI_PATH) -L$(LIBDIR) -LCryptlib -LCryptlib/OpenSSL $(EFI_CRT_OBJS) --build-id=sha1 $(ARCH_LDFLAGS) --no-undefined
|
||||
|
||||
|
@ -36,6 +36,6 @@ $(strip $(foreach x,$(DEFAULT_$(1)),
|
||||
endef
|
||||
|
||||
%.o : %.S
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
$(CC) $(CFLAGS) -c -o $@ $< $(IGNORE_COMPILER_ERRORS)
|
||||
|
||||
# vim:filetype=make
|
||||
|
45
Makefile
45
Makefile
@ -1,7 +1,7 @@
|
||||
default : all
|
||||
|
||||
NAME = shim
|
||||
VERSION = 15.7
|
||||
VERSION = 15.8
|
||||
ifneq ($(origin RELEASE),undefined)
|
||||
DASHRELEASE ?= -$(RELEASE)
|
||||
else
|
||||
@ -38,9 +38,9 @@ CFLAGS += -DENABLE_SHIM_CERT
|
||||
else
|
||||
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 sbat_var.o pe.o httpboot.o csv.o load-options.o
|
||||
OBJS = shim.o globals.o mok.o netboot.o cert.o replacements.o tpm.o version.o errlog.o sbat.o sbat_data.o sbat_var.o pe.o pe-relocate.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) cert.S sbat_var.S
|
||||
ORIG_SOURCES = shim.c globals.c mok.c netboot.c replacements.c tpm.c errlog.c sbat.c pe.c pe-relocate.c httpboot.c shim.h version.h $(wildcard include/*.h) cert.S sbat_var.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
|
||||
@ -76,6 +76,13 @@ ifneq ($(origin EFI_PATH),undefined)
|
||||
$(error EFI_PATH is no longer supported, you must build using the supplied copy of gnu-efi)
|
||||
endif
|
||||
|
||||
compile_commands.json : Makefile Make.rules Make.defaults
|
||||
make clean
|
||||
bear -- make COMPILER=clang test all
|
||||
sed -i \
|
||||
-e 's/"-maccumulate-outgoing-args",//g' \
|
||||
$@
|
||||
|
||||
update :
|
||||
git submodule update --init --recursive
|
||||
|
||||
@ -156,19 +163,19 @@ gnu-efi/$(ARCH_GNUEFI)/gnuefi/libgnuefi.a gnu-efi/$(ARCH_GNUEFI)/lib/libefi.a:
|
||||
ARCH=$(ARCH_GNUEFI) \
|
||||
TOPDIR=$(TOPDIR)/gnu-efi \
|
||||
-f $(TOPDIR)/gnu-efi/Makefile \
|
||||
lib gnuefi inc
|
||||
lib gnuefi inc $(IGNORE_COMPILER_ERRORS)
|
||||
|
||||
Cryptlib/libcryptlib.a:
|
||||
for i in Hash Hmac Cipher Rand Pk Pem SysCall; do mkdir -p Cryptlib/$$i; done
|
||||
$(MAKE) TOPDIR=$(TOPDIR) VPATH=$(TOPDIR)/Cryptlib -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile
|
||||
$(MAKE) TOPDIR=$(TOPDIR) VPATH=$(TOPDIR)/Cryptlib -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile $(IGNORE_COMPILER_ERRORS)
|
||||
|
||||
Cryptlib/OpenSSL/libopenssl.a:
|
||||
for i in x509v3 x509 txt_db stack sha rsa rc4 rand pkcs7 pkcs12 pem ocsp objects modes md5 lhash kdf hmac evp err dso dh conf comp cmac buffer bn bio async/arch asn1 aes; do mkdir -p Cryptlib/OpenSSL/crypto/$$i; done
|
||||
$(MAKE) TOPDIR=$(TOPDIR) VPATH=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile
|
||||
$(MAKE) TOPDIR=$(TOPDIR) VPATH=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile $(IGNORE_COMPILER_ERRORS)
|
||||
|
||||
lib/lib.a: | $(TOPDIR)/lib/Makefile $(wildcard $(TOPDIR)/include/*.[ch])
|
||||
mkdir -p lib
|
||||
$(MAKE) VPATH=$(TOPDIR)/lib TOPDIR=$(TOPDIR) -C lib -f $(TOPDIR)/lib/Makefile
|
||||
$(MAKE) VPATH=$(TOPDIR)/lib TOPDIR=$(TOPDIR) -C lib -f $(TOPDIR)/lib/Makefile $(IGNORE_COMPILER_ERRORS)
|
||||
|
||||
post-process-pe : $(TOPDIR)/post-process-pe.c
|
||||
$(HOSTCC) -std=gnu11 -Og -g3 -Wall -Wextra -Wno-missing-field-initializers -Werror -o $@ $<
|
||||
@ -255,7 +262,7 @@ endif
|
||||
-j .rela* -j .dyn -j .reloc -j .eh_frame \
|
||||
-j .vendor_cert -j .sbat -j .sbatlevel \
|
||||
$(FORMAT) $< $@
|
||||
./post-process-pe -vv $@
|
||||
./post-process-pe -vv $(POST_PROCESS_PE_FLAGS) $@
|
||||
|
||||
ifneq ($(origin ENABLE_SHIM_HASH),undefined)
|
||||
%.hash : %.efi
|
||||
@ -286,6 +293,15 @@ else
|
||||
$(PESIGN) -n certdb -i $< -c "shim" -s -o $@ -f
|
||||
endif
|
||||
|
||||
fuzz fuzz-clean fuzz-coverage fuzz-lto :
|
||||
@make -f $(TOPDIR)/include/fuzz.mk \
|
||||
COMPILER="$(COMPILER)" \
|
||||
CROSS_COMPILE="$(CROSS_COMPILE)" \
|
||||
CLANG_WARNINGS="$(CLANG_WARNINGS)" \
|
||||
ARCH_DEFINES="$(ARCH_DEFINES)" \
|
||||
EFI_INCLUDES="$(EFI_INCLUDES)" \
|
||||
fuzz-clean $@
|
||||
|
||||
test test-clean test-coverage test-lto :
|
||||
@make -f $(TOPDIR)/include/test.mk \
|
||||
COMPILER="$(COMPILER)" \
|
||||
@ -295,14 +311,21 @@ test test-clean test-coverage test-lto :
|
||||
EFI_INCLUDES="$(EFI_INCLUDES)" \
|
||||
test-clean $@
|
||||
|
||||
$(patsubst %.c,%,$(wildcard fuzz-*.c)) :
|
||||
@make -f $(TOPDIR)/include/fuzz.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" $@
|
||||
|
||||
$(patsubst %.c,%,$(wildcard test-*.c)) :
|
||||
@make -f $(TOPDIR)/include/test.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" $@
|
||||
|
||||
.PHONY : $(patsubst %.c,%,$(wildcard test-*.c)) test
|
||||
clean-fuzz-objs:
|
||||
@make -f $(TOPDIR)/include/fuzz.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" clean
|
||||
|
||||
clean-test-objs:
|
||||
@make -f $(TOPDIR)/include/test.mk EFI_INCLUDES="$(EFI_INCLUDES)" ARCH_DEFINES="$(ARCH_DEFINES)" clean
|
||||
|
||||
.PHONY : $(patsubst %.c,%,$(wildcard fuzz-*.c)) fuzz
|
||||
.PHONY : $(patsubst %.c,%,$(wildcard test-*.c)) test
|
||||
|
||||
clean-gnu-efi:
|
||||
@if [ -d gnu-efi ] ; then \
|
||||
$(MAKE) -C gnu-efi \
|
||||
@ -322,7 +345,7 @@ clean-lib-objs:
|
||||
|
||||
clean-shim-objs:
|
||||
@rm -rvf $(TARGET) *.o $(SHIM_OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb $(BOOTCSVNAME)
|
||||
@rm -vf *.debug *.so *.efi *.efi.* *.tar.* version.c buildid post-process-pe
|
||||
@rm -vf *.debug *.so *.efi *.efi.* *.tar.* version.c buildid post-process-pe compile_commands.json
|
||||
@rm -vf Cryptlib/*.[oa] Cryptlib/*/*.[oa]
|
||||
@if [ -d .git ] ; then git clean -f -d -e 'Cryptlib/OpenSSL/*'; fi
|
||||
|
||||
@ -336,7 +359,7 @@ clean-cryptlib-objs:
|
||||
$(MAKE) -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile clean ; \
|
||||
fi
|
||||
|
||||
clean: clean-shim-objs clean-test-objs clean-gnu-efi clean-openssl-objs clean-cryptlib-objs clean-lib-objs
|
||||
clean: clean-shim-objs clean-fuzz-objs clean-test-objs clean-gnu-efi clean-openssl-objs clean-cryptlib-objs clean-lib-objs
|
||||
|
||||
GITTAG = $(VERSION)
|
||||
|
||||
|
@ -53,6 +53,11 @@ The hash will be regenerated by MokManager after the user is requested
|
||||
to enter their password to confirm enrolment of the keys. If the hash
|
||||
matches MokAuth, the user will be prompted to enrol the keys. BS,RT,NV
|
||||
|
||||
ShimRetainProtocol: UINT8, read by Shim before uninstalling protocol.
|
||||
If set to non-zero, Shim will keep the protocol in place. It can be
|
||||
used by second stages to ensure the protocol is still available for
|
||||
later stages, and can thus be used to verify additional PE files. BS,RT.
|
||||
|
||||
State variables:
|
||||
|
||||
MokList: A list of authorized keys and hashes. An EFI_SIGNATURE_LIST
|
||||
|
@ -25,3 +25,8 @@ There are a couple of build options, and a couple of ways to customize the
|
||||
build, described in [BUILDING](BUILDING).
|
||||
|
||||
See the [test plan](testplan.txt), and file a ticket if anything fails!
|
||||
|
||||
In the event that the developers need to be contacted related to a security
|
||||
incident or vulnerability, please mail [secalert@redhat.com].
|
||||
|
||||
[secalert@redhat.com]: mailto:secalert@redhat.com
|
||||
|
@ -5,14 +5,14 @@ SBAT: Current proposal
|
||||
-------------
|
||||
|
||||
the `.sbat` section has the following fields:
|
||||
| field | meaning |
|
||||
|---|---|
|
||||
| component_name | the name we're comparing
|
||||
| component_generation | the generation number for the comparison
|
||||
| vendor_name | human readable vendor name
|
||||
| vendor_package_name | human readable package name
|
||||
| vendor_version | human readable package version (maybe machine parseable too, not specified here)
|
||||
| vendor_url | url to look stuff up, contact, whatever.
|
||||
| field | meaning |
|
||||
|----------------------|----------------------------------------------------------------------------------|
|
||||
| component_name | the name we're comparing |
|
||||
| component_generation | the generation number for the comparison |
|
||||
| vendor_name | human readable vendor name |
|
||||
| vendor_package_name | human readable package name |
|
||||
| vendor_version | human readable package version (maybe machine parseable too, not specified here) |
|
||||
| vendor_url | url to look stuff up, contact, whatever. |
|
||||
|
||||
`SBAT` EFI variable
|
||||
-----------------
|
||||
|
30
SBAT.md
30
SBAT.md
@ -255,11 +255,11 @@ customer impact with as few re-releases as possible, while not creating an
|
||||
unnecessarily large UEFI revocation variable payload.
|
||||
|
||||
| | prior to<br>disclosure\* | after<br>disclosure | after Vendor C's<br>first update | after Vendor C's<br>second update | after next global<br>disclosure |
|
||||
|--------------------------------------------------------------------------------------|------------------------|---------------------|----------------------------------|----------------------------------|---------------------------------|
|
||||
| GRUB global<br>generation number in<br>artifacts .sbat section | 3 | 4 | 4 | 4 | 5 |
|
||||
| Vendor C's product-specific<br>generation number in artifact's<br>.sbat section | 1 | 1 | 2 | 3 | 1 |
|
||||
| GRUB global<br>generation number in<br>UEFI SBAT revocation variable | 3 | 4 | 4 | 4 | 5 |
|
||||
| Vendor C's product-specific<br>generation number in<br>UEFI SBAT revocation variable | not set | not set | 2 | 3 | not set |
|
||||
|--------------------------------------------------------------------------------------|--------------------------|---------------------|----------------------------------|-----------------------------------|---------------------------------|
|
||||
| GRUB global<br>generation number in<br>artifacts .sbat section | 3 | 4 | 4 | 4 | 5 |
|
||||
| Vendor C's product-specific<br>generation number in artifact's<br>.sbat section | 1 | 1 | 2 | 3 | 1 |
|
||||
| GRUB global<br>generation number in<br>UEFI SBAT revocation variable | 3 | 4 | 4 | 4 | 5 |
|
||||
| Vendor C's product-specific<br>generation number in<br>UEFI SBAT revocation variable | not set | not set | 2 | 3 | not set |
|
||||
|
||||
\* A disclosure is the event/date where a CVE and fixes for it are made public.
|
||||
|
||||
@ -307,7 +307,7 @@ most up to date UEFI metadata.
|
||||
Even prior to or without moving to one-shim, it is desirable to get every
|
||||
vendor onto as few shims as possible. Ideally a vendor would have a single shim
|
||||
signed with their certificate embedded and then use that certificate to sign
|
||||
additional <Vendor>_key.EFI key files that then contain all the keys that the
|
||||
additional `<Vendor>_key.EFI` key files that then contain all the keys that the
|
||||
individual components for their products are signed with. This file name needs
|
||||
to be registered at the time of shim review and should not be changed without
|
||||
going back to a shim review. A vendor should be able to store as many
|
||||
@ -354,14 +354,14 @@ them.
|
||||
|
||||
Adding a .sbat section containing the SBAT metadata structure to PE images.
|
||||
|
||||
| field | meaning |
|
||||
|---|---|
|
||||
| component_name | the name we're comparing
|
||||
| component_generation | the generation number for the comparison
|
||||
| vendor_name | human readable vendor name
|
||||
| vendor_package_name | human readable package name
|
||||
| vendor_version | human readable package version (maybe machine parseable too, not specified here)
|
||||
| vendor_url | url to look stuff up, contact, whatever.
|
||||
| field | meaning |
|
||||
|----------------------|----------------------------------------------------------------------------------|
|
||||
| component_name | the name we're comparing |
|
||||
| component_generation | the generation number for the comparison |
|
||||
| vendor_name | human readable vendor name |
|
||||
| vendor_package_name | human readable package name |
|
||||
| vendor_version | human readable package version (maybe machine parseable too, not specified here) |
|
||||
| vendor_url | url to look stuff up, contact, whatever. |
|
||||
|
||||
The format of this .sbat section is comma separated values, or more
|
||||
specifically ASCII encoded strings.
|
||||
@ -448,7 +448,7 @@ fixed. The following show the evolution over a sample set of events:
|
||||
|
||||
## Starting point
|
||||
|
||||
Before CVEs are encountered, an undesirable moudule was built into the a fedora
|
||||
Before CVEs are encountered, an undesirable module was built into Fedora's
|
||||
grub, so it's product-specific generation number has been bumped:
|
||||
|
||||
```
|
||||
|
108
SbatLevel_Variable.txt
Normal file
108
SbatLevel_Variable.txt
Normal file
@ -0,0 +1,108 @@
|
||||
In order to apply SBAT based revocations on systems that will never
|
||||
run shim, code running in boot services context needs to set the
|
||||
following variable:
|
||||
|
||||
Name: SbatLevel
|
||||
Attributes: (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
|
||||
Namespace Guid: 605dab50-e046-4300-abb6-3dd810dd8b23
|
||||
|
||||
Variable content:
|
||||
|
||||
Initialized, no revocations:
|
||||
|
||||
sbat,1,2021030218
|
||||
|
||||
To Revoke GRUB2 binaries impacted by
|
||||
|
||||
* CVE-2021-3695
|
||||
* CVE-2021-3696
|
||||
* CVE-2021-3697
|
||||
* CVE-2022-28733
|
||||
* CVE-2022-28734
|
||||
* CVE-2022-28735
|
||||
* CVE-2022-28736
|
||||
|
||||
sbat,1,2022052400
|
||||
grub,2
|
||||
|
||||
and shim binaries impacted by
|
||||
|
||||
* CVE-2022-28737
|
||||
|
||||
sbat,1,2022052400
|
||||
shim,2
|
||||
grub,2
|
||||
|
||||
Shim delivered both versions of these revocations with
|
||||
the same 2022052400 date stamp, once as an opt-in latest
|
||||
revocation with shim,2 and then as an automatic revocation without
|
||||
shim,2
|
||||
|
||||
|
||||
To revoke GRUB2 grub binaries impacted by
|
||||
|
||||
* CVE-2022-2601
|
||||
* CVE-2022-3775
|
||||
|
||||
sbat,1,2022111500
|
||||
shim,2
|
||||
grub,3
|
||||
|
||||
To revoke Debian's grub.3 which missed
|
||||
the patches:
|
||||
|
||||
sbat,1,2023012900
|
||||
shim,2
|
||||
grub,3
|
||||
grub.debian,4
|
||||
|
||||
|
||||
An additonal bug was fixed in shim that was not considered exploitable,
|
||||
can be revoked by setting:
|
||||
|
||||
sbat,1,2023012950
|
||||
shim,3
|
||||
grub,3
|
||||
grub.debian,4
|
||||
|
||||
shim did not deliver this payload at the time
|
||||
|
||||
|
||||
To Revoke GRUB2 binaries impacted by:
|
||||
|
||||
* CVE-2023-4692
|
||||
* CVE-2023-4693
|
||||
|
||||
These CVEs are in the ntfs module and vendors that do and do not
|
||||
ship this module as part of their signed binary are split.
|
||||
|
||||
sbat,1,2023091900
|
||||
shim,2
|
||||
grub,4
|
||||
|
||||
Since not everyone has shipped updated GRUB packages, shim did not
|
||||
deliver this revocation at the time.
|
||||
|
||||
To Revoke shim binaries impacted by:
|
||||
|
||||
* CVE-2023-40547
|
||||
* CVE-2023-40546
|
||||
* CVE-2023-40548
|
||||
* CVE-2023-40549
|
||||
* CVE-2023-40550
|
||||
* CVE-2023-40551
|
||||
|
||||
sbat,1,2024010900
|
||||
shim,4
|
||||
grub,3
|
||||
grub.debian,4
|
||||
|
||||
Since http boot shim CVE is considerably more serious than then GRUB
|
||||
ntfs CVEs shim is delivering the shim revocation without the updated
|
||||
GRUB revocation as a latest payload.
|
||||
|
||||
To revoke both the impacted shim and impacted GRUB binaries:
|
||||
|
||||
sbat,1,2024<date TBD>
|
||||
shim,4
|
||||
grub,4
|
1
cert.S
1
cert.S
@ -52,3 +52,4 @@ vendor_deauthorized:
|
||||
#endif
|
||||
.Lvendor_deauthorized_end:
|
||||
.Lcert_table_end:
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -1,2 +1,2 @@
|
||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
|
||||
shim,3,UEFI shim,shim,1,https://github.com/rhboot/shim
|
||||
shim,4,UEFI shim,shim,1,https://github.com/rhboot/shim
|
||||
|
|
31
debian/changelog
vendored
31
debian/changelog
vendored
@ -1,3 +1,34 @@
|
||||
shim (15.8-1~deb12u1) bookworm; urgency=medium
|
||||
|
||||
[ Steve McIntyre ]
|
||||
* Cope with changes in pesign packaging.
|
||||
* New upstream release fixing more bugs
|
||||
* Remove all our previous patches, no longer needed:
|
||||
+ Make-sbat_var.S-parse-right-with-buggy-gcc-binutils.patch (now
|
||||
upstream)
|
||||
+ Enable-NX.patch (we don't want NX just yet until the whole boot
|
||||
stack is NX-capable)
|
||||
+ block-grub-sbat3-debian.patch (not needed now upstream grub SBAT
|
||||
is 4)
|
||||
* Cherry-pick 2 new patches from upstream for grub revocations:
|
||||
+ 0001-sbat-Add-grub.peimage-2-to-latest-CVE-2024-2312.patch
|
||||
+ 0002-sbat-Also-bump-latest-for-grub-4-and-to-todays-date.patch
|
||||
* Log if the build is nx-compatible or not
|
||||
* Force shim to use the latest revocations by default to block some
|
||||
older grub / peimage issues. This is:
|
||||
"shim,4\ngrub,4\ngrub.peimage,2\n"
|
||||
* Install a copy of the Debian CA certificate into /usr/share/shim.
|
||||
Closes: #1069054
|
||||
* Clean up better after build. Closes: #1046268
|
||||
|
||||
[ Bastien Roucariès ]
|
||||
* Port autopkgtest from ubuntu
|
||||
* Import MR-12: "shim-unsigned:amd64 cannot be installed alongside
|
||||
shim-unsigned:i386", thanks to adrian15 adrian15 (Closes: #936009).
|
||||
* Fix debian/watch and check signature
|
||||
|
||||
-- Steve McIntyre <93sam@debian.org> Sat, 04 May 2024 21:28:21 +0100
|
||||
|
||||
shim (15.7-1+pmx1) bookworm; urgency=medium
|
||||
|
||||
* Bump version for Proxmox build.
|
||||
|
32
debian/check_nx
vendored
Executable file
32
debian/check_nx
vendored
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Helper script - check if a binary is tagged as NX-compatible or not.
|
||||
|
||||
set -e
|
||||
|
||||
for FILE in "$@"; do
|
||||
|
||||
if [ ! -f "${FILE}" ]; then
|
||||
echo "${FILE} does not exist. ABORT."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking NX bit on ${FILE}:"
|
||||
DLL_CHARACTERISTICS=$(objdump -x "${FILE}" | awk '/DllCharacteristics/ {print $2}')
|
||||
|
||||
echo " DllCharacteristics $DLL_CHARACTERISTICS"
|
||||
case $DLL_CHARACTERISTICS in
|
||||
00000000)
|
||||
echo " NOT tagged as NX-compatible"
|
||||
;;
|
||||
00000100)
|
||||
echo " tagged as NX-compatible"
|
||||
;;
|
||||
*)
|
||||
echo " UNRECOGNISED value, ABORT";
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
done
|
||||
|
2
debian/control
vendored
2
debian/control
vendored
@ -11,6 +11,7 @@ Build-Depends: debhelper-compat (= 12),
|
||||
gcc-12,
|
||||
dos2unix,
|
||||
pesign (>= 0.112-5),
|
||||
efivar,
|
||||
xxd,
|
||||
libefivar-dev
|
||||
Vcs-Browser: https://git.proxmox.com/?p=efi-boot-shim.git
|
||||
@ -21,6 +22,7 @@ Architecture: amd64 arm64 i386
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Conflicts: shim (<< 15+1533136590.3beb971-3~),
|
||||
Replaces: shim (<< 15+1533136590.3beb971-3~),
|
||||
Multi-Arch: same
|
||||
Description: boot loader to chain-load signed boot loaders under Secure Boot
|
||||
This package provides a minimalist boot loader which allows verifying
|
||||
signatures of other UEFI binaries against either the Secure Boot DB/DBX or
|
||||
|
37
debian/generate_dbx_list
vendored
37
debian/generate_dbx_list
vendored
@ -16,12 +16,39 @@ ARCH=$1
|
||||
IN=$2
|
||||
OUT=$3
|
||||
|
||||
DEBIAN_UUID="fa31923d-6047-40bf-81d0-e63edefcf194"
|
||||
|
||||
# This needs to be fixed to make builds reproducible, of course. If
|
||||
# you're deriving from Debian, please generate your own.
|
||||
UUID="$DEBIAN_UUID"
|
||||
|
||||
rm -f $OUT
|
||||
for HASH in $(grep -E "[[:xdigit:]]{32} $ARCH" < $IN | \
|
||||
awk '{print $1}' | sort | uniq); do
|
||||
echo " Adding $HASH to dbx list"
|
||||
efisiglist -o $OUT -a -h $HASH
|
||||
done
|
||||
if [ -x /usr/bin/efisiglist ] ; then
|
||||
# Older versions of the pesign package included the efisiglist
|
||||
# utility. If we have that, use it.
|
||||
for HASH in $(grep -E "[[:xdigit:]]{32} $ARCH" < $IN | \
|
||||
awk '{print $1}' | sort | uniq); do
|
||||
echo " Adding $HASH to dbx list"
|
||||
efisiglist -o $OUT -a -h $HASH
|
||||
done
|
||||
else
|
||||
# It appears we don't have efisiglist, so use efisecdb
|
||||
# instead. It's a little more awkward to drive.
|
||||
INTMP="" # First pass
|
||||
for HASH in $(grep -E "[[:xdigit:]]{32} $ARCH" < $IN | \
|
||||
awk '{print $1}' | sort | uniq); do
|
||||
echo " Adding $HASH to dbx list"
|
||||
efisecdb -g "$UUID" -a -t sha256 -h $HASH $INTMP -o $OUT
|
||||
|
||||
# Subsequent passes need to read the previous output as input
|
||||
# each time, and won't overwrite the output.
|
||||
mv -f $OUT $OUT.in
|
||||
INTMP="-i $OUT.in"
|
||||
done
|
||||
if [ -f $OUT.in ]; then
|
||||
mv -f $OUT.in $OUT
|
||||
fi
|
||||
fi
|
||||
|
||||
# If we have an empty hashes file, create an empty DBX file
|
||||
touch $OUT
|
||||
|
42
debian/patches/0001-sbat-Add-grub.peimage-2-to-latest-CVE-2024-2312.patch
vendored
Normal file
42
debian/patches/0001-sbat-Add-grub.peimage-2-to-latest-CVE-2024-2312.patch
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
From 63edf92f8ae11b884bc7d24aecb8229cbc4ae014 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Andres Klode <julian.klode@canonical.com>
|
||||
Date: Fri, 5 Apr 2024 21:57:07 +0200
|
||||
Subject: [PATCH 1/2] sbat: Add grub.peimage,2 to latest (CVE-2024-2312)
|
||||
|
||||
Add the previous latest level to the switch for automatic.
|
||||
|
||||
Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
|
||||
---
|
||||
include/sbat_var_defs.h | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/include/sbat_var_defs.h b/include/sbat_var_defs.h
|
||||
index f8cba029..04d708f2 100644
|
||||
--- a/include/sbat_var_defs.h
|
||||
+++ b/include/sbat_var_defs.h
|
||||
@@ -47,6 +47,8 @@
|
||||
#define SBAT_VAR_AUTOMATIC_REVOCATIONS "shim,2\ngrub,3\n"
|
||||
#elif SBAT_AUTOMATIC_DATE == 2023012900
|
||||
#define SBAT_VAR_AUTOMATIC_REVOCATIONS "shim,2\ngrub,3\ngrub.debian,4\n"
|
||||
+#elif SBAT_AUTOMATIC_DATE == 2024010900
|
||||
+#define SBAT_VAR_AUTOMATIC_REVOCATIONS "shim,4\ngrub,3\ngrub.debian,4\n"
|
||||
#else
|
||||
#error "Unknown SBAT_AUTOMATIC_DATE"
|
||||
#endif /* SBAT_AUTOMATIC_DATE == */
|
||||
@@ -56,10 +58,10 @@
|
||||
SBAT_VAR_AUTOMATIC_REVOCATIONS
|
||||
|
||||
/*
|
||||
- * Revocations for January 2024 shim CVEs
|
||||
+ * Revocations for January 2024 shim CVEs + Debian/Ubuntu (peimage) CVE-2024-2312
|
||||
*/
|
||||
-#define SBAT_VAR_LATEST_DATE "2024010900"
|
||||
-#define SBAT_VAR_LATEST_REVOCATIONS "shim,4\ngrub,3\ngrub.debian,4\n"
|
||||
+#define SBAT_VAR_LATEST_DATE "2024040500"
|
||||
+#define SBAT_VAR_LATEST_REVOCATIONS "shim,4\ngrub,3\ngrub.debian,4\ngrub.peimage,2\n"
|
||||
#define SBAT_VAR_LATEST \
|
||||
SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_LATEST_DATE "\n" \
|
||||
SBAT_VAR_LATEST_REVOCATIONS
|
||||
--
|
||||
2.39.2
|
||||
|
47
debian/patches/0002-sbat-Also-bump-latest-for-grub-4-and-to-todays-date.patch
vendored
Normal file
47
debian/patches/0002-sbat-Also-bump-latest-for-grub-4-and-to-todays-date.patch
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
From 3e1394e8e6fd0071a69196230f991612a960c154 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Andres Klode <julian.klode@canonical.com>
|
||||
Date: Tue, 9 Apr 2024 18:55:12 +0200
|
||||
Subject: [PATCH 2/2] sbat: Also bump latest for grub,4 (and to todays date)
|
||||
|
||||
Back in January we decided to bump the SBAT level for the shim
|
||||
CVE without bumping the grub level for the previous NTFS issues
|
||||
- CVE-2023-4692 CVE-2023-4693 - as not every vendor was signing
|
||||
the ntfs module.
|
||||
|
||||
Catch up on this revocation to ensure it doesn't get lost. Doing
|
||||
so also allows us to remove the grub.debian,4 revocation as this
|
||||
happened before grub,4 and hence is obsolete.
|
||||
|
||||
Also bump the date of the sbat variable to today's. Don't copy
|
||||
the April 5 one to a previous selection, as it wasn't shipped
|
||||
to anyone.
|
||||
|
||||
Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
|
||||
---
|
||||
include/sbat_var_defs.h | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/include/sbat_var_defs.h b/include/sbat_var_defs.h
|
||||
index 04d708f2..5c7115b9 100644
|
||||
--- a/include/sbat_var_defs.h
|
||||
+++ b/include/sbat_var_defs.h
|
||||
@@ -58,10 +58,13 @@
|
||||
SBAT_VAR_AUTOMATIC_REVOCATIONS
|
||||
|
||||
/*
|
||||
- * Revocations for January 2024 shim CVEs + Debian/Ubuntu (peimage) CVE-2024-2312
|
||||
+ * Revocations for:
|
||||
+ * - January 2024 shim CVEs
|
||||
+ * - October 2023 grub CVEs
|
||||
+ * - Debian/Ubuntu (peimage) CVE-2024-2312
|
||||
*/
|
||||
-#define SBAT_VAR_LATEST_DATE "2024040500"
|
||||
-#define SBAT_VAR_LATEST_REVOCATIONS "shim,4\ngrub,3\ngrub.debian,4\ngrub.peimage,2\n"
|
||||
+#define SBAT_VAR_LATEST_DATE "2024040900"
|
||||
+#define SBAT_VAR_LATEST_REVOCATIONS "shim,4\ngrub,4\ngrub.peimage,2\n"
|
||||
#define SBAT_VAR_LATEST \
|
||||
SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_LATEST_DATE "\n" \
|
||||
SBAT_VAR_LATEST_REVOCATIONS
|
||||
--
|
||||
2.39.2
|
||||
|
79
debian/patches/Enable-NX.patch
vendored
79
debian/patches/Enable-NX.patch
vendored
@ -1,79 +0,0 @@
|
||||
commit 7c7642530fab73facaf3eac233cfbce29e10b0ef
|
||||
Author: Peter Jones <pjones@redhat.com>
|
||||
Date: Thu Nov 17 12:31:31 2022 -0500
|
||||
|
||||
Enable the NX compatibility flag by default.
|
||||
|
||||
Currently by default, when we build shim we do not set the PE
|
||||
NX-compatibility DLL Characteristic flag. This signifies to the
|
||||
firmware that shim (including the components it loads) is not prepared
|
||||
for several related firmware changes:
|
||||
|
||||
- non-executable stack
|
||||
- non-executable pages from AllocatePages()/AllocatePool()/etc.
|
||||
- non-writable 0 page (not strictly related but some firmware will be
|
||||
transitioning at the same time)
|
||||
- the need to use the UEFI 2.10 Memory Attribute Protocol to set page
|
||||
permissions.
|
||||
|
||||
This patch changes that default to be enabled by default. Distributors
|
||||
of shim will need to ensure that either their builds disable this bit
|
||||
(using "post-process-pe -N"), or that the bootloaders and kernels you
|
||||
support loading are all compliant with this change. A new make
|
||||
variable, POST_PROCESS_PE_FLAGS, has been added to simplify doing so.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
|
||||
diff --git a/BUILDING b/BUILDING
|
||||
index 3b2e85d3..17cd98d3 100644
|
||||
--- a/BUILDING
|
||||
+++ b/BUILDING
|
||||
@@ -78,6 +78,9 @@ Variables you could set to customize the build:
|
||||
- OSLABEL
|
||||
This is the label that will be put in BOOT$(EFI_ARCH).CSV for your OS.
|
||||
By default this is the same value as EFIDIR .
|
||||
+- POST_PROCESS_PE_FLAGS
|
||||
+ This allows you to add flags to the invocation of "post-process-pe", for
|
||||
+ example to disable the NX compatibility flag.
|
||||
|
||||
Vendor SBAT data:
|
||||
It will sometimes be requested by reviewers that a build includes extra
|
||||
diff --git a/Make.defaults b/Make.defaults
|
||||
index c46164a3..9af89f4e 100644
|
||||
--- a/Make.defaults
|
||||
+++ b/Make.defaults
|
||||
@@ -139,6 +139,8 @@ CFLAGS = $(FEATUREFLAGS) \
|
||||
$(INCLUDES) \
|
||||
$(DEFINES)
|
||||
|
||||
+POST_PROCESS_PE_FLAGS =
|
||||
+
|
||||
ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined)
|
||||
DEFINES += -DOVERRIDE_SECURITY_POLICY
|
||||
endif
|
||||
diff --git a/Makefile b/Makefile
|
||||
index a9202f46..f0f53f8f 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -255,7 +255,7 @@ endif
|
||||
-j .rela* -j .dyn -j .reloc -j .eh_frame \
|
||||
-j .vendor_cert -j .sbat -j .sbatlevel \
|
||||
$(FORMAT) $< $@
|
||||
- ./post-process-pe -vv $@
|
||||
+ ./post-process-pe -vv $(POST_PROCESS_PE_FLAGS) $@
|
||||
|
||||
ifneq ($(origin ENABLE_SHIM_HASH),undefined)
|
||||
%.hash : %.efi
|
||||
diff --git a/post-process-pe.c b/post-process-pe.c
|
||||
index de8f4a38..f39fdddf 100644
|
||||
--- a/post-process-pe.c
|
||||
+++ b/post-process-pe.c
|
||||
@@ -42,7 +42,7 @@ static int verbosity;
|
||||
0; \
|
||||
})
|
||||
|
||||
-static bool set_nx_compat = false;
|
||||
+static bool set_nx_compat = true;
|
||||
|
||||
typedef uint8_t UINT8;
|
||||
typedef uint16_t UINT16;
|
@ -1,104 +0,0 @@
|
||||
From 657b2483ca6e9fcf2ad8ac7ee577ff546d24c3aa Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Mon, 5 Dec 2022 17:57:36 -0500
|
||||
Subject: [PATCH] Make sbat_var.S parse right with buggy gcc/binutils
|
||||
|
||||
In https://github.com/rhboot/shim/issues/533 , iokomin noticed that
|
||||
gas in binutils before 2.36 appears to be incorrectly concatenating
|
||||
string literals in '.asciz' directives, including an extra NUL character
|
||||
in between the strings, and this will cause us to incorrectly parse the
|
||||
.sbatlevel section in shim binaries.
|
||||
|
||||
This patch adds test cases that will cause the build to fail if this has
|
||||
happened, as well as changing sbat_var.S to to use '.ascii' and '.byte'
|
||||
to construct the data, rather than using '.asciz'.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
---
|
||||
include/test.mk | 2 +-
|
||||
sbat_var.S | 6 ++++--
|
||||
test-sbat.c | 32 ++++++++++++++++++++++++++++++++
|
||||
3 files changed, 37 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/include/test.mk b/include/test.mk
|
||||
index c0e24095..c37b8446 100644
|
||||
--- a/include/test.mk
|
||||
+++ b/include/test.mk
|
||||
@@ -92,7 +92,7 @@ test-mock-variables: CFLAGS+=-DHAVE_SHIM_LOCK_GUID
|
||||
test-mok-mirror_FILES = mok.c globals.c tpm.c lib/guid.c lib/variables.c mock-variables.c
|
||||
test-mok-mirror: CFLAGS+=-DHAVE_START_IMAGE -DHAVE_SHIM_LOCK_GUID
|
||||
|
||||
-test-sbat_FILES = csv.c lib/variables.c lib/guid.c sbat_var.S
|
||||
+test-sbat_FILES = csv.c lib/variables.c lib/guid.c sbat_var.S mock-variables.c
|
||||
test-sbat :: CFLAGS+=-DHAVE_GET_VARIABLE -DHAVE_GET_VARIABLE_ATTR -DHAVE_SHIM_LOCK_GUID
|
||||
|
||||
test-str_FILES = lib/string.c
|
||||
diff --git a/sbat_var.S b/sbat_var.S
|
||||
index a115077a..2a813a40 100644
|
||||
--- a/sbat_var.S
|
||||
+++ b/sbat_var.S
|
||||
@@ -14,7 +14,9 @@ sbat_var_payload_header:
|
||||
.Lsbat_var_payload_header_end:
|
||||
.balign 1, 0
|
||||
.Lsbat_var_previous:
|
||||
- .asciz SBAT_VAR_PREVIOUS
|
||||
+ .ascii SBAT_VAR_PREVIOUS
|
||||
+ .byte 0
|
||||
.balign 1, 0
|
||||
.Lsbat_var_latest:
|
||||
- .asciz SBAT_VAR_LATEST
|
||||
+ .ascii SBAT_VAR_LATEST
|
||||
+ .byte 0
|
||||
diff --git a/test-sbat.c b/test-sbat.c
|
||||
index 72bebe7a..65bc6a84 100644
|
||||
--- a/test-sbat.c
|
||||
+++ b/test-sbat.c
|
||||
@@ -1107,6 +1107,36 @@ test_preserve_sbat_uefi_variable_bad_short(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int
|
||||
+test_sbat_var_asciz(void)
|
||||
+{
|
||||
+ EFI_STATUS status;
|
||||
+ char buf[1024] = "";
|
||||
+ UINT32 attrs = 0;
|
||||
+ UINTN size = sizeof(buf);
|
||||
+ char expected[] = SBAT_VAR_PREVIOUS;
|
||||
+
|
||||
+ status = set_sbat_uefi_variable();
|
||||
+ if (status != EFI_SUCCESS)
|
||||
+ return -1;
|
||||
+
|
||||
+ status = RT->GetVariable(SBAT_VAR_NAME, &SHIM_LOCK_GUID, &attrs, &size, buf);
|
||||
+ if (status != EFI_SUCCESS)
|
||||
+ return -1;
|
||||
+
|
||||
+ /*
|
||||
+ * this should be enough to get past "sbat,", which handles the
|
||||
+ * first error.
|
||||
+ */
|
||||
+ if (size < (strlen(SBAT_VAR_SIG) + 2) || size != strlen(expected))
|
||||
+ return -1;
|
||||
+
|
||||
+ if (strncmp(expected, buf, size) != 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@@ -1155,6 +1185,8 @@ main(void)
|
||||
test(test_preserve_sbat_uefi_variable_version_older);
|
||||
test(test_preserve_sbat_uefi_variable_version_olderlonger);
|
||||
|
||||
+ test(test_sbat_var_asciz);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.30.2
|
||||
|
4
debian/patches/series
vendored
4
debian/patches/series
vendored
@ -1,2 +1,2 @@
|
||||
Make-sbat_var.S-parse-right-with-buggy-gcc-binutils.patch
|
||||
Enable-NX.patch
|
||||
0001-sbat-Add-grub.peimage-2-to-latest-CVE-2024-2312.patch
|
||||
0002-sbat-Also-bump-latest-for-grub-4-and-to-todays-date.patch
|
||||
|
16
debian/rules
vendored
16
debian/rules
vendored
@ -48,6 +48,11 @@ COMMON_OPTIONS += \
|
||||
CC=$(DEB_HOST_GNU_TYPE)-gcc-12 \
|
||||
$(NULL)
|
||||
|
||||
# Force shim to use the latest revocations by default to block some
|
||||
# older grub / peimage issues. This is:
|
||||
# "shim,4\ngrub,4\ngrub.peimage,2\n"
|
||||
COMMON_OPTIONS += SBAT_AUTOMATIC_DATE=2024010900
|
||||
|
||||
$(DBX_LIST): $(DBX_HASHES)
|
||||
./debian/generate_dbx_list $(EFI_ARCH) $< $@
|
||||
|
||||
@ -65,7 +70,9 @@ $(SBAT_DATA): $(SBAT_IN)
|
||||
|
||||
override_dh_auto_clean:
|
||||
dh_auto_clean -- MAKELEVEL=0
|
||||
rm -f $(DBX_LIST) $(SBAT_DATA) sbat.*.csv BOOT*.CSV test-csv test-sbat test-str
|
||||
rm -f $(DBX_LIST) $(SBAT_DATA) sbat.*.csv BOOT*.CSV
|
||||
rm -f test-csv test-sbat test-str test-load-options
|
||||
rm -f test-mock-variables test-mok-mirror test-pe-relocate test-pe-util
|
||||
|
||||
override_dh_auto_build: $(DBX_LIST) $(SBAT_DATA)
|
||||
dh_auto_build -- INSTALL=install $(COMMON_OPTIONS)
|
||||
@ -81,7 +88,14 @@ override_dh_auto_install:
|
||||
# And remove the extra removable-media copy of shim too, it's
|
||||
# not needed for our build and causes debhelper to complain
|
||||
rm -f debian/tmp/boot/efi/EFI/BOOT/BOOT*.EFI
|
||||
|
||||
install -m 644 $(cert) debian/shim-unsigned/usr/share/shim
|
||||
|
||||
# Generate the template packages that we'll use for SB signing later
|
||||
./debian/signing-template.generate
|
||||
|
||||
# Log some useful things about the build here
|
||||
./debian/check_nx shim*.efi
|
||||
sha256sum *.efi
|
||||
|
||||
generate-gnu-efi:
|
||||
|
3
debian/salsa-ci.yml
vendored
Normal file
3
debian/salsa-ci.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
include:
|
||||
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
|
1
debian/shim-unsigned.dirs
vendored
Normal file
1
debian/shim-unsigned.dirs
vendored
Normal file
@ -0,0 +1 @@
|
||||
/usr/share/shim
|
54
debian/tests/01_sanity_tests.py
vendored
Executable file
54
debian/tests/01_sanity_tests.py
vendored
Executable file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# UEFI Shim sanity checks for tests
|
||||
#
|
||||
# Copyright (C) 2019 Canonical, Ltd.
|
||||
# Author: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from uefi_tests_base import UEFITestsBase
|
||||
|
||||
|
||||
class SanityTests(UEFITestsBase):
|
||||
'''
|
||||
Sanity checks for uefi tests
|
||||
'''
|
||||
|
||||
def testArchitectureSuffixes(self):
|
||||
"""Ensure sanity of our concept of architecture suffixes for UEFI"""
|
||||
|
||||
machine = subprocess.check_output(['uname', '-m']).rstrip().decode('utf-8')
|
||||
if machine == 'x86_64':
|
||||
self.assertEqual('x64', self.arch_suffix)
|
||||
self.assertEqual('x86_64-efi', self.grub_arch)
|
||||
self.assertEqual('qemu-system-x86_64', self.qemu_arch)
|
||||
elif machine == 'aarch64':
|
||||
self.assertEqual('aa64', self.arch_suffix)
|
||||
self.assertEqual('arm64-efi', self.grub_arch)
|
||||
self.assertEqual('qemu-system-aarch64', self.qemu_arch)
|
||||
|
||||
def testQemuAvailable(self):
|
||||
"""Ensure QEMU is available for this architecture"""
|
||||
try:
|
||||
out = subprocess.run([self.qemu_arch, '-version'], stdout=None)
|
||||
out.check_returncode()
|
||||
except:
|
||||
raise UEFINotAvailable(feature="qemu", arch=self.arch_machine,
|
||||
details="%s failed to run" % self.qemu_arch)
|
||||
|
||||
|
||||
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))
|
91
debian/tests/05_signature_tests.py
vendored
Executable file
91
debian/tests/05_signature_tests.py
vendored
Executable file
@ -0,0 +1,91 @@
|
||||
#
|
||||
# UEFI signature validation
|
||||
#
|
||||
# Copyright (C) 2019 Canonical, Ltd.
|
||||
# Author: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
import tempfile
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from uefi_tests_base import UEFITestsBase
|
||||
|
||||
|
||||
class TestSignatures(UEFITestsBase):
|
||||
"""
|
||||
Validate UEFI signatures for common problems
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(klass):
|
||||
UEFITestsBase.setUpClass()
|
||||
|
||||
|
||||
def testInstalledGrubIsSigned(self):
|
||||
"""Check that the GRUB copy we installed is correctly signed"""
|
||||
installed_grub_file = Path(self.signed_grub_path)
|
||||
self.assertTrue(installed_grub_file.exists())
|
||||
signed_out = subprocess.run(['sbverify', '--list', self.signed_grub_path],
|
||||
stdout=subprocess.PIPE)
|
||||
self.assertIn(b'image signature issuers:', signed_out.stdout)
|
||||
|
||||
def testGrubSignatureValid(self):
|
||||
return
|
||||
"""Ensure the installed GRUB binary from packaging is signed with the expected key"""
|
||||
self.assertSignatureOK(self.ca, self.signed_grub_path)
|
||||
|
||||
def testInstalledShimIsSigned(self):
|
||||
"""Check that the installed shim is signed"""
|
||||
installed_shim_file = Path(self.signed_shim_path)
|
||||
self.assertTrue(installed_shim_file.exists())
|
||||
signed_out = subprocess.run(['sbverify', '--list', self.signed_shim_path],
|
||||
stdout=subprocess.PIPE)
|
||||
self.assertIn(b'image signature issuers:', signed_out.stdout)
|
||||
|
||||
def testHaveSignedShimOnESP(self):
|
||||
"""Verify that packaging has provided a signed shim"""
|
||||
return
|
||||
signed_shim_file = Path(self.installed_shim)
|
||||
self.assertTrue(signed_shim_file.exists())
|
||||
|
||||
def testSignaturesExist(self):
|
||||
"""Validate that a binary has non-zero signatures"""
|
||||
unsigned_out = subprocess.run(['sbverify', '--list', self.unsigned_shim_path],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
self.assertIn(b'No signature table present', unsigned_out.stderr)
|
||||
signed_out = subprocess.run(['sbverify', '--list', self.signed_shim_path],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
self.assertIn(b'image signature issuers:', signed_out.stdout)
|
||||
|
||||
def testSignatureIsReplayable(self):
|
||||
"""Attest that signature is retrievable from a binary and can be replayed"""
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
subprocess.call(['sbattach',
|
||||
'--detach', os.path.join(tmpdirname, 'sig.pkcs7'),
|
||||
self.signed_shim_path])
|
||||
pkcs7_certs = subprocess.run(['openssl', 'pkcs7',
|
||||
'-inform', 'der',
|
||||
'-in', os.path.join(tmpdirname, 'sig.pkcs7'),
|
||||
'-print_certs'],
|
||||
stdout=subprocess.PIPE)
|
||||
with open(os.path.join(tmpdirname, 'out.crt'), 'ab+') as certstore:
|
||||
certstore.write(pkcs7_certs.stdout)
|
||||
self.assertSignatureOK(os.path.join(tmpdirname, 'out.crt'), self.signed_shim_path)
|
||||
|
||||
|
||||
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))
|
51
debian/tests/10_uefi_boot_tests.py
vendored
Executable file
51
debian/tests/10_uefi_boot_tests.py
vendored
Executable file
@ -0,0 +1,51 @@
|
||||
#
|
||||
# UEFI boot testing
|
||||
#
|
||||
# Copyright (C) 2019 Canonical, Ltd.
|
||||
# Author: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from uefi_tests_base import UEFITestsBase, UEFINotAvailable, UEFIVirtualMachine
|
||||
|
||||
|
||||
class UEFIBootTests(UEFITestsBase):
|
||||
"""
|
||||
Validate UEFI signatures for common problems
|
||||
"""
|
||||
@classmethod
|
||||
def setUpClass(klass):
|
||||
UEFITestsBase.setUpClass()
|
||||
klass.base_image = UEFIVirtualMachine(arch=klass.image_arch)
|
||||
#klass.base_image.prepare()
|
||||
|
||||
def testCanary(self):
|
||||
"""Validate that a control/canary (unchanged) image boots fine"""
|
||||
canary = UEFIVirtualMachine(self.base_image)
|
||||
canary.run()
|
||||
self.assertBoots(canary)
|
||||
|
||||
def testNewShim(self):
|
||||
"""Validate that a new SHIM binary on the image will boot"""
|
||||
new_shim = UEFIVirtualMachine(self.base_image)
|
||||
new_shim.update(src='/usr/lib/shim/shimx64.efi.signed', dst='/boot/efi/EFI/debian/shimx64.efi')
|
||||
new_shim.update(src='/usr/lib/shim/shimx64.efi.signed', dst='/boot/efi/EFI/BOOT/BOOTX64.efi')
|
||||
new_shim.run()
|
||||
self.assertBoots(new_shim)
|
||||
|
||||
|
||||
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))
|
47
debian/tests/control
vendored
Normal file
47
debian/tests/control
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
Test-Command: python3 debian/tests/01_sanity_tests.py
|
||||
Depends: @,
|
||||
qemu-system-arm [arm64],
|
||||
qemu-system-x86 [amd64],
|
||||
lsb-release,
|
||||
python3,
|
||||
wget,
|
||||
openssl,
|
||||
Restrictions: allow-stderr, needs-root, isolation-machine
|
||||
Features: test-name=sanity
|
||||
|
||||
Test-Command: python3 debian/tests/05_signature_tests.py
|
||||
Depends: @,
|
||||
sbsigntool,
|
||||
grub-efi-arm64-signed [arm64],
|
||||
grub-efi-amd64-signed [amd64],
|
||||
shim-signed [amd64],
|
||||
shim-signed [arm64],
|
||||
lsb-release,
|
||||
python3,
|
||||
wget,
|
||||
openssl,
|
||||
Restrictions: allow-stderr, needs-root, isolation-machine
|
||||
Features: test-name=signatures
|
||||
|
||||
Test-Command: python3 debian/tests/10_uefi_boot_tests.py
|
||||
Depends: @,
|
||||
autopkgtest,
|
||||
genisoimage,
|
||||
qemu-utils,
|
||||
sbsigntool,
|
||||
qemu-system-arm [arm64],
|
||||
qemu-system-x86 [amd64],
|
||||
ovmf [amd64],
|
||||
qemu-efi-aarch64 [arm64],
|
||||
grub-efi-arm64-signed [arm64],
|
||||
grub-efi-amd64-signed [amd64],
|
||||
shim-signed [amd64],
|
||||
shim-signed [arm64],
|
||||
lsb-release,
|
||||
python3,
|
||||
wget,
|
||||
openssl,
|
||||
ca-certificates,
|
||||
distro-info,
|
||||
Restrictions: allow-stderr, needs-root, isolation-machine
|
||||
Features: test-name=boot-test
|
261
debian/tests/uefi_tests_base.py
vendored
Normal file
261
debian/tests/uefi_tests_base.py
vendored
Normal file
@ -0,0 +1,261 @@
|
||||
#
|
||||
# UEFI validation/integration tests
|
||||
#
|
||||
# Copyright (C) 2019 Canonical, Ltd.
|
||||
# Author: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
import math
|
||||
import subprocess
|
||||
import tempfile
|
||||
from time import sleep
|
||||
import unittest
|
||||
|
||||
|
||||
class UEFINotAvailable(Exception):
|
||||
"""Exception class for unavailable UEFI features"""
|
||||
def __init__(self, feature=None, arch=None, details=None):
|
||||
self.message = "UEFI is not available"
|
||||
if arch and feature:
|
||||
self.message = "%s is not available on %s" % (feature, arch)
|
||||
elif feature:
|
||||
self.message = "%s is not available" % feature
|
||||
if details:
|
||||
self.message = self.message + ": %s" % details
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.message)
|
||||
|
||||
class UEFITestsBase(unittest.TestCase):
|
||||
'''
|
||||
Common functionality for shim test cases
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def setUpClass(klass):
|
||||
klass.arch_machine = os.uname().machine
|
||||
klass.arch_suffix = ''
|
||||
klass.grub_arch = ''
|
||||
klass.qemu_arch = ''
|
||||
if klass.arch_machine == 'x86_64':
|
||||
klass.image_arch = 'amd64'
|
||||
klass.arch_suffix = 'x64'
|
||||
klass.grub_arch = 'x86_64-efi'
|
||||
klass.qemu_arch = 'qemu-system-x86_64'
|
||||
elif klass.arch_machine == 'aarch64':
|
||||
klass.image_arch = 'arm64'
|
||||
klass.arch_suffix = 'aa64'
|
||||
klass.grub_arch = 'arm64-efi'
|
||||
klass.qemu_arch = 'qemu-system-aarch64'
|
||||
else:
|
||||
raise UEFINotAvailable(feature='any UEFI Shim features', arch=klass.arch_machine)
|
||||
|
||||
# Base paths for the ESP.
|
||||
klass.uefi_base_dir = os.path.join('/', 'boot', 'efi', 'EFI')
|
||||
klass.uefi_boot_dir = os.path.join(klass.uefi_base_dir, 'BOOT')
|
||||
klass.uefi_install_dir = os.path.join(klass.uefi_base_dir, 'debian')
|
||||
|
||||
# CAs for signature validation (not yet)
|
||||
# klass.ca = os.path.join('/usr/share/grub', 'debian-uefi-ca.crt')
|
||||
|
||||
# Shim paths
|
||||
klass.shim_pkg_dir = os.path.join('/', 'usr', 'lib', 'shim')
|
||||
klass.unsigned_shim_path = os.path.join(klass.shim_pkg_dir, 'shim%s.efi' % klass.arch_suffix)
|
||||
klass.signed_shim_path = os.path.join(klass.shim_pkg_dir, 'shim%s.efi.signed' % klass.arch_suffix)
|
||||
klass.installed_shim = os.path.join(klass.uefi_install_dir, 'shim%s.efi' % klass.arch_suffix)
|
||||
klass.removable_shim = os.path.join(klass.uefi_boot_dir, 'boot%s.efi' % klass.arch_suffix)
|
||||
|
||||
# GRUB paths
|
||||
klass.grub_pkg_dir = os.path.join('/', 'usr', 'lib', 'grub', "%s-signed" % klass.grub_arch)
|
||||
klass.signed_grub_path = os.path.join(klass.grub_pkg_dir, 'grub%s.efi.signed' % klass.arch_suffix)
|
||||
klass.installed_grub = os.path.join(klass.uefi_install_dir, 'grub%s.efi' % klass.arch_suffix)
|
||||
|
||||
# OMVF paths
|
||||
if klass.arch_machine == 'x86_64':
|
||||
klass.uefi_code_path = '/usr/share/OVMF/OVMF_CODE_4M.ms.fd'
|
||||
klass.uefi_vars_path = '/usr/share/OVMF/OVMF_VARS_4M.ms.fd'
|
||||
klass.uefi_qemu_extra = [ '-machine', 'q35,smm=on' ]
|
||||
elif klass.arch_machine == 'aarch64':
|
||||
klass.uefi_code_path = '/usr/share/AAVMF/AAVMF_CODE.fd'
|
||||
klass.uefi_vars_path = '/usr/share/AAVMF/AAVMF_VARS.fd'
|
||||
klass.uefi_qemu_extra = []
|
||||
|
||||
subprocess.run(['modprobe', 'nbd'])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(klass):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
|
||||
#
|
||||
# Internal implementation details
|
||||
#
|
||||
|
||||
@classmethod
|
||||
def poll_text(klass, logpath, string, timeout=50):
|
||||
'''Poll log file for a given string with a timeout.
|
||||
|
||||
Timeout is given in deciseconds.
|
||||
'''
|
||||
log = ''
|
||||
while timeout > 0:
|
||||
if os.path.exists(logpath):
|
||||
break
|
||||
timeout -= 1
|
||||
sleep(0.1)
|
||||
assert timeout > 0, 'Timed out waiting for file %s to appear' % logpath
|
||||
|
||||
with open(logpath) as f:
|
||||
while timeout > 0:
|
||||
line = f.readline()
|
||||
if line:
|
||||
log += line
|
||||
if string in line:
|
||||
break
|
||||
continue
|
||||
timeout -= 1
|
||||
sleep(0.1)
|
||||
|
||||
assert timeout > 0, 'Timed out waiting for "%s":\n------------\n%s\n-------\n' % (string, log)
|
||||
|
||||
|
||||
def assertSignatureOK(self, expected_signature, binary):
|
||||
result = subprocess.check_call(['sbverify', '--cert', expected_signature, binary])
|
||||
self.assertEquals(0, result)
|
||||
|
||||
|
||||
def assertBoots(self, vm=None):
|
||||
'''Assert that the VM is booted and ready for use'''
|
||||
self.assertTrue(vm.ready())
|
||||
|
||||
|
||||
DEFAULT_METADATA = 'instance-id: nocloud\nlocal-hostname: autopkgtest\n'
|
||||
|
||||
DEFAULT_USERDATA = """#cloud-config
|
||||
locale: en_US.UTF-8
|
||||
password: debian
|
||||
chpasswd: { expire: False }
|
||||
ssh_pwauth: True
|
||||
manage_etc_hosts: True
|
||||
runcmd:
|
||||
- (while [ ! -e /var/lib/cloud/instance/boot-finished ]; do sleep 1; done;
|
||||
touch /TESTOK;
|
||||
shutdown -P now) &
|
||||
"""
|
||||
|
||||
#
|
||||
# VM management tools
|
||||
#
|
||||
class UEFIVirtualMachine(UEFITestsBase):
|
||||
|
||||
def __init__(self, base=None, arch=None):
|
||||
self.autopkgtest_dir = tempfile.TemporaryDirectory()
|
||||
os.makedirs(os.path.join(self.autopkgtest_dir.name, 'img'))
|
||||
self.arch = arch
|
||||
release = subprocess.run(['lsb_release','-c','-s'], capture_output=True, check=True)
|
||||
self.release = release.stdout.strip().decode('utf-8')
|
||||
release_number = subprocess.run(['lsb_release','-r','-s'], capture_output=True, check=True).stdout.strip().decode('utf-8')
|
||||
self.release_number = None
|
||||
try:
|
||||
self.release_number = int(math.floor(float(release_number)))
|
||||
except:
|
||||
if(self.release == 'sid'):
|
||||
self.release_number = 'sid'
|
||||
else:
|
||||
alias = subprocess.run(['distro-info','--alias', self.release], capture_output=True, check=True).stdout.strip().decode('utf-8')
|
||||
number_distro = subprocess.run(['distro-info','-r', '--%s' % (alias)], capture_output=True, check=True).stdout.strip().decode('utf-8')
|
||||
self.release_number = int(math.floor(float(number_distro)))
|
||||
self.path = tempfile.mkstemp(dir=self.autopkgtest_dir.name)[1]
|
||||
if not base:
|
||||
subprocess.run(['wget',
|
||||
'https://cloud.debian.org/images/cloud/%s/daily/latest/debian-%s-genericcloud-%s-daily.qcow2'
|
||||
% (self.release, self.release_number, self.arch),
|
||||
'-O', '%s/base.img' % self.autopkgtest_dir.name], check = True)
|
||||
else:
|
||||
self.arch = base.arch
|
||||
shutil.copy(base.path, os.path.join(self.autopkgtest_dir.name, 'base.img'))
|
||||
shutil.copy(os.path.join(self.autopkgtest_dir.name, 'base.img'), self.path)
|
||||
shutil.copy("%s" % self.uefi_vars_path, "%s.VARS.fd" % self.path)
|
||||
|
||||
def _mount(self):
|
||||
subprocess.run(['qemu-nbd', '--connect=/dev/nbd0', self.path])
|
||||
# nbd doesn't show instantly...
|
||||
sleep(1)
|
||||
subprocess.run(['mount', '/dev/nbd0p1', os.path.join(self.autopkgtest_dir.name, 'img')])
|
||||
subprocess.run(['mount', '/dev/nbd0p15', os.path.join(self.autopkgtest_dir.name, 'img', 'boot/efi')])
|
||||
|
||||
def _unmount(self):
|
||||
subprocess.run(['umount', '/dev/nbd0p15'])
|
||||
subprocess.run(['umount', '/dev/nbd0p1'])
|
||||
subprocess.run(['qemu-nbd', '--disconnect', '/dev/nbd0'])
|
||||
|
||||
def prepare(self):
|
||||
with open(os.path.join(self.autopkgtest_dir.name, 'meta-data'), 'w') as f:
|
||||
f.write(DEFAULT_METADATA)
|
||||
with open(os.path.join(self.autopkgtest_dir.name, 'user-data'), 'w') as f:
|
||||
f.write(DEFAULT_USERDATA)
|
||||
with open(os.path.join(self.autopkgtest_dir.name, 'network-config'), 'w') as f:
|
||||
f.write('')
|
||||
|
||||
subprocess.run(['genisoimage', '-output', 'cloud-init.seed',
|
||||
'-volid', 'cidata', '-joliet', '-rock',
|
||||
'-quiet', 'user-data', 'meta-data', 'network-config'],
|
||||
cwd=self.autopkgtest_dir.name)
|
||||
|
||||
def list(self, path='/etc/'):
|
||||
self._mount()
|
||||
subprocess.run(['ls', '-l', os.path.join(self.autopkgtest_dir.name, 'img', path)])
|
||||
self._unmount()
|
||||
|
||||
def update(self, src=None, dst=None):
|
||||
self._mount()
|
||||
try:
|
||||
os.makedirs(os.path.join(self.autopkgtest_dir.name, 'img', os.path.dirname(dst)))
|
||||
except FileExistsError:
|
||||
pass
|
||||
shutil.copy(src, os.path.join(self.autopkgtest_dir.name, 'img', dst))
|
||||
self._unmount()
|
||||
|
||||
def run(self):
|
||||
self.prepare()
|
||||
# start qemu-system-$arch, output log to serial and capture to variable
|
||||
subprocess.run([self.qemu_arch] + self.uefi_qemu_extra + [
|
||||
'-m', '1024', '-nographic',
|
||||
'-serial', 'mon:stdio',
|
||||
'-netdev', 'user,id=network0',
|
||||
'-device', 'virtio-net-pci,netdev=network0,mac=52:54:00:12:34:56',
|
||||
'-drive', 'file=%s,if=pflash,format=raw,unit=0,readonly=on' % self.uefi_code_path,
|
||||
'-drive', 'file=%s.VARS.fd,if=pflash,format=raw,unit=1' % self.path,
|
||||
'-drive', 'file=%s,if=none,id=harddrive0,format=qcow2' % self.path,
|
||||
'-device', 'virtio-blk-pci,drive=harddrive0,bootindex=0',
|
||||
'-drive', 'file=%s/cloud-init.seed,if=virtio,readonly=on' % self.autopkgtest_dir.name])
|
||||
|
||||
def ready(self):
|
||||
"""Returns true if the VM is booted and ready at userland"""
|
||||
# check captured serial for our marker
|
||||
self._mount()
|
||||
result = os.path.exists(os.path.join(self.autopkgtest_dir.name, 'img', 'TESTOK'))
|
||||
self._unmount()
|
||||
return result
|
||||
|
||||
|
465
debian/upstream/signing-key.asc
vendored
Normal file
465
debian/upstream/signing-key.asc
vendored
Normal file
@ -0,0 +1,465 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Comment: Hostname:
|
||||
Version: Hockeypuck 2.1.1-10-gec3b0e7
|
||||
|
||||
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
|
||||
/aD7gLo=
|
||||
=+tM6
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
6
debian/watch
vendored
6
debian/watch
vendored
@ -1,5 +1,5 @@
|
||||
# Compulsory line, this is a version 4 file
|
||||
version=4
|
||||
|
||||
opts="repack,compression=xz,filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/shim-$1\.tar\.gz/" \
|
||||
https://github.com/rhboot/shim/releases .*/v?(\d\S*)\.tar\.gz
|
||||
opts="repack,compression=xz,pgpmode=auto,searchmode=plain" \
|
||||
https://api.github.com/repos/rhboot/shim/releases?per_page=100 \
|
||||
https://github.com/rhboot/shim/releases/download/[^/]+/@PACKAGE@-@ANY_VERSION@@ARCHIVE_EXT@
|
3
errlog.c
3
errlog.c
@ -32,6 +32,9 @@ VLogError(const char *file, int line, const char *func, const CHAR16 *fmt,
|
||||
ms_va_list args2;
|
||||
CHAR16 **newerrs;
|
||||
|
||||
if (file == NULL || func == NULL || fmt == NULL)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
newerrs = ReallocatePool(errs, (nerrs + 1) * sizeof(*errs),
|
||||
(nerrs + 3) * sizeof(*errs));
|
||||
if (!newerrs)
|
||||
|
12
fallback.c
12
fallback.c
@ -1006,14 +1006,14 @@ try_start_first_option(EFI_HANDLE parent_image_handle)
|
||||
EFI_HANDLE image_handle;
|
||||
|
||||
if (get_fallback_verbose()) {
|
||||
int fallback_verbose_wait = 500000; /* default to 0.5s */
|
||||
unsigned long fallback_verbose_wait = 500000; /* default to 0.5s */
|
||||
#ifdef FALLBACK_VERBOSE_WAIT
|
||||
fallback_verbose_wait = FALLBACK_VERBOSE_WAIT;
|
||||
#endif
|
||||
console_print(L"Verbose enabled, sleeping for %d mseconds... "
|
||||
L"Press the Pause key now to hold for longer.\n",
|
||||
fallback_verbose_wait);
|
||||
msleep(fallback_verbose_wait);
|
||||
usleep(fallback_verbose_wait);
|
||||
}
|
||||
|
||||
if (!first_new_option) {
|
||||
@ -1036,7 +1036,7 @@ try_start_first_option(EFI_HANDLE parent_image_handle)
|
||||
}
|
||||
console_print(L"\n");
|
||||
|
||||
msleep(500000000);
|
||||
usleep(500000000);
|
||||
return efi_status;
|
||||
}
|
||||
|
||||
@ -1051,7 +1051,7 @@ try_start_first_option(EFI_HANDLE parent_image_handle)
|
||||
efi_status = BS->StartImage(image_handle, NULL, NULL);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
console_print(L"StartImage failed: %r\n", efi_status);
|
||||
msleep(500000000);
|
||||
usleep(500000000);
|
||||
}
|
||||
return efi_status;
|
||||
}
|
||||
@ -1211,14 +1211,14 @@ reset:
|
||||
console_print(L"Reset System\n");
|
||||
|
||||
if (get_fallback_verbose()) {
|
||||
int fallback_verbose_wait = 500000; /* default to 0.5s */
|
||||
unsigned long fallback_verbose_wait = 500000; /* default to 0.5s */
|
||||
#ifdef FALLBACK_VERBOSE_WAIT
|
||||
fallback_verbose_wait = FALLBACK_VERBOSE_WAIT;
|
||||
#endif
|
||||
console_print(L"Verbose enabled, sleeping for %d mseconds... "
|
||||
L"Press the Pause key now to hold for longer.\n",
|
||||
fallback_verbose_wait);
|
||||
msleep(fallback_verbose_wait);
|
||||
usleep(fallback_verbose_wait);
|
||||
}
|
||||
|
||||
RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
|
||||
|
71
fuzz-csv.c
Normal file
71
fuzz-csv.c
Normal file
@ -0,0 +1,71 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
/*
|
||||
* test-csv.c - test our csv parser
|
||||
*/
|
||||
|
||||
#ifndef SHIM_UNIT_TEST
|
||||
#define SHIM_UNIT_TEST
|
||||
#endif
|
||||
#include "shim.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
test_csv_simple_fuzz(char *random_bin, size_t random_bin_len)
|
||||
{
|
||||
list_t entry_list;
|
||||
size_t i;
|
||||
char *current, *end;
|
||||
list_t *pos = NULL;
|
||||
EFI_STATUS efi_status;
|
||||
|
||||
INIT_LIST_HEAD(&entry_list);
|
||||
|
||||
current = &random_bin[0];
|
||||
current = current + 1 - 1;
|
||||
end = current + random_bin_len - 1;
|
||||
*end = '\0';
|
||||
|
||||
efi_status = parse_csv_data(current, end, 7, &entry_list);
|
||||
if (efi_status != EFI_SUCCESS)
|
||||
return 0;
|
||||
if (list_size(&entry_list) <= 1)
|
||||
goto fail;
|
||||
|
||||
i = 0;
|
||||
list_for_each(pos, &entry_list) {
|
||||
struct csv_row *csv_row;
|
||||
|
||||
csv_row = list_entry(pos, struct csv_row, list);
|
||||
i++;
|
||||
}
|
||||
|
||||
free_csv_list(&entry_list);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
free_csv_list(&entry_list);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
int rc;
|
||||
uint8_t *data_copy;
|
||||
|
||||
if (size < 1)
|
||||
return 0;
|
||||
|
||||
data_copy = malloc(size);
|
||||
if (!data_copy)
|
||||
return -1;
|
||||
|
||||
memcpy(data_copy, data, size);
|
||||
rc = test_csv_simple_fuzz((char *)data_copy, size);
|
||||
free(data_copy);
|
||||
|
||||
return rc; // Values other than 0 and -1 are reserved for future use.
|
||||
}
|
||||
|
||||
// vim:fenc=utf-8:tw=75:noet
|
38
fuzz-pe-relocate.c
Normal file
38
fuzz-pe-relocate.c
Normal file
@ -0,0 +1,38 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
/*
|
||||
* fuzz-pe-relocate.c - fuzz our PE relocation code.
|
||||
* Copyright Peter Jones <pjones@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef SHIM_UNIT_TEST
|
||||
#define SHIM_UNIT_TEST
|
||||
#endif
|
||||
#include "shim.h"
|
||||
|
||||
UINT8 mok_policy = 0;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
uint8_t *data_copy;
|
||||
EFI_STATUS status = 0;
|
||||
size_t n = 0;
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT context = { 0, };
|
||||
|
||||
if (size < 1)
|
||||
return 0;
|
||||
|
||||
data_copy = malloc(size+1);
|
||||
if (!data_copy)
|
||||
return -1;
|
||||
|
||||
memcpy(data_copy, data, size);
|
||||
data_copy[size] = 0;
|
||||
|
||||
status = read_header(data_copy, size, &context);
|
||||
|
||||
free(data_copy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim:fenc=utf-8:tw=75:noet
|
46
fuzz-sbat.c
Normal file
46
fuzz-sbat.c
Normal file
@ -0,0 +1,46 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
/*
|
||||
* fuzz-sbat-section.c - fuzz our .sbat parsing code
|
||||
* Copyright Peter Jones <pjones@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef SHIM_UNIT_TEST
|
||||
#define SHIM_UNIT_TEST
|
||||
#endif
|
||||
#include "shim.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
list_t sbat_var;
|
||||
|
||||
BOOLEAN
|
||||
secure_mode() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
uint8_t *data_copy;
|
||||
EFI_STATUS status = 0;
|
||||
size_t n = 0;
|
||||
struct sbat_section_entry **entries = NULL;
|
||||
|
||||
if (size < 1)
|
||||
return 0;
|
||||
|
||||
data_copy = malloc(size+1);
|
||||
if (!data_copy)
|
||||
return -1;
|
||||
|
||||
memcpy(data_copy, data, size);
|
||||
data_copy[size] = 0;
|
||||
status = parse_sbat_section(data_copy, size, &n, &entries);
|
||||
cleanup_sbat_section_entries(n, entries);
|
||||
|
||||
free(data_copy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim:fenc=utf-8:tw=75:noet
|
@ -205,7 +205,7 @@ endif
|
||||
|
||||
ASFLAGS += $(ARCH3264)
|
||||
LDFLAGS += -nostdlib --warn-common --no-undefined --fatal-warnings \
|
||||
--build-id=sha1
|
||||
--build-id=sha1 --no-warn-rwx-segments
|
||||
|
||||
ifneq ($(ARCH),arm)
|
||||
export LIBGCC=$(shell $(CC) $(CFLAGS) $(ARCH3264) -print-libgcc-file-name)
|
||||
|
@ -41,3 +41,4 @@ _start:
|
||||
hello: .byte 'h',0,'e',0,'l',0,'l',0,'o',0,'\n',0,'\r',0,0,0
|
||||
|
||||
#endif
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -51,3 +51,4 @@ _start:
|
||||
.4byte .dummy1-.dummy0 // Page RVA
|
||||
.4byte 10 // Block Size (2*4+2)
|
||||
.2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -191,3 +191,4 @@ _start:
|
||||
|
||||
.L_DYNAMIC:
|
||||
.word _DYNAMIC - .
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -75,3 +75,4 @@ _start:
|
||||
.4byte .dummy1-.dummy0 // Page RVA
|
||||
.4byte 10 // Block Size (2*4+2)
|
||||
.2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -85,3 +85,4 @@ _start_plabel:
|
||||
data4 12 // Block Size (2*4+2*2)
|
||||
data2 (IMAGE_REL_BASED_DIR64<<12) + 0 // reloc for plabel's entry point
|
||||
data2 (IMAGE_REL_BASED_DIR64<<12) + 8 // reloc for plabel's global pointer
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -186,3 +186,4 @@ _pc:
|
||||
.end _start
|
||||
|
||||
.set pop
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -72,3 +72,4 @@ _start:
|
||||
.4byte .dummy1-.dummy0 // Page RVA
|
||||
.4byte 10 // Block Size (2*4+2)
|
||||
.2byte (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -225,3 +225,4 @@ apply_FPTR64:
|
||||
fptr_mem_base:
|
||||
.space MAX_FUNCTION_DESCRIPTORS*16
|
||||
fptr_mem_limit:
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -28,6 +28,6 @@ typedef struct {
|
||||
UINT64 D13;
|
||||
UINT64 D14;
|
||||
UINT64 D15;
|
||||
} ALIGN(JMPBUF_ALIGN) jmp_buf[1];
|
||||
} __attribute__((__aligned__(JMPBUF_ALIGN))) jmp_buf[1];
|
||||
|
||||
#endif /* GNU_EFI_AARCH64_SETJMP_H */
|
||||
|
@ -16,6 +16,6 @@ typedef struct {
|
||||
UINT32 R12;
|
||||
UINT32 R13;
|
||||
UINT32 R14;
|
||||
} ALIGN(JMPBUF_ALIGN) jmp_buf[1];
|
||||
} __attribute__((__aligned__(JMPBUF_ALIGN))) jmp_buf[1];
|
||||
|
||||
#endif /* GNU_EFI_ARM_SETJMP_H */
|
||||
|
@ -10,6 +10,6 @@ typedef struct {
|
||||
UINT32 Ebp;
|
||||
UINT32 Esp;
|
||||
UINT32 Eip;
|
||||
} ALIGN(JMPBUF_ALIGN) jmp_buf[1];
|
||||
} __attribute__((__aligned__(JMPBUF_ALIGN))) jmp_buf[1];
|
||||
|
||||
#endif /* GNU_EFI_IA32_SETJMP_H */
|
||||
|
@ -42,6 +42,6 @@ typedef struct {
|
||||
UINT64 Predicates;
|
||||
UINT64 LoopCount;
|
||||
UINT64 FPSR;
|
||||
} ALIGN(JMPBUF_ALIGN) jmp_buf[1];
|
||||
} __attribute__((__aligned__(JMPBUF_ALIGN))) jmp_buf[1];
|
||||
|
||||
#endif /* GNU_EFI_IA64_SETJMP_H */
|
||||
|
@ -29,6 +29,6 @@ typedef struct {
|
||||
UINT64 F30;
|
||||
UINT64 F31;
|
||||
#endif
|
||||
} ALIGN(JMPBUF_ALIGN) jmp_buf[1];
|
||||
} __attribute__((__aligned__(JMPBUF_ALIGN))) jmp_buf[1];
|
||||
|
||||
#endif /* GNU_EFI_MIPS64EL_SETJMP_H */
|
||||
|
@ -17,6 +17,6 @@ typedef struct {
|
||||
UINT64 Rip;
|
||||
UINT64 MxCsr;
|
||||
UINT8 XmmBuffer[160]; // XMM6 - XMM15
|
||||
} ALIGN(JMPBUF_ALIGN) jmp_buf[1];
|
||||
} __attribute__((__aligned__(JMPBUF_ALIGN))) jmp_buf[1];
|
||||
|
||||
#endif /* GNU_EFI_X86_64_SETJMP_H */
|
||||
|
@ -1,91 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 1999-2001 Hewlett-Packard Co.
|
||||
# Contributed by David Mosberger <davidm@hpl.hp.com>
|
||||
# Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
# * Neither the name of Hewlett-Packard Co. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SRCDIR = .
|
||||
|
||||
VPATH = $(SRCDIR)
|
||||
|
||||
include $(SRCDIR)/../Make.defaults
|
||||
|
||||
TOPDIR = $(SRCDIR)/..
|
||||
|
||||
CDIR = $(TOPDIR)/..
|
||||
FILES = boxdraw smbios console crc data debug dpath \
|
||||
error event guid hand hw init lock \
|
||||
misc print sread str cmdline \
|
||||
runtime/rtlock runtime/efirtlib runtime/rtstr runtime/vm runtime/rtdata \
|
||||
$(ARCH)/initplat $(ARCH)/math
|
||||
|
||||
ifeq ($(ARCH),ia64)
|
||||
FILES += $(ARCH)/salpal $(ARCH)/palproc
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
FILES += $(ARCH)/callwrap $(ARCH)/efi_stub
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),arm)
|
||||
FILES += $(ARCH)/lib1funcs $(ARCH)/div64
|
||||
endif
|
||||
|
||||
OBJS = $(FILES:%=%.o)
|
||||
|
||||
SUBDIRS = ia32 x86_64 ia64 aarch64 arm runtime
|
||||
|
||||
LIBDIRINSTALL = $(INSTALLROOT)$(LIBDIR)
|
||||
|
||||
all: libsubdirs libefi.a
|
||||
|
||||
.PHONY: libsubdirs
|
||||
libsubdirs:
|
||||
for sdir in $(SUBDIRS); do mkdir -p $$sdir; done
|
||||
|
||||
libefi.a: $(patsubst %,libefi.a(%),$(OBJS))
|
||||
|
||||
clean:
|
||||
rm -f libefi.a *~ $(OBJS) */*.o
|
||||
|
||||
$(LIBDIRINSTALL):
|
||||
mkdir -p $@
|
||||
|
||||
$(LIBDIRINSTALL)/libefi.a: libefi.a | $(LIBDIRINSTALL)
|
||||
$(INSTALL) -m 644 $< $(dir $@)
|
||||
|
||||
install: $(LIBDIRINSTALL)/libefi.a
|
||||
|
||||
include $(SRCDIR)/../Make.rules
|
||||
|
||||
.PHONY: libsubdirs
|
@ -1 +1,2 @@
|
||||
/* This stub is a stub to make the build happy */
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -58,3 +58,4 @@ longjmp:
|
||||
mov w0, #1
|
||||
csel w0, w1, w0, ne
|
||||
br x30
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -153,3 +153,4 @@ label1:
|
||||
@ What to do about division by zero? For now, just return.
|
||||
ASM_PFX(__aeabi_idiv0):
|
||||
bx r14
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -1 +1,2 @@
|
||||
/* This stub is a stub to make the build happy */
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -59,3 +59,4 @@ L_Exit:
|
||||
|
||||
|
||||
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -39,3 +39,4 @@ ASM_PFX(__aeabi_llsl):
|
||||
lsl r1,r0,r3
|
||||
mov r0,#0
|
||||
bx lr
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -39,3 +39,4 @@ ASM_PFX(__aeabi_llsr):
|
||||
lsr r0,r1,r3
|
||||
mov r1,#0
|
||||
bx lr
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -31,3 +31,4 @@ ASM_PFX(__aeabi_lmul):
|
||||
mla r1, r2, r1, ip
|
||||
mla r1, r3, lr, r1
|
||||
ldmia sp!, {pc}
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -23,3 +23,4 @@ setjmp:
|
||||
.type longjmp, %function
|
||||
longjmp:
|
||||
ldmia r0, {r3-r12,r14}
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -265,3 +265,4 @@ ASM_PFX(__aeabi_ldiv0):
|
||||
bx r14
|
||||
|
||||
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -1 +1,2 @@
|
||||
/* This stub is a stub to make the build happy */
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -43,3 +43,4 @@ longjmp:
|
||||
movl (%edx), %ebx
|
||||
movl 4(%edx), %esi
|
||||
movl 8(%edx), %edi
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -159,3 +159,4 @@ StackedComeBackFromPALCall:
|
||||
|
||||
PROCEDURE_EXIT(MakeStackedPALCall)
|
||||
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -197,3 +197,4 @@ _skip_flushrs:
|
||||
invala
|
||||
mov ar.rsc = r16
|
||||
br.ret.sptk b0
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -1 +1,2 @@
|
||||
/* This stub is a stub to make the build happy */
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -90,3 +90,4 @@ longjmp:
|
||||
li $v0, 1
|
||||
movn $v0, $a1, $a1
|
||||
jr $ra
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -187,3 +187,4 @@ ENTRY(efi_call10)
|
||||
ret
|
||||
|
||||
#endif
|
||||
.section .note.GNU-stack,"a"
|
||||
|
@ -46,3 +46,4 @@ longjmp:
|
||||
cmp %rax,%rdx
|
||||
cmove %rcx,%rax
|
||||
jmp *0x38(%rdi)
|
||||
.section .note.GNU-stack,"a"
|
||||
|
16
httpboot.c
16
httpboot.c
@ -578,7 +578,13 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size)
|
||||
}
|
||||
|
||||
if (*buf_size == 0) {
|
||||
perror(L"Failed to get Content-Lenght\n");
|
||||
perror(L"Failed to get Content-Length\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (*buf_size < rx_message.BodyLength) {
|
||||
efi_status = EFI_BAD_BUFFER_SIZE;
|
||||
perror(L"Invalid Content-Length\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -713,18 +719,20 @@ error:
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size)
|
||||
httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size,
|
||||
CHAR8 *name)
|
||||
{
|
||||
EFI_STATUS efi_status;
|
||||
EFI_HANDLE nic;
|
||||
CHAR8 next_loader[sizeof DEFAULT_LOADER_CHAR];
|
||||
CHAR8 *next_loader;
|
||||
CHAR8 *next_uri = NULL;
|
||||
CHAR8 *hostname = NULL;
|
||||
|
||||
if (!uri)
|
||||
return EFI_NOT_READY;
|
||||
|
||||
translate_slashes(next_loader, DEFAULT_LOADER_CHAR);
|
||||
next_loader = (CHAR8 *)AllocatePool((strlen(name) + 1) * sizeof (CHAR8));
|
||||
translate_slashes(next_loader, name);
|
||||
|
||||
/* Create the URI for the next loader based on the original URI */
|
||||
efi_status = generate_next_uri(uri, next_loader, &next_uri);
|
||||
|
@ -40,11 +40,11 @@ static inline void wait_for_debug(void)
|
||||
{
|
||||
uint64_t a, b;
|
||||
int x;
|
||||
extern void msleep(unsigned long msecs);
|
||||
extern void usleep(unsigned long usecs);
|
||||
|
||||
a = read_counter();
|
||||
for (x = 0; x < 1000; x++) {
|
||||
msleep(1000);
|
||||
usleep(1000);
|
||||
b = read_counter();
|
||||
if (a != b)
|
||||
break;
|
||||
|
@ -198,5 +198,55 @@
|
||||
#error shim has no cache_invalidate() implementation for this compiler
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
#define GNUC_PREREQ(maj, min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
#define GNUC_PREREQ(maj, min) 0
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
|
||||
#define CLANG_PREREQ(maj, min) \
|
||||
((__clang_major__ > (maj)) || \
|
||||
(__clang_major__ == (maj) && __clang_minor__ >= (min)))
|
||||
#else
|
||||
#define CLANG_PREREQ(maj, min) 0
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(5, 1) || CLANG_PREREQ(3, 8)
|
||||
#define checked_add(addend0, addend1, sum) \
|
||||
__builtin_add_overflow(addend0, addend1, sum)
|
||||
#define checked_sub(minuend, subtrahend, difference) \
|
||||
__builtin_sub_overflow(minuend, subtrahend, difference)
|
||||
#define checked_mul(factor0, factor1, product) \
|
||||
__builtin_mul_overflow(factor0, factor1, product)
|
||||
#else
|
||||
#define checked_add(a0, a1, s) \
|
||||
({ \
|
||||
(*s) = ((a0) + (a1)); \
|
||||
0; \
|
||||
})
|
||||
#define checked_sub(s0, s1, d) \
|
||||
({ \
|
||||
(*d) = ((s0) - (s1)); \
|
||||
0; \
|
||||
})
|
||||
#define checked_mul(f0, f1, p) \
|
||||
({ \
|
||||
(*p) = ((f0) * (f1)); \
|
||||
0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define checked_div(dividend, divisor, quotient) \
|
||||
({ \
|
||||
bool _ret = True; \
|
||||
if ((divisor) != 0) { \
|
||||
_ret = False; \
|
||||
(quotient) = (dividend) / (divisor); \
|
||||
} \
|
||||
_ret; \
|
||||
})
|
||||
|
||||
#endif /* !COMPILER_H_ */
|
||||
// vim:fenc=utf-8:tw=75:et
|
||||
|
@ -106,8 +106,8 @@ extern UINT32 verbose;
|
||||
dprint_(L"%a:%d:%a() " fmt, __FILE__, __LINE__ - 1, __func__, \
|
||||
##__VA_ARGS__)
|
||||
#else
|
||||
#define dprint_(...)
|
||||
#define dprint(fmt, ...)
|
||||
#define dprint_(...) ({ ; })
|
||||
#define dprint(fmt, ...) ({ ; })
|
||||
#endif
|
||||
|
||||
extern EFI_STATUS EFIAPI vdprint_(const CHAR16 *fmt, const char *file, int line,
|
||||
@ -122,7 +122,9 @@ extern EFI_STATUS EFIAPI vdprint_(const CHAR16 *fmt, const char *file, int line,
|
||||
extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line);
|
||||
#define crypterr(rc) print_crypto_errors((rc), __FILE__, __func__, __LINE__)
|
||||
|
||||
extern VOID msleep(unsigned long msecs);
|
||||
#ifndef SHIM_UNIT_TEST
|
||||
extern VOID usleep(unsigned long usecs);
|
||||
#endif
|
||||
|
||||
/* This is used in various things to determine if we should print to the
|
||||
* console */
|
||||
|
@ -21,6 +21,7 @@ fanalyzer-build-all : COMPILER=gcc
|
||||
fanalyzer-build-all : CCACHE_DISABLE=1
|
||||
fanalyzer-build-all : FEATUREFLAGS+=-fanalyzer
|
||||
fanalyzer-build-all : WERRFLAGS=-Werror=analyzer-null-dereference
|
||||
fanalyzer-build-all : IGNORE_COMPILER_ERRORS=" || :"
|
||||
fanalyzer-build-all : all
|
||||
|
||||
fanalyzer-no-openssl : | fanalyzer-test
|
||||
|
97
include/fuzz.mk
Normal file
97
include/fuzz.mk
Normal file
@ -0,0 +1,97 @@
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
# fuzz.mk - makefile to fuzz local test programs
|
||||
#
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
include Make.defaults
|
||||
|
||||
CC = clang
|
||||
VALGRIND ?=
|
||||
DEBUG_PRINTS ?= 0
|
||||
OPTIMIZATIONS ?= -Og -ggdb
|
||||
FUZZ_ARGS ?=
|
||||
CFLAGS = $(OPTIMIZATIONS) -std=gnu11 \
|
||||
-isystem $(TOPDIR)/include/system \
|
||||
$(EFI_INCLUDES) \
|
||||
-Iinclude -iquote . \
|
||||
-isystem /usr/include \
|
||||
-isystem $(shell $(CC) $(ARCH_CFLAGS) -print-file-name=include) \
|
||||
$(ARCH_CFLAGS) \
|
||||
-fsanitize=fuzzer,address \
|
||||
-fshort-wchar \
|
||||
-fno-builtin \
|
||||
-rdynamic \
|
||||
-fno-inline \
|
||||
-fno-eliminate-unused-debug-types \
|
||||
-fno-eliminate-unused-debug-symbols \
|
||||
-gpubnames \
|
||||
-grecord-gcc-switches \
|
||||
$(if $(findstring clang,$(CC)),-Wno-unknown-warning-option) \
|
||||
$(DEFAULT_WARNFLAGS) \
|
||||
-Wsign-compare \
|
||||
-Wno-deprecated-declarations \
|
||||
$(if $(findstring gcc,$(CC)),-Wno-unused-but-set-variable) \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-unused-variable \
|
||||
-Wno-pointer-sign \
|
||||
$(DEFAULT_WERRFLAGS) \
|
||||
-Werror=nonnull \
|
||||
$(shell $(CC) -Werror=nonnull-compare -E -x c /dev/null >/dev/null 2>&1 && echo -Werror=nonnull-compare) \
|
||||
$(ARCH_DEFINES) \
|
||||
-DEFI_FUNCTION_WRAPPER \
|
||||
-DGNU_EFI_USE_MS_ABI -DPAGE_SIZE=4096 \
|
||||
-DSHIM_UNIT_TEST \
|
||||
-DSHIM_ENABLE_LIBFUZZER \
|
||||
"-DDEFAULT_DEBUG_PRINT_STATE=$(DEBUG_PRINTS)"
|
||||
|
||||
# On some systems (e.g. Arch Linux), limits.h is in the "include-fixed" instead
|
||||
# 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)
|
||||
|
||||
libefi-test.a :
|
||||
$(MAKE) -C gnu-efi \
|
||||
COMPILER="$(COMPILER)" \
|
||||
CC="$(CC)" \
|
||||
ARCH=$(ARCH_GNUEFI) \
|
||||
TOPDIR=$(TOPDIR)/gnu-efi \
|
||||
-f $(TOPDIR)/gnu-efi/Makefile \
|
||||
clean lib
|
||||
mv gnu-efi/$(ARCH)/lib/libefi.a $@
|
||||
$(MAKE) -C gnu-efi \
|
||||
COMPILER="$(COMPILER)" \
|
||||
ARCH=$(ARCH_GNUEFI) \
|
||||
TOPDIR=$(TOPDIR)/gnu-efi \
|
||||
-f $(TOPDIR)/gnu-efi/Makefile \
|
||||
clean
|
||||
|
||||
fuzz-sbat_FILES = csv.c lib/variables.c lib/guid.c sbat_var.S mock-variables.c
|
||||
fuzz-sbat :: CFLAGS+=-DHAVE_GET_VARIABLE -DHAVE_GET_VARIABLE_ATTR -DHAVE_SHIM_LOCK_GUID
|
||||
|
||||
fuzzers := $(patsubst %.c,%,$(wildcard fuzz-*.c))
|
||||
|
||||
$(fuzzers) :: fuzz-% : | libefi-test.a
|
||||
|
||||
$(fuzzers) :: fuzz-% : test.c fuzz-%.c $(fuzz-%_FILES)
|
||||
$(CC) $(CFLAGS) -o $@ $(sort $^ $(wildcard $*.c) $(fuzz-$*_FILES)) libefi-test.a -lefivar
|
||||
$(VALGRIND) ./$@ -max_len=4096 -jobs=24 $(FUZZ_ARGS)
|
||||
|
||||
fuzz : $(fuzzers)
|
||||
$(MAKE) -f include/fuzz.mk fuzz-clean
|
||||
|
||||
fuzz-clean :
|
||||
@rm -vf random.bin libefi-test.a
|
||||
@rm -vf vgcore.* fuzz*.log
|
||||
|
||||
clean : fuzz-clean
|
||||
|
||||
all : fuzz-clean fuzz
|
||||
|
||||
.PHONY: $(fuzzers) all fuzz clean
|
||||
.SECONDARY: random.bin
|
||||
|
||||
# vim:ft=make
|
@ -37,5 +37,6 @@ 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;
|
||||
extern EFI_GUID SECUREBOOT_EFI_NAMESPACE_GUID;
|
||||
|
||||
#endif /* SHIM_GUID_H */
|
||||
|
@ -12,6 +12,6 @@
|
||||
|
||||
extern BOOLEAN find_httpboot(EFI_HANDLE device);
|
||||
extern EFI_STATUS httpboot_fetch_buffer(EFI_HANDLE image, VOID **buffer,
|
||||
UINT64 *buf_size);
|
||||
UINT64 *buf_size, CHAR8 *name);
|
||||
|
||||
#endif /* SHIM_HTTPBOOT_H */
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
extern BOOLEAN findNetboot(EFI_HANDLE image_handle);
|
||||
|
||||
extern EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle);
|
||||
extern EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle, CHAR8 *name);
|
||||
|
||||
extern EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *bufsiz);
|
||||
|
||||
|
14
include/pe.h
14
include/pe.h
@ -21,6 +21,20 @@ EFI_STATUS verify_image(void *data, unsigned int datasize,
|
||||
EFI_STATUS
|
||||
verify_sbat_section(char *SBATBase, size_t SBATSize);
|
||||
|
||||
EFI_STATUS
|
||||
get_section_vma (UINTN section_num,
|
||||
char *buffer, size_t bufsz UNUSED,
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
char **basep, size_t *sizep,
|
||||
EFI_IMAGE_SECTION_HEADER **sectionp);
|
||||
|
||||
EFI_STATUS
|
||||
get_section_vma_by_name (char *name, size_t namesz,
|
||||
char *buffer, size_t bufsz,
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
char **basep, size_t *sizep,
|
||||
EFI_IMAGE_SECTION_HEADER **sectionp);
|
||||
|
||||
EFI_STATUS
|
||||
handle_image (void *data, unsigned int datasize,
|
||||
EFI_LOADED_IMAGE *li,
|
||||
|
@ -29,6 +29,9 @@
|
||||
#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1)))
|
||||
#define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment))))
|
||||
|
||||
// Check if `val` is evenly aligned to the page size.
|
||||
#define IS_PAGE_ALIGNED(val) (!((val) & EFI_PAGE_MASK))
|
||||
|
||||
//
|
||||
// PE32+ Subsystem type for EFI images
|
||||
//
|
||||
|
@ -30,10 +30,15 @@
|
||||
|
||||
#define SBAT_POLICY L"SbatPolicy"
|
||||
#define SBAT_POLICY8 "SbatPolicy"
|
||||
#define SSP_POLICY L"SSPPolicy"
|
||||
#define SSP_POLICY8 "SSPPolicy"
|
||||
|
||||
#define SBAT_POLICY_LATEST 1
|
||||
#define SBAT_POLICY_PREVIOUS 2
|
||||
#define SBAT_POLICY_RESET 3
|
||||
#define POLICY_LATEST 1
|
||||
#define POLICY_AUTOMATIC 2
|
||||
#define POLICY_RESET 3
|
||||
#define POLICY_NOTREAD 255
|
||||
|
||||
#define REVOCATIONFILE L"revocations.efi"
|
||||
|
||||
extern UINTN _sbat, _esbat;
|
||||
|
||||
@ -50,9 +55,10 @@ extern list_t sbat_var;
|
||||
#define SBAT_VAR_COLUMNS ((sizeof (struct sbat_var_entry) - sizeof(list_t)) / sizeof(CHAR8 *))
|
||||
#define SBAT_VAR_REQUIRED_COLUMNS (SBAT_VAR_COLUMNS - 1)
|
||||
|
||||
EFI_STATUS parse_sbat_var(list_t *entries);
|
||||
EFI_STATUS parse_sbat_var(list_t *entries, char *sbat_var_candidate);
|
||||
void cleanup_sbat_var(list_t *entries);
|
||||
EFI_STATUS set_sbat_uefi_variable(void);
|
||||
EFI_STATUS set_sbat_uefi_variable_internal(void);
|
||||
EFI_STATUS set_sbat_uefi_variable(char *, char *);
|
||||
bool preserve_sbat_uefi_variable(UINT8 *sbat, UINTN sbatsize,
|
||||
UINT32 attributes, char *sbar_var);
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef SBAT_VAR_DEFS_H_
|
||||
#define SBAT_VAR_DEFS_H_
|
||||
|
||||
#define QUOTEVAL(s) QUOTE(s)
|
||||
#define QUOTE(s) #s
|
||||
|
||||
/*
|
||||
* This is the entry for the sbat data format
|
||||
*/
|
||||
@ -13,11 +16,9 @@
|
||||
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_AUTOMATIC_DATE "2021030218"
|
||||
#define SBAT_VAR_AUTOMATIC \
|
||||
SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_AUTOMATIC_DATE "\n"
|
||||
|
||||
#define SBAT_VAR_LATEST_DATE "2022050100"
|
||||
#define SBAT_VAR_LATEST_REVOCATIONS "component,2\nothercomponent,2\n"
|
||||
@ -25,21 +26,42 @@
|
||||
SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_LATEST_DATE "\n" \
|
||||
SBAT_VAR_LATEST_REVOCATIONS
|
||||
#else /* !ENABLE_SHIM_DEVEL */
|
||||
/*
|
||||
* As of 2022-11-16, most folks (including Ubuntu, SUSE, openSUSE) don't have
|
||||
* a "shim,2" yet, so adding that here would end up unbootable.
|
||||
*/
|
||||
#define SBAT_VAR_PREVIOUS_DATE "2022052400"
|
||||
#define SBAT_VAR_PREVIOUS_REVOCATIONS "grub,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 "2022111500"
|
||||
#define SBAT_VAR_LATEST_REVOCATIONS "shim,2\ngrub,3\n"
|
||||
/*
|
||||
* Some distros may want to apply revocations from 2022052400
|
||||
* or 2022111500 automatically. They can be selected by setting
|
||||
* SBAT_AUTOMATIC_DATE=<datestamp> at build time. Otherwise the
|
||||
* default is to apply the second to most recent revocations
|
||||
* automatically. Distros that need to manage automatic updates
|
||||
* externally from shim can choose the epoch 2021030218 emtpy
|
||||
* revocations.
|
||||
*/
|
||||
#ifndef SBAT_AUTOMATIC_DATE
|
||||
#define SBAT_AUTOMATIC_DATE 2023012900
|
||||
#endif /* SBAT_AUTOMATIC_DATE */
|
||||
#if SBAT_AUTOMATIC_DATE == 2021030218
|
||||
#define SBAT_VAR_AUTOMATIC_REVOCATIONS
|
||||
#elif SBAT_AUTOMATIC_DATE == 2022052400
|
||||
#define SBAT_VAR_AUTOMATIC_REVOCATIONS "grub,2\n"
|
||||
#elif SBAT_AUTOMATIC_DATE == 2022111500
|
||||
#define SBAT_VAR_AUTOMATIC_REVOCATIONS "shim,2\ngrub,3\n"
|
||||
#elif SBAT_AUTOMATIC_DATE == 2023012900
|
||||
#define SBAT_VAR_AUTOMATIC_REVOCATIONS "shim,2\ngrub,3\ngrub.debian,4\n"
|
||||
#else
|
||||
#error "Unknown SBAT_AUTOMATIC_DATE"
|
||||
#endif /* SBAT_AUTOMATIC_DATE == */
|
||||
#define SBAT_VAR_AUTOMATIC_DATE QUOTEVAL(SBAT_AUTOMATIC_DATE)
|
||||
#define SBAT_VAR_AUTOMATIC \
|
||||
SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_AUTOMATIC_DATE "\n" \
|
||||
SBAT_VAR_AUTOMATIC_REVOCATIONS
|
||||
|
||||
/*
|
||||
* Revocations for January 2024 shim CVEs
|
||||
*/
|
||||
#define SBAT_VAR_LATEST_DATE "2024010900"
|
||||
#define SBAT_VAR_LATEST_REVOCATIONS "shim,4\ngrub,3\ngrub.debian,4\n"
|
||||
#define SBAT_VAR_LATEST \
|
||||
SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_LATEST_DATE "\n" \
|
||||
SBAT_VAR_LATEST_REVOCATIONS
|
||||
#endif /* ENABLE_SHIM_DEVEL */
|
||||
|
||||
#endif /* !SBAT_VAR_DEFS_H_ */
|
||||
|
@ -22,6 +22,7 @@ scan-build-unchecked-openssl : Cryptlib/OpenSSL/libopenssl.a
|
||||
|
||||
scan-build-all : CCACHE_DISABLE=1
|
||||
scan-build-all : COMPILER=clang
|
||||
scan-build-all : IGNORE_COMPILER_ERRORS=" || :"
|
||||
scan-build-all : | scan-test
|
||||
scan-build-all :
|
||||
+scan-build -o scan-results make $(MAKEARGS) $(DASHJ) CCACHE_DISABLE=1 all
|
||||
|
14
include/ssp.h
Normal file
14
include/ssp.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef SSP_H_
|
||||
#define SSP_H_
|
||||
|
||||
#define SSPVER_VAR_NAME L"SkuSiPolicyVersion"
|
||||
#define SSPSIG_VAR_NAME L"SkuSiPolicyUpdateSigners"
|
||||
#define SSP_VAR_ATTRS UEFI_VAR_NV_BS
|
||||
|
||||
#define SSPVER_SIZE 8
|
||||
#define SSPSIG_SIZE 131
|
||||
|
||||
EFI_STATUS set_ssp_uefi_variable_internal(void);
|
||||
EFI_STATUS set_ssp_uefi_variable(uint8_t*, uint8_t*, uint8_t*, uint8_t*);
|
||||
|
||||
#endif /* !SSP_H_ */
|
19
include/ssp_var_defs.h
Normal file
19
include/ssp_var_defs.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* variable definitions to enable bootmgr self revocation
|
||||
*/
|
||||
#ifndef SSP_VAR_DEFS_H_
|
||||
#define SSP_VAR_DEFS_H_
|
||||
|
||||
uint8_t SkuSiPolicyVersion[] = { 0x2,0x0,0x0,0x0,0x0,0x0,0x2,0x0 };
|
||||
uint8_t SkuSiPolicyUpdateSigners[] = {
|
||||
0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
|
||||
0x0b,0x00,0x00,0x00,0xd0,0x91,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
|
||||
0x00,0x00,0x00,0x00,0x54,0xa6,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
|
||||
0x00,0x00,0x00,0x00,0x5c,0xa6,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,
|
||||
0x00,0x00,0x00,0x00,0x64,0xa6,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0a,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x03,0x06,0x00,
|
||||
0x00,0x00,0x00 };
|
||||
|
||||
#endif /* !SSP_VAR_DEFS_H_ */
|
@ -92,9 +92,12 @@ test-mock-variables: CFLAGS+=-DHAVE_SHIM_LOCK_GUID
|
||||
test-mok-mirror_FILES = mok.c globals.c tpm.c lib/guid.c lib/variables.c mock-variables.c
|
||||
test-mok-mirror: CFLAGS+=-DHAVE_START_IMAGE -DHAVE_SHIM_LOCK_GUID
|
||||
|
||||
test-sbat_FILES = csv.c lib/variables.c lib/guid.c sbat_var.S
|
||||
test-sbat_FILES = csv.c lib/variables.c lib/guid.c sbat_var.S mock-variables.c
|
||||
test-sbat :: CFLAGS+=-DHAVE_GET_VARIABLE -DHAVE_GET_VARIABLE_ATTR -DHAVE_SHIM_LOCK_GUID
|
||||
|
||||
test-pe-relocate_FILES = globals.c
|
||||
test-pe-relocate :: CFLAGS+=-DHAVE_SHIM_LOCK_GUID
|
||||
|
||||
test-str_FILES = lib/string.c
|
||||
|
||||
tests := $(patsubst %.c,%,$(wildcard test-*.c))
|
||||
|
@ -743,11 +743,13 @@ setup_verbosity(VOID)
|
||||
setup_console(-1);
|
||||
}
|
||||
|
||||
#ifndef SHIM_UNIT_TEST
|
||||
VOID
|
||||
msleep(unsigned long msecs)
|
||||
usleep(unsigned long usecs)
|
||||
{
|
||||
BS->Stall(msecs);
|
||||
BS->Stall(usecs);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is used in various things to determine if we should print to the
|
||||
* console */
|
||||
|
@ -36,3 +36,4 @@ EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x
|
||||
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} };
|
||||
EFI_GUID SECUREBOOT_EFI_NAMESPACE_GUID = {0x77fa9abd, 0x0359, 0x4d32, {0xbd, 0x60, 0x28, 0xf4, 0xe7, 0x8f, 0x78, 0x4b} };
|
||||
|
2
model.c
2
model.c
@ -54,7 +54,7 @@ gcm_gmult_4bit(u64 Xi[2], u128 Htable[16])
|
||||
}
|
||||
|
||||
void
|
||||
msleep(int n)
|
||||
usleep(int n)
|
||||
{
|
||||
__coverity_sleep__();
|
||||
}
|
||||
|
18
mok.c
18
mok.c
@ -291,7 +291,7 @@ mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
|
||||
&var, &varsz);
|
||||
if (EFI_ERROR(efi_status) || !var || !varsz) {
|
||||
LogError(L"Couldn't allocate %lu bytes for mok variable \"%s\": %r\n",
|
||||
varsz, var, efi_status);
|
||||
varsz, name, efi_status);
|
||||
return efi_status;
|
||||
}
|
||||
|
||||
@ -302,7 +302,7 @@ mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
|
||||
FreePool(var);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
LogError(L"Couldn't create mok variable \"%s\": %r\n",
|
||||
varsz, var, efi_status);
|
||||
name, efi_status);
|
||||
return efi_status;
|
||||
}
|
||||
|
||||
@ -423,12 +423,20 @@ mirror_mok_db(CHAR16 *name, CHAR8 *name8, EFI_GUID *guid, UINT32 attrs,
|
||||
}
|
||||
|
||||
/* The name counts towards the size of the variable */
|
||||
max_var_sz -= (StrLen(namen) + 1) * 2;
|
||||
SIZE_T namen_sz = (StrLen(namen) + 1) * 2;
|
||||
if (max_var_sz > namen_sz)
|
||||
max_var_sz -= namen_sz;
|
||||
else
|
||||
max_var_sz = 0;
|
||||
dprint(L"max_var_sz - name: %lx\n", max_var_sz);
|
||||
|
||||
SIZE_T howmany;
|
||||
howmany = MIN((max_var_sz - sizeof(*esl)) / esl->SignatureSize,
|
||||
(esl_end_pos - pos) / esl->SignatureSize);
|
||||
if (max_var_sz > sizeof(*esl))
|
||||
howmany = MIN((max_var_sz - sizeof(*esl)) / esl->SignatureSize,
|
||||
(esl_end_pos - pos) / esl->SignatureSize);
|
||||
else
|
||||
howmany = 0;
|
||||
|
||||
if (howmany == 0) {
|
||||
/* No signatures from this ESL can be mirrored in to a
|
||||
* single variable, so skip it.
|
||||
|
60
netboot.c
60
netboot.c
@ -160,25 +160,30 @@ static CHAR8 *str2ip6(CHAR8 *str)
|
||||
return (CHAR8 *)ip;
|
||||
}
|
||||
|
||||
static BOOLEAN extract_tftp_info(CHAR8 *url)
|
||||
static BOOLEAN extract_tftp_info(CHAR8 *url, CHAR8 *name)
|
||||
{
|
||||
CHAR8 *start, *end;
|
||||
CHAR8 ip6str[40];
|
||||
CHAR8 ip6inv[16];
|
||||
CHAR8 template[sizeof DEFAULT_LOADER_CHAR];
|
||||
int template_len = 0;
|
||||
CHAR8 *template;
|
||||
|
||||
translate_slashes(template, DEFAULT_LOADER_CHAR);
|
||||
while (name[template_len++] != '\0');
|
||||
template = (CHAR8 *)AllocatePool((template_len + 1) * sizeof (CHAR8));
|
||||
translate_slashes(template, name);
|
||||
|
||||
// to check against str2ip6() errors
|
||||
memset(ip6inv, 0, sizeof(ip6inv));
|
||||
|
||||
if (strncmp((const char *)url, (const char *)"tftp://", 7)) {
|
||||
console_print(L"URLS MUST START WITH tftp://\n");
|
||||
FreePool(template);
|
||||
return FALSE;
|
||||
}
|
||||
start = url + 7;
|
||||
if (*start != '[') {
|
||||
console_print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
|
||||
FreePool(template);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -188,22 +193,28 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
|
||||
end++;
|
||||
if (end - start >= (int)sizeof(ip6str)) {
|
||||
console_print(L"TFTP URL includes malformed IPv6 address\n");
|
||||
FreePool(template);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (*end == '\0') {
|
||||
console_print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
|
||||
FreePool(template);
|
||||
return FALSE;
|
||||
}
|
||||
memset(ip6str, 0, sizeof(ip6str));
|
||||
memcpy(ip6str, start, end - start);
|
||||
end++;
|
||||
memcpy(&tftp_addr.v6, str2ip6(ip6str), 16);
|
||||
if (memcmp(&tftp_addr.v6, ip6inv, sizeof(ip6inv)) == 0)
|
||||
if (memcmp(&tftp_addr.v6, ip6inv, sizeof(ip6inv)) == 0) {
|
||||
FreePool(template);
|
||||
return FALSE;
|
||||
}
|
||||
full_path = AllocateZeroPool(strlen(end)+strlen(template)+1);
|
||||
if (!full_path)
|
||||
if (!full_path) {
|
||||
FreePool(template);
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(full_path, end, strlen(end));
|
||||
end = (CHAR8 *)strrchr((char *)full_path, '/');
|
||||
if (!end)
|
||||
@ -211,10 +222,11 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
|
||||
memcpy(end, template, strlen(template));
|
||||
end[strlen(template)] = '\0';
|
||||
|
||||
FreePool(template);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static EFI_STATUS parseDhcp6()
|
||||
static EFI_STATUS parseDhcp6(CHAR8 *name)
|
||||
{
|
||||
EFI_PXE_BASE_CODE_DHCPV6_PACKET *packet = (EFI_PXE_BASE_CODE_DHCPV6_PACKET *)&pxe->Mode->DhcpAck.Raw;
|
||||
CHAR8 *bootfile_url;
|
||||
@ -222,7 +234,7 @@ static EFI_STATUS parseDhcp6()
|
||||
bootfile_url = get_v6_bootfile_url(packet);
|
||||
if (!bootfile_url)
|
||||
return EFI_NOT_FOUND;
|
||||
if (extract_tftp_info(bootfile_url) == FALSE) {
|
||||
if (extract_tftp_info(bootfile_url, name) == FALSE) {
|
||||
FreePool(bootfile_url);
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
@ -230,14 +242,16 @@ static EFI_STATUS parseDhcp6()
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static EFI_STATUS parseDhcp4()
|
||||
static EFI_STATUS parseDhcp4(CHAR8 *name)
|
||||
{
|
||||
CHAR8 template[sizeof DEFAULT_LOADER_CHAR];
|
||||
INTN template_len;
|
||||
CHAR8 *template;
|
||||
INTN template_len = 0;
|
||||
UINTN template_ofs = 0;
|
||||
EFI_PXE_BASE_CODE_DHCPV4_PACKET* pkt_v4 = (EFI_PXE_BASE_CODE_DHCPV4_PACKET *)&pxe->Mode->DhcpAck.Dhcpv4;
|
||||
|
||||
translate_slashes(template, DEFAULT_LOADER_CHAR);
|
||||
while (name[template_len++] != '\0');
|
||||
template = (CHAR8 *)AllocatePool((template_len + 1) * sizeof (CHAR8));
|
||||
translate_slashes(template, name);
|
||||
template_len = strlen(template) + 1;
|
||||
|
||||
if(pxe->Mode->ProxyOfferReceived) {
|
||||
@ -263,30 +277,42 @@ static EFI_STATUS parseDhcp4()
|
||||
UINT8 *dir = pkt_v4->BootpBootFile;
|
||||
|
||||
for (i = dir_len; i >= 0; i--) {
|
||||
if (dir[i] == '/')
|
||||
if ((dir[i] == '/') || (dir[i] == '\\'))
|
||||
break;
|
||||
}
|
||||
dir_len = (i >= 0) ? i + 1 : 0;
|
||||
|
||||
full_path = AllocateZeroPool(dir_len + template_len);
|
||||
|
||||
if (!full_path)
|
||||
if (!full_path) {
|
||||
FreePool(template);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (dir_len > 0) {
|
||||
strncpy(full_path, (CHAR8 *)dir, dir_len);
|
||||
if (full_path[dir_len-1] == '/' && template[0] == '/')
|
||||
full_path[dir_len-1] = '\0';
|
||||
/*
|
||||
* If the path from DHCP is using backslash instead of slash,
|
||||
* accept that and use it in the template in the same position
|
||||
* as well.
|
||||
*/
|
||||
if (full_path[dir_len-1] == '\\' && template[0] == '/') {
|
||||
full_path[dir_len-1] = '\0';
|
||||
template[0] = '\\';
|
||||
}
|
||||
}
|
||||
if (dir_len == 0 && dir[0] != '/' && template[0] == '/')
|
||||
template_ofs++;
|
||||
strcat(full_path, template + template_ofs);
|
||||
memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4);
|
||||
|
||||
FreePool(template);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle UNUSED)
|
||||
EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle UNUSED, CHAR8 *netbootname)
|
||||
{
|
||||
|
||||
EFI_STATUS efi_status;
|
||||
@ -301,9 +327,9 @@ EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle UNUSED)
|
||||
* if its ipv4 or ipv6
|
||||
*/
|
||||
if (pxe->Mode->UsingIpv6){
|
||||
efi_status = parseDhcp6();
|
||||
efi_status = parseDhcp6(netbootname);
|
||||
} else
|
||||
efi_status = parseDhcp4();
|
||||
efi_status = parseDhcp4(netbootname);
|
||||
return efi_status;
|
||||
}
|
||||
|
||||
@ -315,7 +341,7 @@ EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle UNUSED, VOID **buffer, UINT
|
||||
BOOLEAN nobuffer = FALSE;
|
||||
UINTN blksz = 512;
|
||||
|
||||
console_print(L"Fetching Netboot Image\n");
|
||||
console_print(L"Fetching Netboot Image %a\n", full_path);
|
||||
if (*buffer == NULL) {
|
||||
*buffer = AllocatePool(4096 * 1024);
|
||||
if (!*buffer)
|
||||
|
554
pe-relocate.c
Normal file
554
pe-relocate.c
Normal file
@ -0,0 +1,554 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
/*
|
||||
* pe-relocate.c - our PE relocation/loading (but not verification) code
|
||||
* Copyright Peter Jones <pjones@redhat.com>
|
||||
*/
|
||||
|
||||
#include "shim.h"
|
||||
|
||||
/*
|
||||
* Perform basic bounds checking of the intra-image pointers
|
||||
*/
|
||||
void *
|
||||
ImageAddress (void *image, uint64_t size, uint64_t address)
|
||||
{
|
||||
uintptr_t img_addr;
|
||||
|
||||
/* ensure our local pointer isn't bigger than our size */
|
||||
if (address >= size)
|
||||
return NULL;
|
||||
|
||||
/* Insure our math won't overflow */
|
||||
img_addr = (uintptr_t)image;
|
||||
if (checked_add(img_addr, address, &img_addr))
|
||||
return NULL;
|
||||
|
||||
/* return the absolute pointer */
|
||||
return (void *)img_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the actual relocation
|
||||
*/
|
||||
EFI_STATUS
|
||||
relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
EFI_IMAGE_SECTION_HEADER *Section,
|
||||
void *orig, void *data)
|
||||
{
|
||||
EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
|
||||
UINT64 Adjust;
|
||||
UINT16 *Reloc, *RelocEnd;
|
||||
char *Fixup, *FixupBase;
|
||||
UINT16 *Fixup16;
|
||||
UINT32 *Fixup32;
|
||||
UINT64 *Fixup64;
|
||||
int size = context->ImageSize;
|
||||
void *ImageEnd = (char *)orig + size;
|
||||
int n = 0;
|
||||
|
||||
/* Alright, so here's how this works:
|
||||
*
|
||||
* context->RelocDir gives us two things:
|
||||
* - the VA the table of base relocation blocks are (maybe) to be
|
||||
* mapped at (RelocDir->VirtualAddress)
|
||||
* - the virtual size (RelocDir->Size)
|
||||
*
|
||||
* The .reloc section (Section here) gives us some other things:
|
||||
* - the name! kind of. (Section->Name)
|
||||
* - the virtual size (Section->VirtualSize), which should be the same
|
||||
* as RelocDir->Size
|
||||
* - the virtual address (Section->VirtualAddress)
|
||||
* - the file section size (Section->SizeOfRawData), which is
|
||||
* a multiple of OptHdr->FileAlignment. Only useful for image
|
||||
* validation, not really useful for iteration bounds.
|
||||
* - the file address (Section->PointerToRawData)
|
||||
* - a bunch of stuff we don't use that's 0 in our binaries usually
|
||||
* - Flags (Section->Characteristics)
|
||||
*
|
||||
* and then the thing that's actually at the file address is an array
|
||||
* of EFI_IMAGE_BASE_RELOCATION structs with some values packed behind
|
||||
* them. The SizeOfBlock field of this structure includes the
|
||||
* structure itself, and adding it to that structure's address will
|
||||
* yield the next entry in the array.
|
||||
*/
|
||||
RelocBase = ImageAddress(orig, size, Section->PointerToRawData);
|
||||
/* RelocBaseEnd here is the address of the first entry /past/ the
|
||||
* table. */
|
||||
RelocBaseEnd = ImageAddress(orig, size, Section->PointerToRawData +
|
||||
context->RelocDir->Size - 1);
|
||||
|
||||
if (!RelocBase && !RelocBaseEnd)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
if (!RelocBase || !RelocBaseEnd) {
|
||||
perror(L"Reloc table overflows binary\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Adjust = (UINTN)data - context->ImageAddress;
|
||||
|
||||
if (Adjust == 0)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
while (RelocBase < RelocBaseEnd) {
|
||||
Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
|
||||
|
||||
if (RelocBase->SizeOfBlock == 0) {
|
||||
perror(L"Reloc %d block size 0 is invalid\n", n);
|
||||
return EFI_UNSUPPORTED;
|
||||
} else if (RelocBase->SizeOfBlock > context->RelocDir->Size) {
|
||||
perror(L"Reloc %d block size %d greater than reloc dir"
|
||||
"size %d, which is invalid\n", n,
|
||||
RelocBase->SizeOfBlock,
|
||||
context->RelocDir->Size);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
RelocEnd = (UINT16 *) ((char *) RelocBase + RelocBase->SizeOfBlock);
|
||||
if ((void *)RelocEnd < orig || (void *)RelocEnd > ImageEnd) {
|
||||
perror(L"Reloc %d entry overflows binary\n", n);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
FixupBase = ImageAddress(data, size, RelocBase->VirtualAddress);
|
||||
if (!FixupBase) {
|
||||
perror(L"Reloc %d Invalid fixupbase\n", n);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
while (Reloc < RelocEnd) {
|
||||
Fixup = FixupBase + (*Reloc & 0xFFF);
|
||||
switch ((*Reloc) >> 12) {
|
||||
case EFI_IMAGE_REL_BASED_ABSOLUTE:
|
||||
break;
|
||||
|
||||
case EFI_IMAGE_REL_BASED_HIGH:
|
||||
Fixup16 = (UINT16 *) Fixup;
|
||||
*Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
|
||||
break;
|
||||
|
||||
case EFI_IMAGE_REL_BASED_LOW:
|
||||
Fixup16 = (UINT16 *) Fixup;
|
||||
*Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust);
|
||||
break;
|
||||
|
||||
case EFI_IMAGE_REL_BASED_HIGHLOW:
|
||||
Fixup32 = (UINT32 *) Fixup;
|
||||
*Fixup32 = *Fixup32 + (UINT32) Adjust;
|
||||
break;
|
||||
|
||||
case EFI_IMAGE_REL_BASED_DIR64:
|
||||
Fixup64 = (UINT64 *) Fixup;
|
||||
*Fixup64 = *Fixup64 + (UINT64) Adjust;
|
||||
break;
|
||||
|
||||
default:
|
||||
perror(L"Reloc %d Unknown relocation\n", n);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
Reloc += 1;
|
||||
}
|
||||
RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
|
||||
n++;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
get_section_vma (UINTN section_num,
|
||||
char *buffer, size_t bufsz UNUSED,
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
char **basep, size_t *sizep,
|
||||
EFI_IMAGE_SECTION_HEADER **sectionp)
|
||||
{
|
||||
EFI_IMAGE_SECTION_HEADER *sections = context->FirstSection;
|
||||
EFI_IMAGE_SECTION_HEADER *section;
|
||||
char *base = NULL, *end = NULL;
|
||||
|
||||
if (section_num >= context->NumberOfSections)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
if (context->FirstSection == NULL) {
|
||||
perror(L"Invalid section %d requested\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
section = §ions[section_num];
|
||||
|
||||
base = ImageAddress (buffer, context->ImageSize, section->VirtualAddress);
|
||||
end = ImageAddress (buffer, context->ImageSize,
|
||||
section->VirtualAddress + section->Misc.VirtualSize - 1);
|
||||
|
||||
if (!(section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE)) {
|
||||
if (!base) {
|
||||
perror(L"Section %d has invalid base address\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
if (!end) {
|
||||
perror(L"Section %d has zero size\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(section->Characteristics & EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA) &&
|
||||
(section->VirtualAddress < context->SizeOfHeaders ||
|
||||
section->PointerToRawData < context->SizeOfHeaders)) {
|
||||
perror(L"Section %d is inside image headers\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (end < base) {
|
||||
perror(L"Section %d has negative size\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
*basep = base;
|
||||
*sizep = end - base;
|
||||
*sectionp = section;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
get_section_vma_by_name (char *name, size_t namesz,
|
||||
char *buffer, size_t bufsz,
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
char **basep, size_t *sizep,
|
||||
EFI_IMAGE_SECTION_HEADER **sectionp)
|
||||
{
|
||||
UINTN i;
|
||||
char namebuf[9];
|
||||
|
||||
if (!name || namesz == 0 || !buffer || bufsz < namesz || !context
|
||||
|| !basep || !sizep || !sectionp)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
/*
|
||||
* This code currently is only used for ".reloc\0\0" and
|
||||
* ".sbat\0\0\0", and it doesn't know how to look up longer section
|
||||
* names.
|
||||
*/
|
||||
if (namesz > 8)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
SetMem(namebuf, sizeof(namebuf), 0);
|
||||
CopyMem(namebuf, name, MIN(namesz, 8));
|
||||
|
||||
/*
|
||||
* Copy the executable's sections to their desired offsets
|
||||
*/
|
||||
for (i = 0; i < context->NumberOfSections; i++) {
|
||||
EFI_STATUS status;
|
||||
EFI_IMAGE_SECTION_HEADER *section = NULL;
|
||||
char *base = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
status = get_section_vma(i, buffer, bufsz, context, &base, &size, §ion);
|
||||
if (!EFI_ERROR(status)) {
|
||||
if (CompareMem(section->Name, namebuf, 8) == 0) {
|
||||
*basep = base;
|
||||
*sizep = size;
|
||||
*sectionp = section;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(status) {
|
||||
case EFI_NOT_FOUND:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* here's a chart:
|
||||
* i686 x86_64 aarch64
|
||||
* 64-on-64: nyet yes yes
|
||||
* 64-on-32: nyet yes nyet
|
||||
* 32-on-32: yes yes no
|
||||
*/
|
||||
static int
|
||||
allow_64_bit(void)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__aarch64__)
|
||||
return 1;
|
||||
#elif defined(__i386__) || defined(__i686__)
|
||||
/* Right now blindly assuming the kernel will correctly detect this
|
||||
* and /halt the system/ if you're not really on a 64-bit cpu */
|
||||
if (in_protocol)
|
||||
return 1;
|
||||
return 0;
|
||||
#else /* assuming everything else is 32-bit... */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
allow_32_bit(void)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
#if defined(ALLOW_32BIT_KERNEL_ON_X64)
|
||||
if (in_protocol)
|
||||
return 1;
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#elif defined(__i386__) || defined(__i686__)
|
||||
return 1;
|
||||
#elif defined(__aarch64__)
|
||||
return 0;
|
||||
#else /* assuming everything else is 32-bit... */
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
image_is_64_bit(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
|
||||
{
|
||||
/* .Magic is the same offset in all cases */
|
||||
if (PEHdr->Pe32.OptionalHeader.Magic
|
||||
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT16 machine_type =
|
||||
#if defined(__x86_64__)
|
||||
IMAGE_FILE_MACHINE_X64;
|
||||
#elif defined(__aarch64__)
|
||||
IMAGE_FILE_MACHINE_ARM64;
|
||||
#elif defined(__arm__)
|
||||
IMAGE_FILE_MACHINE_ARMTHUMB_MIXED;
|
||||
#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
|
||||
IMAGE_FILE_MACHINE_I386;
|
||||
#elif defined(__ia64__)
|
||||
IMAGE_FILE_MACHINE_IA64;
|
||||
#else
|
||||
#error this architecture is not supported by shim
|
||||
#endif
|
||||
|
||||
static int
|
||||
image_is_loadable(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
|
||||
{
|
||||
/* If the machine type doesn't match the binary, bail, unless
|
||||
* we're in an allowed 64-on-32 scenario */
|
||||
if (PEHdr->Pe32.FileHeader.Machine != machine_type) {
|
||||
if (!(machine_type == IMAGE_FILE_MACHINE_I386 &&
|
||||
PEHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64 &&
|
||||
allow_64_bit())) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's not a header type we recognize at all, bail */
|
||||
switch (PEHdr->Pe32Plus.OptionalHeader.Magic) {
|
||||
case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
|
||||
case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* and now just check for general 64-vs-32 compatibility */
|
||||
if (image_is_64_bit(PEHdr)) {
|
||||
if (allow_64_bit())
|
||||
return 1;
|
||||
} else {
|
||||
if (allow_32_bit())
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the binary header and grab appropriate information from it
|
||||
*/
|
||||
EFI_STATUS
|
||||
read_header(void *data, unsigned int datasize,
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT *context)
|
||||
{
|
||||
EFI_IMAGE_DOS_HEADER *DosHdr = data;
|
||||
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
|
||||
unsigned long HeaderWithoutDataDir, SectionHeaderOffset, OptHeaderSize;
|
||||
unsigned long FileAlignment = 0;
|
||||
UINT16 DllFlags;
|
||||
size_t dos_sz = 0;
|
||||
size_t tmpsz0, tmpsz1;
|
||||
|
||||
if (datasize < sizeof (*DosHdr)) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
|
||||
if (DosHdr->e_lfanew < sizeof (*DosHdr) ||
|
||||
DosHdr->e_lfanew > datasize - 4) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
dos_sz = DosHdr->e_lfanew;
|
||||
PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
|
||||
}
|
||||
|
||||
if (datasize - dos_sz < sizeof (PEHdr->Pe32)) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (image_is_64_bit(PEHdr) &&
|
||||
(datasize - dos_sz < sizeof (PEHdr->Pe32Plus))) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (!image_is_loadable(PEHdr)) {
|
||||
perror(L"Platform does not support this image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (image_is_64_bit(PEHdr)) {
|
||||
context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;
|
||||
context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
|
||||
context->ImageSize = PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
|
||||
context->SectionAlignment = PEHdr->Pe32Plus.OptionalHeader.SectionAlignment;
|
||||
FileAlignment = PEHdr->Pe32Plus.OptionalHeader.FileAlignment;
|
||||
OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64);
|
||||
} else {
|
||||
context->NumberOfRvaAndSizes = PEHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes;
|
||||
context->SizeOfHeaders = PEHdr->Pe32.OptionalHeader.SizeOfHeaders;
|
||||
context->ImageSize = (UINT64)PEHdr->Pe32.OptionalHeader.SizeOfImage;
|
||||
context->SectionAlignment = PEHdr->Pe32.OptionalHeader.SectionAlignment;
|
||||
FileAlignment = PEHdr->Pe32.OptionalHeader.FileAlignment;
|
||||
OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32);
|
||||
}
|
||||
|
||||
if (FileAlignment % 2 != 0) {
|
||||
perror(L"File Alignment is invalid (%d)\n", FileAlignment);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
if (FileAlignment == 0)
|
||||
FileAlignment = 0x200;
|
||||
if (context->SectionAlignment == 0)
|
||||
context->SectionAlignment = PAGE_SIZE;
|
||||
if (context->SectionAlignment < FileAlignment)
|
||||
context->SectionAlignment = FileAlignment;
|
||||
|
||||
context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections;
|
||||
|
||||
if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < context->NumberOfRvaAndSizes) {
|
||||
perror(L"Image header too large\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (checked_mul(sizeof(EFI_IMAGE_DATA_DIRECTORY), EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES, &tmpsz0) ||
|
||||
checked_sub(OptHeaderSize, tmpsz0, &HeaderWithoutDataDir) ||
|
||||
checked_sub((size_t)PEHdr->Pe32.FileHeader.SizeOfOptionalHeader, HeaderWithoutDataDir, &tmpsz0) ||
|
||||
checked_mul((size_t)context->NumberOfRvaAndSizes, sizeof (EFI_IMAGE_DATA_DIRECTORY), &tmpsz1) ||
|
||||
(tmpsz0 != tmpsz1)) {
|
||||
perror(L"Image header overflows data directory\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (checked_add((size_t)DosHdr->e_lfanew, sizeof(UINT32), &tmpsz0) ||
|
||||
checked_add(tmpsz0, sizeof(EFI_IMAGE_FILE_HEADER), &tmpsz0) ||
|
||||
checked_add(tmpsz0, PEHdr->Pe32.FileHeader.SizeOfOptionalHeader, &SectionHeaderOffset)) {
|
||||
perror(L"Image sections overflow image size\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (checked_sub((size_t)context->ImageSize, SectionHeaderOffset, &tmpsz0) ||
|
||||
(tmpsz0 / EFI_IMAGE_SIZEOF_SECTION_HEADER <= context->NumberOfSections)) {
|
||||
perror(L"Image sections overflow image size\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (checked_sub((size_t)context->SizeOfHeaders, SectionHeaderOffset, &tmpsz0) ||
|
||||
(tmpsz0 / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)context->NumberOfSections)) {
|
||||
perror(L"Image sections overflow section headers\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (checked_mul((size_t)context->NumberOfSections, sizeof(EFI_IMAGE_SECTION_HEADER), &tmpsz0) ||
|
||||
checked_add(tmpsz0, SectionHeaderOffset, &tmpsz0) ||
|
||||
(tmpsz0 > datasize)) {
|
||||
perror(L"Image sections overflow section headers\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (checked_sub((size_t)(uintptr_t)PEHdr, (size_t)(uintptr_t)data, &tmpsz0) ||
|
||||
checked_add(tmpsz0, sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION), &tmpsz0) ||
|
||||
(tmpsz0 > datasize)) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) {
|
||||
perror(L"Unsupported image type\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (PEHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) {
|
||||
perror(L"Unsupported image - Relocations have been stripped\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
context->PEHdr = PEHdr;
|
||||
|
||||
if (image_is_64_bit(PEHdr)) {
|
||||
context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase;
|
||||
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;
|
||||
}
|
||||
|
||||
if (checked_add((size_t)(uintptr_t)PEHdr, PEHdr->Pe32.FileHeader.SizeOfOptionalHeader, &tmpsz0) ||
|
||||
checked_add(tmpsz0, sizeof(UINT32), &tmpsz0) ||
|
||||
checked_add(tmpsz0, sizeof(EFI_IMAGE_FILE_HEADER), &tmpsz0)) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)(uintptr_t)tmpsz0;
|
||||
if ((uint64_t)(uintptr_t)(context->FirstSection)
|
||||
> (uint64_t)(uintptr_t)data + datasize) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (context->ImageSize < context->SizeOfHeaders) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (checked_sub((size_t)(uintptr_t)context->SecDir, (size_t)(uintptr_t)data, &tmpsz0) ||
|
||||
(tmpsz0 > datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (context->SecDir->VirtualAddress > datasize ||
|
||||
(context->SecDir->VirtualAddress == datasize &&
|
||||
context->SecDir->Size > 0)) {
|
||||
perror(L"Malformed security header\n");
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// vim:fenc=utf-8:tw=75:noet
|
544
pe.c
544
pe.c
@ -21,152 +21,6 @@
|
||||
|
||||
#include <Library/BaseCryptLib.h>
|
||||
|
||||
/*
|
||||
* Perform basic bounds checking of the intra-image pointers
|
||||
*/
|
||||
void *
|
||||
ImageAddress (void *image, uint64_t size, uint64_t address)
|
||||
{
|
||||
/* ensure our local pointer isn't bigger than our size */
|
||||
if (address > size)
|
||||
return NULL;
|
||||
|
||||
/* Insure our math won't overflow */
|
||||
if (UINT64_MAX - address < (uint64_t)(intptr_t)image)
|
||||
return NULL;
|
||||
|
||||
/* return the absolute pointer */
|
||||
return image + address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the actual relocation
|
||||
*/
|
||||
EFI_STATUS
|
||||
relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
EFI_IMAGE_SECTION_HEADER *Section,
|
||||
void *orig, void *data)
|
||||
{
|
||||
EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd;
|
||||
UINT64 Adjust;
|
||||
UINT16 *Reloc, *RelocEnd;
|
||||
char *Fixup, *FixupBase;
|
||||
UINT16 *Fixup16;
|
||||
UINT32 *Fixup32;
|
||||
UINT64 *Fixup64;
|
||||
int size = context->ImageSize;
|
||||
void *ImageEnd = (char *)orig + size;
|
||||
int n = 0;
|
||||
|
||||
/* Alright, so here's how this works:
|
||||
*
|
||||
* context->RelocDir gives us two things:
|
||||
* - the VA the table of base relocation blocks are (maybe) to be
|
||||
* mapped at (RelocDir->VirtualAddress)
|
||||
* - the virtual size (RelocDir->Size)
|
||||
*
|
||||
* The .reloc section (Section here) gives us some other things:
|
||||
* - the name! kind of. (Section->Name)
|
||||
* - the virtual size (Section->VirtualSize), which should be the same
|
||||
* as RelocDir->Size
|
||||
* - the virtual address (Section->VirtualAddress)
|
||||
* - the file section size (Section->SizeOfRawData), which is
|
||||
* a multiple of OptHdr->FileAlignment. Only useful for image
|
||||
* validation, not really useful for iteration bounds.
|
||||
* - the file address (Section->PointerToRawData)
|
||||
* - a bunch of stuff we don't use that's 0 in our binaries usually
|
||||
* - Flags (Section->Characteristics)
|
||||
*
|
||||
* and then the thing that's actually at the file address is an array
|
||||
* of EFI_IMAGE_BASE_RELOCATION structs with some values packed behind
|
||||
* them. The SizeOfBlock field of this structure includes the
|
||||
* structure itself, and adding it to that structure's address will
|
||||
* yield the next entry in the array.
|
||||
*/
|
||||
RelocBase = ImageAddress(orig, size, Section->PointerToRawData);
|
||||
/* RelocBaseEnd here is the address of the first entry /past/ the
|
||||
* table. */
|
||||
RelocBaseEnd = ImageAddress(orig, size, Section->PointerToRawData +
|
||||
Section->Misc.VirtualSize);
|
||||
|
||||
if (!RelocBase && !RelocBaseEnd)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
if (!RelocBase || !RelocBaseEnd) {
|
||||
perror(L"Reloc table overflows binary\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Adjust = (UINTN)data - context->ImageAddress;
|
||||
|
||||
if (Adjust == 0)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
while (RelocBase < RelocBaseEnd) {
|
||||
Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
|
||||
|
||||
if (RelocBase->SizeOfBlock == 0) {
|
||||
perror(L"Reloc %d block size 0 is invalid\n", n);
|
||||
return EFI_UNSUPPORTED;
|
||||
} else if (RelocBase->SizeOfBlock > context->RelocDir->Size) {
|
||||
perror(L"Reloc %d block size %d greater than reloc dir"
|
||||
"size %d, which is invalid\n", n,
|
||||
RelocBase->SizeOfBlock,
|
||||
context->RelocDir->Size);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
RelocEnd = (UINT16 *) ((char *) RelocBase + RelocBase->SizeOfBlock);
|
||||
if ((void *)RelocEnd < orig || (void *)RelocEnd > ImageEnd) {
|
||||
perror(L"Reloc %d entry overflows binary\n", n);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
FixupBase = ImageAddress(data, size, RelocBase->VirtualAddress);
|
||||
if (!FixupBase) {
|
||||
perror(L"Reloc %d Invalid fixupbase\n", n);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
while (Reloc < RelocEnd) {
|
||||
Fixup = FixupBase + (*Reloc & 0xFFF);
|
||||
switch ((*Reloc) >> 12) {
|
||||
case EFI_IMAGE_REL_BASED_ABSOLUTE:
|
||||
break;
|
||||
|
||||
case EFI_IMAGE_REL_BASED_HIGH:
|
||||
Fixup16 = (UINT16 *) Fixup;
|
||||
*Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
|
||||
break;
|
||||
|
||||
case EFI_IMAGE_REL_BASED_LOW:
|
||||
Fixup16 = (UINT16 *) Fixup;
|
||||
*Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust);
|
||||
break;
|
||||
|
||||
case EFI_IMAGE_REL_BASED_HIGHLOW:
|
||||
Fixup32 = (UINT32 *) Fixup;
|
||||
*Fixup32 = *Fixup32 + (UINT32) Adjust;
|
||||
break;
|
||||
|
||||
case EFI_IMAGE_REL_BASED_DIR64:
|
||||
Fixup64 = (UINT64 *) Fixup;
|
||||
*Fixup64 = *Fixup64 + (UINT64) Adjust;
|
||||
break;
|
||||
|
||||
default:
|
||||
perror(L"Reloc %d Unknown relocation\n", n);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
Reloc += 1;
|
||||
}
|
||||
RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
|
||||
n++;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
#define check_size_line(data, datasize_in, hashbase, hashsize, l) ({ \
|
||||
if ((unsigned long)hashbase > \
|
||||
(unsigned long)data + datasize_in) { \
|
||||
@ -185,113 +39,6 @@ relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
})
|
||||
#define check_size(d, ds, h, hs) check_size_line(d, ds, h, hs, __LINE__)
|
||||
|
||||
EFI_STATUS
|
||||
get_section_vma (UINTN section_num,
|
||||
char *buffer, size_t bufsz UNUSED,
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
char **basep, size_t *sizep,
|
||||
EFI_IMAGE_SECTION_HEADER **sectionp)
|
||||
{
|
||||
EFI_IMAGE_SECTION_HEADER *sections = context->FirstSection;
|
||||
EFI_IMAGE_SECTION_HEADER *section;
|
||||
char *base = NULL, *end = NULL;
|
||||
|
||||
if (section_num >= context->NumberOfSections)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
if (context->FirstSection == NULL) {
|
||||
perror(L"Invalid section %d requested\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
section = §ions[section_num];
|
||||
|
||||
base = ImageAddress (buffer, context->ImageSize, section->VirtualAddress);
|
||||
end = ImageAddress (buffer, context->ImageSize,
|
||||
section->VirtualAddress + section->Misc.VirtualSize - 1);
|
||||
|
||||
if (!(section->Characteristics & EFI_IMAGE_SCN_MEM_DISCARDABLE)) {
|
||||
if (!base) {
|
||||
perror(L"Section %d has invalid base address\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
if (!end) {
|
||||
perror(L"Section %d has zero size\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(section->Characteristics & EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA) &&
|
||||
(section->VirtualAddress < context->SizeOfHeaders ||
|
||||
section->PointerToRawData < context->SizeOfHeaders)) {
|
||||
perror(L"Section %d is inside image headers\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (end < base) {
|
||||
perror(L"Section %d has negative size\n", section_num);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
*basep = base;
|
||||
*sizep = end - base;
|
||||
*sectionp = section;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
get_section_vma_by_name (char *name, size_t namesz,
|
||||
char *buffer, size_t bufsz,
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
||||
char **basep, size_t *sizep,
|
||||
EFI_IMAGE_SECTION_HEADER **sectionp)
|
||||
{
|
||||
UINTN i;
|
||||
char namebuf[9];
|
||||
|
||||
if (!name || namesz == 0 || !buffer || bufsz < namesz || !context
|
||||
|| !basep || !sizep || !sectionp)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
/*
|
||||
* This code currently is only used for ".reloc\0\0" and
|
||||
* ".sbat\0\0\0", and it doesn't know how to look up longer section
|
||||
* names.
|
||||
*/
|
||||
if (namesz > 8)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
SetMem(namebuf, sizeof(namebuf), 0);
|
||||
CopyMem(namebuf, name, MIN(namesz, 8));
|
||||
|
||||
/*
|
||||
* Copy the executable's sections to their desired offsets
|
||||
*/
|
||||
for (i = 0; i < context->NumberOfSections; i++) {
|
||||
EFI_STATUS status;
|
||||
EFI_IMAGE_SECTION_HEADER *section = NULL;
|
||||
char *base = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
status = get_section_vma(i, buffer, bufsz, context, &base, &size, §ion);
|
||||
if (!EFI_ERROR(status)) {
|
||||
if (CompareMem(section->Name, namebuf, 8) == 0) {
|
||||
*basep = base;
|
||||
*sizep = size;
|
||||
*sectionp = section;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(status) {
|
||||
case EFI_NOT_FOUND:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the SHA1 and SHA256 hashes of a binary
|
||||
@ -585,249 +332,6 @@ done:
|
||||
return efi_status;
|
||||
}
|
||||
|
||||
/* here's a chart:
|
||||
* i686 x86_64 aarch64
|
||||
* 64-on-64: nyet yes yes
|
||||
* 64-on-32: nyet yes nyet
|
||||
* 32-on-32: yes yes no
|
||||
*/
|
||||
static int
|
||||
allow_64_bit(void)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__aarch64__)
|
||||
return 1;
|
||||
#elif defined(__i386__) || defined(__i686__)
|
||||
/* Right now blindly assuming the kernel will correctly detect this
|
||||
* and /halt the system/ if you're not really on a 64-bit cpu */
|
||||
if (in_protocol)
|
||||
return 1;
|
||||
return 0;
|
||||
#else /* assuming everything else is 32-bit... */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
allow_32_bit(void)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
#if defined(ALLOW_32BIT_KERNEL_ON_X64)
|
||||
if (in_protocol)
|
||||
return 1;
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#elif defined(__i386__) || defined(__i686__)
|
||||
return 1;
|
||||
#elif defined(__aarch64__)
|
||||
return 0;
|
||||
#else /* assuming everything else is 32-bit... */
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
image_is_64_bit(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
|
||||
{
|
||||
/* .Magic is the same offset in all cases */
|
||||
if (PEHdr->Pe32Plus.OptionalHeader.Magic
|
||||
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const UINT16 machine_type =
|
||||
#if defined(__x86_64__)
|
||||
IMAGE_FILE_MACHINE_X64;
|
||||
#elif defined(__aarch64__)
|
||||
IMAGE_FILE_MACHINE_ARM64;
|
||||
#elif defined(__arm__)
|
||||
IMAGE_FILE_MACHINE_ARMTHUMB_MIXED;
|
||||
#elif defined(__i386__) || defined(__i486__) || defined(__i686__)
|
||||
IMAGE_FILE_MACHINE_I386;
|
||||
#elif defined(__ia64__)
|
||||
IMAGE_FILE_MACHINE_IA64;
|
||||
#else
|
||||
#error this architecture is not supported by shim
|
||||
#endif
|
||||
|
||||
static int
|
||||
image_is_loadable(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
|
||||
{
|
||||
/* If the machine type doesn't match the binary, bail, unless
|
||||
* we're in an allowed 64-on-32 scenario */
|
||||
if (PEHdr->Pe32.FileHeader.Machine != machine_type) {
|
||||
if (!(machine_type == IMAGE_FILE_MACHINE_I386 &&
|
||||
PEHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64 &&
|
||||
allow_64_bit())) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's not a header type we recognize at all, bail */
|
||||
switch (PEHdr->Pe32Plus.OptionalHeader.Magic) {
|
||||
case EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC:
|
||||
case EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* and now just check for general 64-vs-32 compatibility */
|
||||
if (image_is_64_bit(PEHdr)) {
|
||||
if (allow_64_bit())
|
||||
return 1;
|
||||
} else {
|
||||
if (allow_32_bit())
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the binary header and grab appropriate information from it
|
||||
*/
|
||||
EFI_STATUS
|
||||
read_header(void *data, unsigned int datasize,
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT *context)
|
||||
{
|
||||
EFI_IMAGE_DOS_HEADER *DosHdr = data;
|
||||
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");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
|
||||
PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
|
||||
|
||||
if (!image_is_loadable(PEHdr)) {
|
||||
perror(L"Platform does not support this image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (image_is_64_bit(PEHdr)) {
|
||||
context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;
|
||||
context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders;
|
||||
context->ImageSize = PEHdr->Pe32Plus.OptionalHeader.SizeOfImage;
|
||||
context->SectionAlignment = PEHdr->Pe32Plus.OptionalHeader.SectionAlignment;
|
||||
FileAlignment = PEHdr->Pe32Plus.OptionalHeader.FileAlignment;
|
||||
OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64);
|
||||
} else {
|
||||
context->NumberOfRvaAndSizes = PEHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes;
|
||||
context->SizeOfHeaders = PEHdr->Pe32.OptionalHeader.SizeOfHeaders;
|
||||
context->ImageSize = (UINT64)PEHdr->Pe32.OptionalHeader.SizeOfImage;
|
||||
context->SectionAlignment = PEHdr->Pe32.OptionalHeader.SectionAlignment;
|
||||
FileAlignment = PEHdr->Pe32.OptionalHeader.FileAlignment;
|
||||
OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32);
|
||||
}
|
||||
|
||||
if (FileAlignment % 2 != 0) {
|
||||
perror(L"File Alignment is invalid (%d)\n", FileAlignment);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
if (FileAlignment == 0)
|
||||
FileAlignment = 0x200;
|
||||
if (context->SectionAlignment == 0)
|
||||
context->SectionAlignment = PAGE_SIZE;
|
||||
if (context->SectionAlignment < FileAlignment)
|
||||
context->SectionAlignment = FileAlignment;
|
||||
|
||||
context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections;
|
||||
|
||||
if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < context->NumberOfRvaAndSizes) {
|
||||
perror(L"Image header too small\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
HeaderWithoutDataDir = OptHeaderSize
|
||||
- sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
|
||||
if (((UINT32)PEHdr->Pe32.FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=
|
||||
context->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) {
|
||||
perror(L"Image header overflows data directory\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
SectionHeaderOffset = DosHdr->e_lfanew
|
||||
+ sizeof (UINT32)
|
||||
+ sizeof (EFI_IMAGE_FILE_HEADER)
|
||||
+ PEHdr->Pe32.FileHeader.SizeOfOptionalHeader;
|
||||
if (((UINT32)context->ImageSize - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER
|
||||
<= context->NumberOfSections) {
|
||||
perror(L"Image sections overflow image size\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if ((context->SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER
|
||||
< (UINT32)context->NumberOfSections) {
|
||||
perror(L"Image sections overflow section headers\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if ((((UINT8 *)PEHdr - (UINT8 *)data) + sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION)) > datasize) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) {
|
||||
perror(L"Unsupported image type\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (PEHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) {
|
||||
perror(L"Unsupported image - Relocations have been stripped\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
context->PEHdr = PEHdr;
|
||||
|
||||
if (image_is_64_bit(PEHdr)) {
|
||||
context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase;
|
||||
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) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if ((unsigned long)((UINT8 *)context->SecDir - (UINT8 *)data) >
|
||||
(datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
|
||||
perror(L"Invalid image\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (context->SecDir->VirtualAddress > datasize ||
|
||||
(context->SecDir->VirtualAddress == datasize &&
|
||||
context->SecDir->Size > 0)) {
|
||||
perror(L"Malformed security header\n");
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
verify_sbat_section(char *SBATBase, size_t SBATSize)
|
||||
{
|
||||
@ -851,7 +355,11 @@ verify_sbat_section(char *SBATBase, size_t SBATSize)
|
||||
return in_protocol ? EFI_SUCCESS : EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
|
||||
sbat_size = SBATSize + 1;
|
||||
if (checked_add(SBATSize, 1, &sbat_size)) {
|
||||
dprint(L"SBATSize + 1 would overflow\n");
|
||||
return EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
|
||||
sbat_data = AllocatePool(sbat_size);
|
||||
if (!sbat_data) {
|
||||
console_print(L"Failed to allocate .sbat section buffer\n");
|
||||
@ -937,7 +445,7 @@ get_mem_attrs (uintptr_t addr, size_t size, uint64_t *attrs)
|
||||
if (EFI_ERROR(efi_status) || !proto)
|
||||
return efi_status;
|
||||
|
||||
if (physaddr & 0xfff || size & 0xfff || size == 0 || attrs == NULL) {
|
||||
if (!IS_PAGE_ALIGNED(physaddr) || !IS_PAGE_ALIGNED(size) || 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),
|
||||
@ -971,7 +479,7 @@ update_mem_attrs(uintptr_t addr, uint64_t size,
|
||||
(unsigned long long)addr, (unsigned long long)size,
|
||||
&before, efi_status);
|
||||
|
||||
if (physaddr & 0xfff || size & 0xfff || size == 0) {
|
||||
if (!IS_PAGE_ALIGNED(physaddr) || !IS_PAGE_ALIGNED(size) || 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),
|
||||
@ -990,10 +498,20 @@ update_mem_attrs(uintptr_t addr, uint64_t size,
|
||||
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)
|
||||
if (uefi_set_attrs) {
|
||||
efi_status = proto->SetMemoryAttributes(proto, physaddr, size, uefi_set_attrs);
|
||||
if (!EFI_ERROR(efi_status) && uefi_clear_attrs)
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
dprint(L"Failed to set memory attrs:0x%0x physaddr:0x%llx size:0x%0lx status:%r\n",
|
||||
uefi_set_attrs, physaddr, size, efi_status);
|
||||
}
|
||||
}
|
||||
if (!EFI_ERROR(efi_status) && uefi_clear_attrs) {
|
||||
efi_status = proto->ClearMemoryAttributes(proto, physaddr, size, uefi_clear_attrs);
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
dprint(L"Failed to clear memory attrs:0x%0x physaddr:0x%llx size:0x%0lx status:%r\n",
|
||||
uefi_clear_attrs, physaddr, size, efi_status);
|
||||
}
|
||||
}
|
||||
ret = efi_status;
|
||||
|
||||
efi_status = get_mem_attrs (addr, size, &after);
|
||||
@ -1243,6 +761,7 @@ handle_image (void *data, unsigned int datasize,
|
||||
(Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) &&
|
||||
(mok_policy & MOK_POLICY_REQUIRE_NX)) {
|
||||
perror(L"Section %d is writable and executable\n", i);
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@ -1268,6 +787,7 @@ handle_image (void *data, unsigned int datasize,
|
||||
if (CompareMem(Section->Name, ".reloc\0\0", 8) == 0) {
|
||||
if (RelocSection) {
|
||||
perror(L"Image has multiple relocation sections\n");
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
/* If it has nonzero sizes, and our bounds check
|
||||
@ -1277,8 +797,12 @@ handle_image (void *data, unsigned int datasize,
|
||||
Section->Misc.VirtualSize &&
|
||||
base && end &&
|
||||
RelocBase == base &&
|
||||
RelocBaseEnd == end) {
|
||||
RelocBaseEnd <= end) {
|
||||
RelocSection = Section;
|
||||
} else {
|
||||
perror(L"Relocation section is invalid \n");
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1288,10 +812,12 @@ handle_image (void *data, unsigned int datasize,
|
||||
|
||||
if (!base) {
|
||||
perror(L"Section %d has invalid base address\n", i);
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
if (!end) {
|
||||
perror(L"Section %d has zero size\n", i);
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@ -1299,6 +825,7 @@ handle_image (void *data, unsigned int datasize,
|
||||
(Section->VirtualAddress < context.SizeOfHeaders ||
|
||||
Section->PointerToRawData < context.SizeOfHeaders)) {
|
||||
perror(L"Section %d is inside image headers\n", i);
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@ -1307,6 +834,7 @@ handle_image (void *data, unsigned int datasize,
|
||||
} else {
|
||||
if (Section->PointerToRawData < context.SizeOfHeaders) {
|
||||
perror(L"Section %d is inside image headers\n", i);
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@ -1324,7 +852,7 @@ handle_image (void *data, unsigned int datasize,
|
||||
|
||||
if (context.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
|
||||
perror(L"Image has no relocation entry\n");
|
||||
FreePool(buffer);
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@ -1337,7 +865,7 @@ handle_image (void *data, unsigned int datasize,
|
||||
|
||||
if (EFI_ERROR(efi_status)) {
|
||||
perror(L"Relocation failed: %r\n", efi_status);
|
||||
FreePool(buffer);
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return efi_status;
|
||||
}
|
||||
}
|
||||
@ -1372,7 +900,11 @@ handle_image (void *data, unsigned int datasize,
|
||||
+ Section->Misc.VirtualSize - 1);
|
||||
|
||||
addr = (uintptr_t)base;
|
||||
length = (uintptr_t)end - (uintptr_t)base + 1;
|
||||
// Align the length up to PAGE_SIZE. This is required because
|
||||
// platforms generally set memory attributes at page
|
||||
// granularity, but the section length (unlike the section
|
||||
// address) is not required to be aligned.
|
||||
length = ALIGN_VALUE((uintptr_t)end - (uintptr_t)base + 1, PAGE_SIZE);
|
||||
|
||||
if (Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) {
|
||||
set_attrs |= MEM_ATTR_W;
|
||||
@ -1399,10 +931,12 @@ handle_image (void *data, unsigned int datasize,
|
||||
|
||||
if (!found_entry_point) {
|
||||
perror(L"Entry point is not within sections\n");
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
if (found_entry_point > 1) {
|
||||
perror(L"%d sections contain entry point\n", found_entry_point);
|
||||
BS->FreePages(*alloc_address, *alloc_pages);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user