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