Commit Graph

329 Commits

Author SHA1 Message Date
Peter Jones
0e7ba5947e Generate a sane PE header on shim, fallback, and MokManager.
It turns out a7249a65 was masking a second problem - on some binaries,
when we actually don't have any base relocations at all, binutils'
"objcopy --target efi-app-x86_64" is generating a PE header with a base
relocations pointer that happily points into the middle of our text
section.  So with shim processing base relocations correctly, it refuses
to load those binaries.

For example, on one binary I just built:

00000130  00 a0 00 00 0a 00 00 00  00 00 00 00 00 00 00 00 |................|

which says there's a Base Relocation Table at 0xa000 that's 0xa bytes long.
That's here:

0000a000  58 00 29 00 00 00 00 00  48 00 44 00 28 00 50 00 |X.).....H.D.(.P.|
0000a010  61 00 72 00 74 00 25 00  64 00 2c 00 53 00 69 00 |a.r.t.%.d.,.S.i.|
0000a020  67 00 25 00 67 00 29 00  00 00 00 00 00 00 00 00 |g.%.g.).........|
0000a030  48 00 44 00 28 00 50 00  61 00 72 00 74 00 25 00 |H.D.(.P.a.r.t.%.|

So the table is:

0000a000  58 00 29 00 00 00 00 00  48 00                   |X.).....H.      |

That wouldn't be so bad, except those binaries are MokManager.efi,
fallback.efi, and shim.efi, and sometimes they're .reloc, which we're
actually trying to handle correctly now because grub builds with a real
and valid .reloc table.  So though I didn't think there was any hair
left on this yak, more shaving ensues.

With this change, instead of letting objcopy do whatever it likes, we
switch to "-O binary" and merely link in a header that's appropriate for
our binaries.  This is the same method Ard wrote for aarch64, and it
seems to work fine in either place (modulo some minor changes.)

At some point this should be merged into gnu-efi instead of carrying our
own crt0-efi-x86_64.S, but that's a less immediate problem.

I did not need this problem.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-09-21 16:25:27 -04:00
Peter Jones
eb72a4c3a1 Fix our "in_protocol" printing.
When I merged 4bfb13d and fixed the conflicts, I managed to make the
in_protocol test exactly backwards, so that's why we don't currently see
error messages.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-09-21 16:25:27 -04:00
Peter Jones
3d1cdbc4e3 Don't call AuthenticodeVerify if vendor_cert_size is 0.
Actually check the size of our vendor cert quite early, so that there's
no confusion as to what's going on.

This isn't strictly necessary, in that in all cases if vendor_cert_size
is 0, then AuthenticodeVerify -> Pkcs7Verify() -> d2i_X509() will result
in a NULL "Cert", and it will return FALSE, and we'll reject the
signature, but better to avoid all that code in the first place.  Belt
and suspenders and whatnot.

Based on a patch from https://github.com/TBOpen .

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-09-21 16:25:27 -04:00
Peter Jones
f04d50b747 Validate computed hash bases/hash sizes more thoroughly.
I screwed one of these up when working on 750584c, and it's a real pain
to figure out, so that means we should be validating them.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-09-21 16:25:20 -04:00
Peter Jones
750584c207 Make 64-on-32 maybe work on x86_64.
This is mostly based on a patch (https://github.com/mjg59/shim/issues/30)
from https://github.com/TBOpen , which refactors our __LP64__
tests to be tests of the header magic instead.  I've simplified things
by using what we've pre-loaded into "context" and making some helper
functions so the conditionals in most of the code say what they do,
instead of how they work.

Note that we're only allowing that from in_protocol's loader - that is,
we'll let 64-bit grub load a 32-bit kernel or 32-bit grub load a 64-bit
kernel, but 32-bit shim isn't loading a 64-bit grub.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-09-21 13:12:03 -04:00
Peter Jones
a7249a65af Actually refer to the base relocation table of our loaded image.
Currently when we process base relocations, we get the correct Data
Directory pointer from the headers (context->RelocDir), and that header
has been copied into our pristine allocated image when we copied up to
SizeOfHeaders.  But the data it points to has not been mirrored in to
the new image, so it is whatever data AllocPool() gave us.

This patch changes relocate_coff() to refer to the base relocation table
from the image we loaded from disk, but apply the fixups to the new
copy.

I have no idea how x86_64 worked without this, but I can't make aarch64
work without it.  I also don't know how Ard or Leif have seen aarch64
work.  Maybe they haven't?  Leif indicated on irc that they may have
only tested shim with simple "hello world" applications from gnu-efi;
they are certainly much less complex than grub.efi, and are generated
through a different linking process.

My only theory is that we're getting recycled data there pretty reliably
that just makes us /not/ process any relocations, but since our
ImageBase is 0, and I don't think we ever load grub with 0 as its base
virtual address, that doesn't follow.  I'm open to any other ideas
anybody has.

I do know that on x86_64 (and presumably aarch64 as well), we don't
actually start seeing *symptoms* of this bug until the first chunk[0] of
94c9a77f is applied[1].  Once that is applied, relocate_coff() starts
seeing zero[2] for both RelocBase->VirtualAddress and
RelocBase->SizeOfBlock, because RelocBase is a (generated, relative)
pointer that only makes sense in the context of the original binary, not
our partial copy.  Since RelocBase->SizeOfBlock is tested first,
relocate_base() gives us "Reloc block size is invalid"[3] and returns
EFI_UNSUPPORTED.  At that point shim exits with an error.

[0] The second chunk of 94c9a77f patch makes no difference on this
    issue.
[1] I don't see why at all.
[2] Which could really be any value since it's AllocatePool() and not
    AllocateZeroPool() results, but 0 is all I've observed; I think
    AllocatePool() has simply never recycled any memory in my test
    cases.
[3] which is silent because perror() tries to avoid talking because that
    has caused much crashing in the past; work needs to go in to 0.9 for
    this.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-09-19 09:30:26 -04:00
Peter Jones
fa2a35ce78 Make sure we don't try to load a binary from a different arch.
Since in theory you could, for example, get an x86_64 binary signed that
also behaves as an ARM executable, we should be checking this before
people build on other architectures.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-08-27 16:40:57 -04:00
Peter Jones
32f10548cd Don't name something exit().
On aarch64 due to some terrifying include chain we wind up with
Cryptlib's definition of exit here.  I'm not a glutton for punishment,
so I'm just changing the name so it's not coliding.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-08-27 16:40:57 -04:00
Ard Biesheuvel
94c9a77f65 Handle empty .reloc section in PE/COFF loader
On archs where no EFI aware objcopy is available, the generated PE/COFF
header contains a .reloc section which is completely empty. Handle this by
- returning early from relocate_coff() with EFI_SUCCESS,
- ignoring discardable sections in the section loader.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2014-08-27 11:49:39 -04:00
Peter Jones
14acaa4a33 Fix typo from Ard's old tree 32-bit ARM patch.
We don't need to .data entries; the second one should be .data*.  He's
since fixed this in his tree, but I'd already pulled it and pushed to
master.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-08-27 11:49:39 -04:00
Gary Ching-Pang Lin
21f96e5863 Update openssl to 0.9.8zb
Also update to Tiano Cryptlib r15802 and remove the execute mode
bits from the C and header files of openssl
2014-08-19 14:20:23 -04:00
Ard Biesheuvel
fa525bc463 Add support for 32-bit ARM
This adds support for building the shim for a 32-bit ARM UEFI environment.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2014-08-12 10:54:05 -04:00
Ard Biesheuvel
04cba93d64 Add support for 64-bit ARM (AArch64)
This adds support for building the shim for a 64-bit ARM UEFI environment.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2014-08-12 10:54:05 -04:00
Ard Biesheuvel
99d7b5e858 Factor out x86-isms and add cross compile support
This patch cleans up and refactors the Makefiles to better allow new
architectures to be added:
- remove unused Makefile definitions
- import Makefile definitions from top level rather than redefining
- move x86 specific CFLAGS to inside ifeq() blocks
- remove x86 inline asm
- allow $(FORMAT) to be overridden: this is necessary as there exists no
  EFI or PE/COFF aware objcopy for ARM

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2014-08-12 10:54:05 -04:00
Ard Biesheuvel
77cdb40423 unhook_system_services: bail on systab == NULL
Prevent unhook_system_services() from dereferencing a NULL systab, which
may occur if hook_system_services() has never been called.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2014-08-12 10:54:05 -04:00
Ard Biesheuvel
a30276e095 CryptLib: undefine va_arg and friends before redefining them
Upstream GNU-EFI contains changes to efistdarg.h resulting in the va_start,
va_arg and va_end macros to be #defined unconditionally. Make sure we #undef
them before overriding the definitions.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
2014-08-12 10:54:05 -04:00
Peter Jones
81ee561dde Replace build instructions in README with something not completely wrong.
These were really, really out of date.
2014-07-21 16:15:07 -04:00
Gary Ching-Pang Lin
76f8050ff6 Update openssl to 0.9.8za
Also update to Tiano Cryptlib r15638
2014-07-14 09:03:36 -04:00
Gary Ching-Pang Lin
e5f161147d Simplify the checking of SB and DB states
MokSBState and MokDBState are just 1 byte variables, so a UINT8
local variable is sufficient to include the content.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>

Conflicts:
	shim.c
2014-06-25 10:58:23 -04:00
Peter Jones
eb4cb6a509 Make sure we default to assuming we're locked down.
If "SecureBoot" exists but "SetupMode" does not, assume "SetupMode" says
we're not in Setup Mode.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-06-25 10:55:56 -04:00
Gary Ching-Pang Lin
868b372115 Check the secure variables with the lib functions
There are functions defined in lib to check the secure variables.
Use the functions to shun the duplicate code.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>

Conflicts:
	shim.c
2014-06-25 10:55:12 -04:00
Peter Jones
86173dba42 Explain the logic in secure_mode() better.
I was getting confused reading it, and I wrote it, so clearly it needs
more commentry.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-06-25 10:46:52 -04:00
Gary Ching-Pang Lin
c36d88cb16 Free the string from DevicePathToStr
Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>

Conflicts:
	shim.c
2014-06-25 10:33:25 -04:00
Gary Ching-Pang Lin
4bfb13d803 Silence the functions of shim protocol
When grub2 invokes the functions of shim protocol in gfx mode,
OutputString in shim could distort the screen.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>

Conflicts:
	shim.c

(modified by pjones to include some newer Prints that weren't there when
Gary did the initial work here.)
2014-06-25 10:30:38 -04:00
Gary Ching-Pang Lin
8bd7bad4b7 Remove the duplicate calls in lib/console.c
Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-06-25 10:15:31 -04:00
Gary Ching-Pang Lin
dc8fc734b8 No newline for console_notify
The newlines are for Print(), not console_notify().

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>

Conflicts:
	shim.c
2014-06-25 10:12:43 -04:00
Gary Ching-Pang Lin
09283f08f0 Exclude ca.crt while signing EFI images
If ca.crt was added into the certificate database, ca.crt would be the first
certificate in the signature. Because shim couldn't verify ca.crt with the
embedded shim.cer, it failed to load MokManager.efi.signed and
fallback.efi.signed.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-06-25 10:03:08 -04:00
Gary Ching-Pang Lin
22254e2633 MokManager: handle the error status from ReadKeyStroke
On some machines, even though the key event was signaled, ReadKeyStroke
still got EFI_NOT_READY. This commit handles the error status to avoid
console_get_keystroke from returning unexpected keys.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>

Conflicts:
	MokManager.c
2014-06-25 10:02:18 -04:00
Gary Ching-Pang Lin
53a8f8721c MokManager: delete the BS+NV variables the right way
LibDeleteVariable assumes that the variable is RT+NV and it
won't work on a BS+NV variable.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-06-25 09:57:10 -04:00
Gary Ching-Pang Lin
78aaad3003 Remove grubpath in generate_path()
The variable is not used anymore.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-06-25 09:56:27 -04:00
Gary Ching-Pang Lin
5f18e2e364 Check the first 4 bytes of the certificate
A non-DER encoding x509 certificate may be mistakenly enrolled into
db or MokList. This commit checks the first 4 bytes of the certificate
to ensure that it's DER encoding.

This commit also removes the iteration of the x509 signature list.
Per UEFI SPEC, each x509 signature list contains only one x509 certificate.
Besides, the size of certificate is incorrect. The size of the header must
be substracted from the signature size.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-06-25 09:55:49 -04:00
Gary Ching-Pang Lin
f500a8742c Fetch the netboot image from the same device
The previous strategy is to locate the first available PXE_BASE_CODE
protocol and to fetch the second stage image from it, and this may
cause shim to fetch the wrong second stage image, i.e. grub.efi.

Consider the machine with the following boot order:
1. PXE Boot
2. Hard Drive

Assume that the EFI image, e.g. bootx64.efi, in the PXE server is
broken, then "PXE Boot" will fail and fallback to "Hard Drive". While
shim.efi in "Hard Drive" is loaded, it will find the PXE protocol is
available and fetch grub.efi from the PXE server, not grub.efi in the
disk.

This commit checks the DeviceHandle from Loaded Image. If the device
supports PXE, then shim fetches grub.efi with the PXE protocol. Otherwise,
shim loads grub.efi from the disk.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-06-25 09:53:23 -04:00
Gary Ching-Pang Lin
0ba09477af [fallback] Try to boot the first boot option anyway
Some UEFI implementations never care the boot options, so the
restored boot options could be just ignored and this results in
endless reboot. To avoid this situation, this commit makes
fallback.efi to load the first matched boot option even if there
is no boot option to be restored. It may not be perfect, but at
least the bootloader is loaded...

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-05-13 13:30:07 -04:00
Gary Ching-Pang Lin
4aac8a1179 [fallback] Fix the data size for boot option comparison
Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-05-13 13:24:12 -04:00
Gary Ching-Pang Lin
382a0b66e6 [fallback] Avoid duplicate old BootOrder
set_boot_order() already copies the old BootOrder to the variable,
bootorder. Besides, we can adjust BootOrder when adding the newly
generated boot option. So, we don't have to copy the old one again
in update_boot_order(). This avoid the duplicate entries in BootOrder.

Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
2014-05-13 13:23:41 -04:00
Peter Jones
5103c3b368 Get rid of SectionCache in generate_hash(), it is unused.
Signed-off-by: Peter Jones <pjones@redhat.com>
2014-04-11 15:07:45 -04:00
Peter Jones
a876037a0d Kees' patch missed the offset adjustment to PEHdr.
In read_header, we adjust context->PEHdr's address by doshdr->e_lfanew.
If we're going to recompute that address, we have to adjust it here
too.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-04-11 15:05:24 -04:00
Kees Cook
5495694c04 additional bounds-checking on section sizes
This adds additional bounds-checking on the section sizes. Also adds
-Wsign-compare to the Makefile and replaces some signed variables with
unsigned counteparts for robustness.

Signed-off-by: Kees Cook <kees@ubuntu.com>
2014-04-11 14:41:22 -04:00
Peter Jones
06495f692f Allow fallback to use the system's LoadImage/StartImage .
Track use of the system's LoadImage(), and when the next StartImage()
call is for an image the system verified, allow that to count as
participating, since it has been verified by the system's db.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-02-14 17:48:01 -05:00
Peter Jones
a0bb7822bc Add a failure case to the test plan and fix an ordering error.
Signed-off-by: Peter Jones <pjones@redhat.com>
2014-02-14 17:48:01 -05:00
Peter Jones
ac356a0e77 Add a preliminary test plan.
Because you know you wanted a test plan.  You feel it deeply inside.

Note that none of the /negative/ cases are tested yet.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-02-14 14:08:30 -05:00
Peter Jones
894a2738d6 [fallback] Attempt to re-use existing entries when possible.
Some firmwares seem to ignore our boot entries and put their fallback
entries back on top.  Right now that results in a lot of boot entries
for our stuff, a la https://bugzilla.redhat.com/show_bug.cgi?id=995834 .

Instead of that happening, if we simply find existing entries that match
the entry we would create and move them to the top of the boot order,
the machine will continue to operate in failure mode (which we can't
avoid), but at least we won't create thousands of extra entries.

Signed-off-by: Peter Jones <pjones@redhat.com>
2014-01-31 10:31:10 -05:00
Peter Jones
dfd6c73a21 [fallback] For HD() device paths, use just the media node and later.
UEFI 2.x section 3.1.2 provides for "short-form device path", where the
first element specified is a "hard drive media device path", so that you
can move a disk around on different buses without invalidating your
device path.  Fallback has not been using this option, though in most
cases efibootmgr has.

Note that we still keep the full device path, because LoadImage()
isn't necessarily the layer where HD() works - one some systems BDS is
responsible for resolving the full path and passes that to LoadImage()
instead.  So we have to do LoadImage() with the full path.
2014-01-31 10:30:36 -05:00
Peter Jones
293f28d1fe Error check the right thing in get_variable_attr() when allocating.
Signed-off-by: Peter Jones <pjones@redhat.com>
2013-11-21 11:48:24 -05:00
Peter Jones
3a7feeff6c Rewrite directory traversal allocation path so coverity can grok it.
The things we do for our tools.  In this case, make the AllocatePool()
happen outside of a conditional, even though that conditional will
always bee satisfied.  This way coverity won't think we're setting fi
to NULL and passing it to StrCaseCmp.

Signed-off-by: Peter Jones <pjones@redhat.com>
2013-11-21 11:48:24 -05:00
Peter Jones
4dbef508ab Initialize entries before we pass it to another function.
Coverity scan noticed that entries is uninitialized when we pass its
location to another function.

Signed-off-by: Peter Jones <pjones@redhat.com>
2013-11-21 11:48:24 -05:00
Peter Jones
af25679e16 Fix wrong sizeof().
CHAR16* vs CHAR16**, so the result is the same on all platforms.

Detected by coverity.

Signed-off-by: Peter Jones <pjones@redhat.com>
2013-11-21 11:48:24 -05:00
Peter Jones
27129a5a05 Lengths that might be -1 can't be unsigned, Peter.
Signed-off-by: Peter Jones <pjones@redhat.com>
2013-11-21 11:48:24 -05:00
Peter Jones
e62b69a5b0 Fix path generation for Dhcpv4 bootloader.
Right now we always look for e.g. "\grubx64.efi", which is completely
wrong.  This makes it look for the path shim was loaded from and modify
that to end in a sanitized version of our default loader name.

Resolves: rhbz#1032583

Signed-off-by: Peter Jones <pjones@redhat.com>
2013-11-21 11:48:24 -05:00
Matthew Garrett
8b48ec5c70 Don't hook system services if shim has no built-in keys
Shim should only need to enforce its security policy when its launching
binaries signed with its built-in key. Binaries signed by keys in db or
Mokdb should be able to rely on their own security policy.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
2013-11-19 10:20:34 -05:00