diff --git a/.shim.metadata b/.shim.metadata index 7f2a942..a6c53d4 100644 --- a/.shim.metadata +++ b/.shim.metadata @@ -1,7 +1,3 @@ -d193e3e3cf19148c8ac867de8e1ae39f9b66afec SOURCES/DB.auth 7686b4eb198c0efb70dae703dc8d71885d462ab0 SOURCES/0.7.tar.gz -b8452a8a6a929d4938391d106e810fd517430bbc SOURCES/PK.auth -66895070de7ebfc2d49324ad24ee53debcc540db SOURCES/securebootca.cer -4c954f56aa4273f24bb45c6e8b0084a67999c251 SOURCES/KEK.auth -f4e556118ee4f4dec187db15dc8767b92e99461d SOURCES/mokutil-0.2.0.tar.bz2 -531f3d9eb430649609695efd3d97ff3f6b8b9326 SOURCES/0.3.tar.gz +cf9230e69000076727e5b784ec871d22716dc5da SOURCES/securebootca.cer +ef680b489eb689a390ed2e1470eaaf2682ad5072 SOURCES/mokutil-0.2.0.tar.gz diff --git a/SOURCES/0001-Actually-reflect-the-upstream-commit-this-patchset-g.patch b/SOURCES/0001-Actually-reflect-the-upstream-commit-this-patchset-g.patch new file mode 100644 index 0000000..807a104 --- /dev/null +++ b/SOURCES/0001-Actually-reflect-the-upstream-commit-this-patchset-g.patch @@ -0,0 +1,37 @@ +From af3293e11528d991090b34a564c4d2e5de416e79 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 18 Feb 2014 15:19:07 -0500 +Subject: [PATCH] Actually reflect the upstream commit this patchset gets us + to. + +Signed-off-by: Peter Jones +--- + Makefile | 2 +- + commit | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + create mode 100644 commit + +diff --git a/Makefile b/Makefile +index e65d28d..c3ce4be 100644 +--- a/Makefile ++++ b/Makefile +@@ -67,7 +67,7 @@ shim_cert.h: shim.cer + version.c : version.c.in + sed -e "s,@@VERSION@@,$(VERSION)," \ + -e "s,@@UNAME@@,$(shell uname -a)," \ +- -e "s,@@COMMIT@@,$(shell if [ -d .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo commit id not available; fi)," \ ++ -e "s,@@COMMIT@@,$(shell if [ -f commit ]; then cat commit ; else echo commit id not available; fi)," \ + < version.c.in > version.c + + certdb/secmod.db: shim.crt +diff --git a/commit b/commit +new file mode 100644 +index 0000000..c52fa12 +--- /dev/null ++++ b/commit +@@ -0,0 +1 @@ ++06495f692fa748a553ffbde8bfae2974d8c791c0 +\ No newline at end of file +-- +1.8.5.3 + diff --git a/SOURCES/0001-Add-a-preliminary-test-plan.patch b/SOURCES/0001-Add-a-preliminary-test-plan.patch new file mode 100644 index 0000000..89a7995 --- /dev/null +++ b/SOURCES/0001-Add-a-preliminary-test-plan.patch @@ -0,0 +1,104 @@ +From ac356a0e7723662d0a83ca3991088ce346495772 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 14 Feb 2014 14:06:45 -0500 +Subject: [PATCH 1/3] 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 +--- + testplan.txt | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) + create mode 100644 testplan.txt + +diff --git a/testplan.txt b/testplan.txt +new file mode 100644 +index 0000000..118dfcd +--- /dev/null ++++ b/testplan.txt +@@ -0,0 +1,80 @@ ++How to test a new shim build for RHEL/fedora: ++ ++1) build pesign-test-app, and sign it with the appropriate key ++2) build shim with the appropriate key built in ++3) install pesign-test-app and shim-unsigned on the test machine ++4) make a lockdown.efi for "Red Hat Test Certificate" and put it in \EFI\test ++ mkdir /boot/efi/EFI/test/ ++ wget http://pjones.fedorapeople.org/shim/LockDown-rhtest.efi ++ mv LockDown-rhtest.efi /boot/efi/EFI/test/lockdown.efi ++5) sign shim with RHTC and put it in \EFI\test: ++ pesign -i /usr/share/shim/shim.efi -o /boot/efi/EFI/test/shim.efi \ ++ -s -c "Red Hat Test Certificate" ++6) put pesign-test-app-signed.efi in \EFI\test as grubx64.efi ++ cp /usr/share/pesign-test-app-0.4/pesign-test-app-signed.efi \ ++ /boot/efi/EFI/test/test.efi ++7) sign a copy of grubx64.efi with RHTC and iput it in \EFI\test\: ++ pesign -i /boot/efi/EFI/redhat/grubx64.efi -o grubx64-unsigned.efi \ ++ -r -u 0 ++ pesign -i grubx64-unsigned.efi -o /boot/efi/EFI/test/grub.efi \ ++ -s -c "Red Hat Test Certificate" ++8) sign a copy of mokmanager with RHTC and put it in \EFI\test: ++ pesign -i /usr/share/shim/MokManager.efi \ ++ -o /boot/efi/EFI/test/MokManager.efi -s \ ++ -c "Red Hat Test Certificate" ++9) copy grub.cfg to our test directory: ++ cp /boot/efi/EFI/redhat/grub.cfg /boot/efi/EFI/test/grub.cfg ++10) *move* \EFI\redhat\BOOT.CSV to \EFI\test ++ mv /boot/efi/EFI/redhat/BOOT.CSV /boot/efi/EFI/test/BOOT.CSV ++11) sign a copy of fallback.efi and put it in \EFI\BOOT\fallback.efi ++ rm -rf /boot/efi/EFI/BOOT/ ++ mkdir /boot/efi/EFI/BOOT/ ++ pesign -i /usr/share/shim/fallback.efi \ ++ -o /boot/efi/EFI/BOOT/fallback.efi \ ++ -s -c "Red Hat Test Certificate" ++12) put shim.efi there as well ++ cp /boot/efi/EFI/test/shim.efi /boot/efi/EFI/BOOT/BOOTX64.EFI ++13) enroll the current kernel's certificate with mokutil: ++ mokutil --import ~/redhatsecurebootca2.cer ++14) put machine in setup mode ++15) boot to the UEFI shell ++16) run lockdown.efi from #4: ++ fs0:\EFI\test\lockdown.efi ++17) enable secure boot verification ++18) verify it can't run other binaries: ++ fs0:\EFI\redhat\grubx64.efi ++ result should be an error, probably similar to: ++ "fs0:\...\grubx64.efi is not recognized as an internal or external command" ++19) copy test.efi to grubx64.efi: ++ cp \EFI\test\test.efi \EFI\test\grubx64.efi ++20) in the EFI shell, run fs0:\EFI\test\shim.efi ++21) you should see MokManager. Enroll the certificate you added in #13, and ++ the system will reboot. ++22) reboot to the UEFI shell and run fs0:\EFI\test\shim.efi ++ result: "This is a test application that should be completely safe." ++ If you get the expected result, shim can run things signed by its internal ++ key ring. Check a box someplace that says it can do that. ++23) from the EFI shell, copy grub to grubx64.efi: ++ cp \EFI\test\grubx.efi \EFI\test\grubx64.efi ++24) in the EFI shell, run fs0:\EFI\test\shim.efi ++ result: this should start grub, which will let you boot a kernel ++ If grub starts, it means shim can run things signed by a key in the system's ++ db. Check a box someplace that says it can do that. ++ If the kernel boots, it means shim can run things from Mok. Check a box ++ someplace that says it can do that. ++25) remove all boot entries and the BootOrder variable: ++ [root@uefi ~]# cd /sys/firmware/efi/efivars/ ++ [root@uefi efivars]# rm -vf Boot[0123456789]* BootOrder-* ++ removed ‘Boot0000-8be4df61-93ca-11d2-aa0d-00e098032b8c’ ++ removed ‘Boot0001-8be4df61-93ca-11d2-aa0d-00e098032b8c’ ++ removed ‘Boot0002-8be4df61-93ca-11d2-aa0d-00e098032b8c’ ++ removed ‘Boot2001-8be4df61-93ca-11d2-aa0d-00e098032b8c’ ++ removed ‘BootOrder-8be4df61-93ca-11d2-aa0d-00e098032b8c’ ++ [root@uefi efivars]# ++27) reboot ++28) the system should run \EFI\BOOT\BOOTX64.EFI . If it doesn't, you may just ++ have an old machine. In that case, go to the EFI shell and run: ++ fs0:\EFI\BOOT\BOOTX64.EFI ++ If this works, you should see a bit of output very quickly and then the same ++ thing as #24. This means shim recognized it was in \EFI\BOOT and ran ++ fallback.efi, which worked. +-- +1.8.5.3 + diff --git a/SOURCES/0001-Fix-path-generation-for-Dhcpv4-bootloader.patch b/SOURCES/0001-Fix-path-generation-for-Dhcpv4-bootloader.patch deleted file mode 100644 index 5bbcb2d..0000000 --- a/SOURCES/0001-Fix-path-generation-for-Dhcpv4-bootloader.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0ca010d2f46a4bd49d79a529efb74680110012b5 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 20 Nov 2013 12:20:23 -0500 -Subject: [PATCH] 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 ---- - include/str.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ - netboot.c | 28 +++++++++++++++++++++------- - 2 files changed, 66 insertions(+), 7 deletions(-) - create mode 100644 include/str.h - -diff --git a/include/str.h b/include/str.h -new file mode 100644 -index 0000000..0f3e003 ---- /dev/null -+++ b/include/str.h -@@ -0,0 +1,45 @@ -+#ifndef SHIM_STR_H -+#define SHIM_STR_H -+ -+static inline -+__attribute__((unused)) -+unsigned long strnlena(const CHAR8 *s, unsigned long n) -+{ -+ unsigned long i; -+ for (i = 0; i <= n; i++) -+ if (s[i] == '\0') -+ break; -+ return i; -+} -+ -+static inline -+__attribute__((unused)) -+CHAR8 * -+strncpya(CHAR8 *dest, const CHAR8 *src, unsigned long n) -+{ -+ unsigned long i; -+ -+ for (i = 0; i < n && src[i] != '\0'; i++) -+ dest[i] = src[i]; -+ for (; i < n; i++) -+ dest[i] = '\0'; -+ -+ return dest; -+} -+ -+static inline -+__attribute__((unused)) -+CHAR8 * -+strcata(CHAR8 *dest, const CHAR8 *src) -+{ -+ unsigned long dest_len = strlena(dest); -+ unsigned long i; -+ -+ for (i = 0; src[i] != '\0'; i++) -+ dest[dest_len + i] = src[i]; -+ dest[dest_len + i] = '\0'; -+ -+ return dest; -+} -+ -+#endif /* SHIM_STR_H */ -diff --git a/netboot.c b/netboot.c -index a83c82a..1732dc7 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -38,6 +38,7 @@ - #include - #include "shim.h" - #include "netboot.h" -+#include "str.h" - - static inline unsigned short int __swap16(unsigned short int x) - { -@@ -305,19 +306,32 @@ static EFI_STATUS parseDhcp6() - - static EFI_STATUS parseDhcp4() - { -- CHAR8 *template = (CHAR8 *)DEFAULT_LOADER_CHAR; -- full_path = AllocateZeroPool(strlen(template)+1); -+ CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); -+ UINTN template_len = strlen(template) + 1; -+ -+ UINTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); -+ UINTN i; -+ UINT8 *dir = pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile; -+ -+ for (i = dir_len; i >= 0; i--) { -+ if (dir[i] == '/') -+ break; -+ } -+ dir_len = (i >= 0) ? i + 1 : 0; -+ -+ full_path = AllocateZeroPool(dir_len + template_len); - - if (!full_path) - return EFI_OUT_OF_RESOURCES; - -+ if (dir_len > 0) { -+ strncpya(full_path, dir, dir_len); -+ if (full_path[dir_len-1] == '/' && template[0] == '/') -+ full_path[dir_len-1] = '\0'; -+ } -+ strcata(full_path, template); - memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); - -- memcpy(full_path, template, strlen(template)); -- -- /* Note we don't capture the filename option here because we know its shim.efi -- * We instead assume the filename at the end of the path is going to be grubx64.efi -- */ - return EFI_SUCCESS; - } - --- -1.8.3.1 - diff --git a/SOURCES/0001-Lengths-that-might-be-1-can-t-be-unsigned-Peter.patch b/SOURCES/0001-Lengths-that-might-be-1-can-t-be-unsigned-Peter.patch deleted file mode 100644 index 62712c3..0000000 --- a/SOURCES/0001-Lengths-that-might-be-1-can-t-be-unsigned-Peter.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 36c3ce078d59abe148cd5045c0a8d9b9f7ffb88e Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 21 Nov 2013 11:26:08 -0500 -Subject: [PATCH] Lengths that might be -1 can't be unsigned, Peter. - -Signed-off-by: Peter Jones ---- - netboot.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/netboot.c b/netboot.c -index 1732dc7..07e2773 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -307,10 +307,10 @@ static EFI_STATUS parseDhcp6() - static EFI_STATUS parseDhcp4() - { - CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); -- UINTN template_len = strlen(template) + 1; -+ INTN template_len = strlen(template) + 1; - -- UINTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); -- UINTN i; -+ INTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); -+ INTN i; - UINT8 *dir = pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile; - - for (i = dir_len; i >= 0; i--) { -@@ -329,6 +329,8 @@ static EFI_STATUS parseDhcp4() - if (full_path[dir_len-1] == '/' && template[0] == '/') - full_path[dir_len-1] = '\0'; - } -+ if (dir_len == 0 && dir[0] != '/' && template[0] == '/') -+ template++; - strcata(full_path, template); - memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); - --- -1.8.3.1 - diff --git a/SOURCES/0001-fix-verify_mok.patch b/SOURCES/0001-fix-verify_mok.patch new file mode 100644 index 0000000..cd4e642 --- /dev/null +++ b/SOURCES/0001-fix-verify_mok.patch @@ -0,0 +1,54 @@ +From 11495d4019d44dce1487939f91f7d751ffbb9730 Mon Sep 17 00:00:00 2001 +From: Andrew Boie +Date: Mon, 15 Apr 2013 14:11:17 -0700 +Subject: [PATCH 01/19] fix verify_mok() + +() Fix the return value semantics. If the MokList doesn't +exist, we are OK. If the MokList was compromised but we +were able to erase it, that is OK too. Only if the list +can't be nuked do we return an error. + +() Fix use of potentially uninitialized attribute variable + +() Actually use the return value when called from verify_buffer. + +Change-Id: If16df21d79c52a1726928df96d133390cde4cb7e +Signed-off-by: Andrew Boie +--- + shim.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/shim.c b/shim.c +index 23dd0ee..dcb36d0 100644 +--- a/shim.c ++++ b/shim.c +@@ -670,13 +670,12 @@ static EFI_STATUS verify_mok (void) { + status = get_variable_attr(L"MokList", &MokListData, &MokListDataSize, + shim_lock_guid, &attributes); + +- if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { ++ if (!EFI_ERROR(status) && attributes & EFI_VARIABLE_RUNTIME_ACCESS) { + Print(L"MokList is compromised!\nErase all keys in MokList!\n"); + if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) { + Print(L"Failed to erase MokList\n"); ++ return EFI_ACCESS_DENIED; + } +- status = EFI_ACCESS_DENIED; +- return status; + } + + if (MokListData) +@@ -722,7 +721,9 @@ static EFI_STATUS verify_buffer (char *data, int datasize, + /* + * Check that the MOK database hasn't been modified + */ +- verify_mok(); ++ status = verify_mok(); ++ if (status != EFI_SUCCESS) ++ return status; + + /* + * Ensure that the binary isn't blacklisted +-- +1.8.5.3 + diff --git a/SOURCES/0002-Fix-a-part-of-the-test-plan-that-was-out-of-order.patch b/SOURCES/0002-Fix-a-part-of-the-test-plan-that-was-out-of-order.patch new file mode 100644 index 0000000..8213cb6 --- /dev/null +++ b/SOURCES/0002-Fix-a-part-of-the-test-plan-that-was-out-of-order.patch @@ -0,0 +1,39 @@ +From 9e8d5151979040c331f45b9d2cd443a59ca297e4 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 14 Feb 2014 14:44:31 -0500 +Subject: [PATCH 2/4] Fix a part of the test plan that was out of order. + +Signed-off-by: Peter Jones +--- + testplan.txt | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/testplan.txt b/testplan.txt +index 118dfcd..96aa364 100644 +--- a/testplan.txt ++++ b/testplan.txt +@@ -25,10 +25,10 @@ How to test a new shim build for RHEL/fedora: + 9) copy grub.cfg to our test directory: + cp /boot/efi/EFI/redhat/grub.cfg /boot/efi/EFI/test/grub.cfg + 10) *move* \EFI\redhat\BOOT.CSV to \EFI\test +- mv /boot/efi/EFI/redhat/BOOT.CSV /boot/efi/EFI/test/BOOT.CSV +-11) sign a copy of fallback.efi and put it in \EFI\BOOT\fallback.efi + rm -rf /boot/efi/EFI/BOOT/ + mkdir /boot/efi/EFI/BOOT/ ++ mv /boot/efi/EFI/redhat/BOOT.CSV /boot/efi/EFI/test/BOOT.CSV ++11) sign a copy of fallback.efi and put it in \EFI\BOOT\fallback.efi + pesign -i /usr/share/shim/fallback.efi \ + -o /boot/efi/EFI/BOOT/fallback.efi \ + -s -c "Red Hat Test Certificate" +@@ -55,7 +55,7 @@ How to test a new shim build for RHEL/fedora: + If you get the expected result, shim can run things signed by its internal + key ring. Check a box someplace that says it can do that. + 23) from the EFI shell, copy grub to grubx64.efi: +- cp \EFI\test\grubx.efi \EFI\test\grubx64.efi ++ cp \EFI\test\grub.efi \EFI\test\grubx64.efi + 24) in the EFI shell, run fs0:\EFI\test\shim.efi + result: this should start grub, which will let you boot a kernel + If grub starts, it means shim can run things signed by a key in the system's +-- +1.8.5.3 + diff --git a/SOURCES/0002-shim.c-Add-support-for-hashing-relocation-of-32-bit-.patch b/SOURCES/0002-shim.c-Add-support-for-hashing-relocation-of-32-bit-.patch new file mode 100644 index 0000000..8f6d38c --- /dev/null +++ b/SOURCES/0002-shim.c-Add-support-for-hashing-relocation-of-32-bit-.patch @@ -0,0 +1,175 @@ +From 8e9d3af7b108cc76ce18017b3f58ad4b2e60989f Mon Sep 17 00:00:00 2001 +From: Mohanraj S +Date: Tue, 27 Aug 2013 09:27:00 -0700 +Subject: [PATCH 02/19] shim.c: Add support for hashing/relocation of 32-bit + binaries + +Change-Id: Ib93305f7f1691d1b142567507df1058de62dde06 +Signed-off-by: Andrew Boie +--- + shim.c | 72 +++++++++++++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 49 insertions(+), 23 deletions(-) + +diff --git a/shim.c b/shim.c +index dcb36d0..a043779 100644 +--- a/shim.c ++++ b/shim.c +@@ -126,7 +126,11 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, + int size = context->ImageSize; + void *ImageEnd = (char *)data + size; + ++#if __LP64__ + context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)data; ++#else ++ context->PEHdr->Pe32.OptionalHeader.ImageBase = (UINT32)data; ++#endif + + if (context->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + Print(L"Image has no relocation entry\n"); +@@ -141,7 +145,7 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, + return EFI_UNSUPPORTED; + } + +- Adjust = (UINT64)data - context->ImageAddress; ++ Adjust = (UINTN)data - context->ImageAddress; + + if (Adjust == 0) + return EFI_SUCCESS; +@@ -549,9 +553,15 @@ static EFI_STATUS generate_hash (char *data, int datasize, + } + + /* Hash end of certificate table to end of image header */ ++#if __LP64__ + hashbase = (char *) &context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; + hashsize = context->PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders - + (int) ((char *) (&context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - data); ++#else ++ hashbase = (char *) &context->PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; ++ hashsize = context->PEHdr->Pe32.OptionalHeader.SizeOfHeaders - ++ (int) ((char *) (&context->PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - data); ++#endif + + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || + !(Sha1Update(sha1ctx, hashbase, hashsize))) { +@@ -561,7 +571,11 @@ static EFI_STATUS generate_hash (char *data, int datasize, + } + + /* Sort sections */ ++#if __LP64__ + SumOfBytesHashed = context->PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders; ++#else ++ SumOfBytesHashed = context->PEHdr->Pe32.OptionalHeader.SizeOfHeaders; ++#endif + + Section = (EFI_IMAGE_SECTION_HEADER *) ( + (char *)context->PEHdr + sizeof (UINT32) + +@@ -628,7 +642,11 @@ static EFI_STATUS generate_hash (char *data, int datasize, + hashbase = data + SumOfBytesHashed; + hashsize = (unsigned int)( + size - ++#if __LP64__ + context->PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - ++#else ++ context->PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - ++#endif + SumOfBytesHashed); + + if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || +@@ -781,7 +799,7 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, + { + EFI_IMAGE_DOS_HEADER *DosHdr = data; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data; +- unsigned long HeaderWithoutDataDir, SectionHeaderOffset; ++ unsigned long HeaderWithoutDataDir, SectionHeaderOffset, OptHeaderSize; + + if (datasize < sizeof(EFI_IMAGE_DOS_HEADER)) { + Print(L"Invalid image\n"); +@@ -790,18 +808,28 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, + + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) + PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew); ++#if __LP64__ ++ context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes; ++ context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders; ++ context->ImageSize = PEHdr->Pe32Plus.OptionalHeader.SizeOfImage; ++ OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64); ++#else ++ context->NumberOfRvaAndSizes = PEHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes; ++ context->SizeOfHeaders = PEHdr->Pe32.OptionalHeader.SizeOfHeaders; ++ context->ImageSize = (UINT64)PEHdr->Pe32.OptionalHeader.SizeOfImage; ++ OptHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32); ++#endif ++ context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections; + +- if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES +- < PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes) { ++ if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < context->NumberOfRvaAndSizes) { + Print(L"Image header too small\n"); + return EFI_UNSUPPORTED; + } + +- HeaderWithoutDataDir = sizeof (EFI_IMAGE_OPTIONAL_HEADER64) ++ HeaderWithoutDataDir = OptHeaderSize + - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; +- if (((UINT32)PEHdr->Pe32Plus.FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) != +- PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes +- * sizeof (EFI_IMAGE_DATA_DIRECTORY)) { ++ if (((UINT32)PEHdr->Pe32.FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) != ++ context->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) { + Print(L"Image header overflows data directory\n"); + return EFI_UNSUPPORTED; + } +@@ -809,15 +837,15 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, + SectionHeaderOffset = DosHdr->e_lfanew + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) +- + PEHdr->Pe32Plus.FileHeader.SizeOfOptionalHeader; +- if ((PEHdr->Pe32Plus.OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER +- <= PEHdr->Pe32Plus.FileHeader.NumberOfSections) { ++ + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader; ++ if (((UINT32)context->ImageSize - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER ++ <= context->NumberOfSections) { + Print(L"Image sections overflow image size\n"); + return EFI_UNSUPPORTED; + } + +- if ((PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER +- < (UINT32)PEHdr->Pe32Plus.FileHeader.NumberOfSections) { ++ if ((context->SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER ++ < (UINT32)context->NumberOfSections) { + Print(L"Image sections overflow section headers\n"); + return EFI_UNSUPPORTED; + } +@@ -837,21 +865,19 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, + return EFI_UNSUPPORTED; + } + +- if (PEHdr->Pe32.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { +- Print(L"Only 64-bit images supported\n"); +- return EFI_UNSUPPORTED; +- } +- + context->PEHdr = PEHdr; ++#if __LP64__ + context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase; +- context->ImageSize = (UINT64)PEHdr->Pe32Plus.OptionalHeader.SizeOfImage; +- context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders; + context->EntryPoint = PEHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint; + context->RelocDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; +- context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes; +- context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections; +- context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER)); + context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; ++#else ++ context->ImageAddress = PEHdr->Pe32.OptionalHeader.ImageBase; ++ context->EntryPoint = PEHdr->Pe32.OptionalHeader.AddressOfEntryPoint; ++ context->RelocDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; ++ context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; ++#endif ++ context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER)); + + if (context->ImageSize < context->SizeOfHeaders) { + Print(L"Invalid image\n"); +-- +1.8.5.3 + diff --git a/SOURCES/0003-Allow-fallback-to-use-the-system-s-LoadImage-StartIm.patch b/SOURCES/0003-Allow-fallback-to-use-the-system-s-LoadImage-StartIm.patch new file mode 100644 index 0000000..7ac76f0 --- /dev/null +++ b/SOURCES/0003-Allow-fallback-to-use-the-system-s-LoadImage-StartIm.patch @@ -0,0 +1,249 @@ +From 06495f692fa748a553ffbde8bfae2974d8c791c0 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 14 Feb 2014 15:38:25 -0500 +Subject: [PATCH 3/3] 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 +--- + replacements.c | 68 +++++++++++++++++++++++++++++++++++++++++++++- + replacements.h | 3 +++ + shim.c | 85 +++++++++++++++++++++++++++++++++++----------------------- + 3 files changed, 121 insertions(+), 35 deletions(-) + +diff --git a/replacements.c b/replacements.c +index 5ea5c32..48dc437 100644 +--- a/replacements.c ++++ b/replacements.c +@@ -60,26 +60,82 @@ + + static EFI_SYSTEM_TABLE *systab; + ++static typeof(systab->BootServices->LoadImage) system_load_image; + static typeof(systab->BootServices->StartImage) system_start_image; + static typeof(systab->BootServices->Exit) system_exit; + static typeof(systab->BootServices->ExitBootServices) system_exit_boot_services; + ++static EFI_HANDLE last_loaded_image; ++ + void + unhook_system_services(void) + { + systab->BootServices->Exit = system_exit; ++ systab->BootServices->LoadImage = system_load_image; + systab->BootServices->StartImage = system_start_image; + systab->BootServices->ExitBootServices = system_exit_boot_services; + } + + static EFI_STATUS EFIAPI ++load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle, ++ EFI_DEVICE_PATH *DevicePath, VOID *SourceBuffer, ++ UINTN SourceSize, EFI_HANDLE *ImageHandle) ++{ ++ EFI_STATUS status; ++ unhook_system_services(); ++ ++ status = systab->BootServices->LoadImage(BootPolicy, ++ ParentImageHandle, DevicePath, ++ SourceBuffer, SourceSize, ImageHandle); ++ hook_system_services(systab); ++ if (EFI_ERROR(status)) ++ last_loaded_image = NULL; ++ else ++ last_loaded_image = *ImageHandle; ++ return status; ++} ++ ++static EFI_STATUS EFIAPI + start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data) + { + EFI_STATUS status; + unhook_system_services(); ++ ++ /* We have to uninstall shim's protocol here, because if we're ++ * On the fallback.efi path, then our call pathway is: ++ * ++ * shim->fallback->shim->grub ++ * ^ ^ ^ ++ * | | \- gets protocol #0 ++ * | \- installs its protocol (#1) ++ * \- installs its protocol (#0) ++ * and if we haven't removed this, then grub will get the *first* ++ * shim's protocol, but it'll get the second shim's systab ++ * replacements. So even though it will participate and verify ++ * the kernel, the systab never finds out. ++ */ ++ if (image_handle == last_loaded_image) { ++ loader_is_participating = 1; ++ uninstall_shim_protocols(); ++ } + status = systab->BootServices->StartImage(image_handle, exit_data_size, exit_data); +- if (EFI_ERROR(status)) ++ if (EFI_ERROR(status)) { ++ if (image_handle == last_loaded_image) { ++ EFI_STATUS status2 = install_shim_protocols(); ++ ++ if (EFI_ERROR(status2)) { ++ Print(L"Something has gone seriously wrong: %d\n", ++ status2); ++ Print(L"shim cannot continue, sorry.\n"); ++ systab->BootServices->Stall(5000000); ++ systab->RuntimeServices->ResetSystem( ++ EfiResetShutdown, ++ EFI_SECURITY_VIOLATION, 0, NULL); ++ } ++ } + hook_system_services(systab); ++ loader_is_participating = 0; ++ } + return status; + } + +@@ -123,6 +179,16 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab) + + /* We need to hook various calls to make this work... */ + ++ /* We need LoadImage() hooked so that fallback.c can load shim ++ * without having to fake LoadImage as well. This allows it ++ * to call the system LoadImage(), and have us track the output ++ * and mark loader_is_participating in start_image. This means ++ * anything added by fallback has to be verified by the system db, ++ * which we want to preserve anyway, since that's all launching ++ * through BDS gives us. */ ++ system_load_image = systab->BootServices->LoadImage; ++ systab->BootServices->LoadImage = load_image; ++ + /* we need StartImage() so that we can allow chain booting to an + * image trusted by the firmware */ + system_start_image = systab->BootServices->StartImage; +diff --git a/replacements.h b/replacements.h +index 5b57bc2..bd09424 100644 +--- a/replacements.h ++++ b/replacements.h +@@ -41,4 +41,7 @@ extern int loader_is_participating; + extern void hook_system_services(EFI_SYSTEM_TABLE *local_systab); + extern void unhook_system_services(void); + ++extern EFI_STATUS install_shim_protocols(void); ++extern void uninstall_shim_protocols(void); ++ + #endif /* SHIM_REPLACEMENTS_H */ +diff --git a/shim.c b/shim.c +index cf93d65..0e18d38 100644 +--- a/shim.c ++++ b/shim.c +@@ -1707,11 +1707,56 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) + return EFI_SUCCESS; + } + +-EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) ++static SHIM_LOCK shim_lock_interface; ++static EFI_HANDLE shim_lock_handle; ++ ++EFI_STATUS ++install_shim_protocols(void) ++{ ++ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; ++ EFI_STATUS efi_status; ++ /* ++ * Install the protocol ++ */ ++ efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, ++ &shim_lock_handle, &shim_lock_guid, ++ EFI_NATIVE_INTERFACE, &shim_lock_interface); ++ if (EFI_ERROR(efi_status)) { ++ console_error(L"Could not install security protocol", ++ efi_status); ++ return efi_status; ++ } ++ ++#if defined(OVERRIDE_SECURITY_POLICY) ++ /* ++ * Install the security protocol hook ++ */ ++ security_policy_install(shim_verify); ++#endif ++ ++ return EFI_SUCCESS; ++} ++ ++void ++uninstall_shim_protocols(void) + { + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; +- static SHIM_LOCK shim_lock_interface; +- EFI_HANDLE handle = NULL; ++#if defined(OVERRIDE_SECURITY_POLICY) ++ /* ++ * Clean up the security protocol hook ++ */ ++ security_policy_uninstall(); ++#endif ++ ++ /* ++ * If we're back here then clean everything up before exiting ++ */ ++ uefi_call_wrapper(BS->UninstallProtocolInterface, 3, shim_lock_handle, ++ &shim_lock_guid, &shim_lock_interface); ++} ++ ++EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) ++{ + EFI_STATUS efi_status; + + verification_method = VERIFIED_BY_NOTHING; +@@ -1768,24 +1813,9 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) + } + } + +- /* +- * Install the protocol +- */ +- efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, +- &handle, &shim_lock_guid, EFI_NATIVE_INTERFACE, +- &shim_lock_interface); +- if (EFI_ERROR(efi_status)) { +- console_error(L"Could not install security protocol", +- efi_status); ++ efi_status = install_shim_protocols(); ++ if (EFI_ERROR(efi_status)) + return efi_status; +- } +- +-#if defined(OVERRIDE_SECURITY_POLICY) +- /* +- * Install the security protocol hook +- */ +- security_policy_install(shim_verify); +-#endif + + /* + * Enter MokManager if necessary +@@ -1810,20 +1840,7 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) + + efi_status = init_grub(image_handle); + +-#if defined(OVERRIDE_SECURITY_POLICY) +- /* +- * Clean up the security protocol hook +- */ +- security_policy_uninstall(); +-#endif +- +- /* +- * If we're back here then clean everything up before exiting +- */ +- uefi_call_wrapper(BS->UninstallProtocolInterface, 3, handle, +- &shim_lock_guid, &shim_lock_interface); +- +- ++ uninstall_shim_protocols(); + /* + * Remove our hooks from system services. + */ +-- +1.8.5.3 + diff --git a/SOURCES/0003-netboot.h-fix-build-error-on-32-bit-systems.patch b/SOURCES/0003-netboot.h-fix-build-error-on-32-bit-systems.patch new file mode 100644 index 0000000..abd8da7 --- /dev/null +++ b/SOURCES/0003-netboot.h-fix-build-error-on-32-bit-systems.patch @@ -0,0 +1,27 @@ +From 434e854202236ec5809dbb96589fc34313dbff9e Mon Sep 17 00:00:00 2001 +From: Andrew Boie +Date: Thu, 31 Oct 2013 13:56:56 -0700 +Subject: [PATCH 03/19] netboot.h: fix build error on 32-bit systems + +Function prototype/implementation mismatch. + +Change-Id: I89aaae1b49d0372d3aed76fc21c194e0ae55f72e +Signed-off-by: Andrew Boie +--- + netboot.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/netboot.h b/netboot.h +index 2cdb421..6417373 100644 +--- a/netboot.h ++++ b/netboot.h +@@ -5,5 +5,5 @@ extern BOOLEAN findNetboot(EFI_HANDLE image_handle); + + extern EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle); + +-extern EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINTN *bufsiz); ++extern EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *bufsiz); + #endif +-- +1.8.5.3 + diff --git a/SOURCES/0004-properly-compile-OpenSSL-in-32-bit-mode.patch b/SOURCES/0004-properly-compile-OpenSSL-in-32-bit-mode.patch new file mode 100644 index 0000000..d528ecb --- /dev/null +++ b/SOURCES/0004-properly-compile-OpenSSL-in-32-bit-mode.patch @@ -0,0 +1,34 @@ +From c5ed2dfa5d9c2d5de33db290ae8cc237342dbc4c Mon Sep 17 00:00:00 2001 +From: Andrey Petrov +Date: Mon, 11 Nov 2013 13:46:42 -0800 +Subject: [PATCH 04/19] properly compile OpenSSL in 32-bit mode + +Change-Id: Iff3ee5ae0f0b95b282b99a23e465723b4e9f6104 +Signed-off-by: Andrey Petrov +Signed-off-by: Andrew Boie +--- + Cryptlib/OpenSSL/Makefile | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile +index c93d5af..3d5a87c 100644 +--- a/Cryptlib/OpenSSL/Makefile ++++ b/Cryptlib/OpenSSL/Makefile +@@ -10,9 +10,12 @@ LIB_GCC = $(shell $(CC) -print-libgcc-file-name) + EFI_LIBS = -lefi -lgnuefi $(LIB_GCC) + + CFLAGS = -ggdb -O0 -I. -I.. -I../Include/ -Icrypto -fno-stack-protector -fno-strict-aliasing -fpic -fshort-wchar -nostdinc -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \ +- -Wall $(EFI_INCLUDES) -DOPENSSL_SYSNAME_UWIN -DOPENSSL_SYS_UEFI -DL_ENDIAN -DSIXTY_FOUR_BIT_LONG -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_SEED -DOPENSSL_NO_RC5 -DOPENSSL_NO_MDC2 -DOPENSSL_NO_SOCK -DOPENSSL_NO_CMS -DOPENSSL_NO_JPAKE -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_ERR -DOPENSSL_NO_KRB5 -DOPENSSL_NO_DYNAMIC_ENGINE -DGETPID_IS_MEANINGLESS -DOPENSSL_NO_STDIO -DOPENSSL_NO_FP_API -DOPENSSL_NO_DGRAM -DOPENSSL_NO_SHA0 -DOPENSSL_NO_LHASH -DOPENSSL_NO_HW -DOPENSSL_NO_OCSP -DOPENSSL_NO_LOCKING -DOPENSSL_NO_DEPRECATED -DOPENSSL_SMALL_FOOTPRINT -DPEDANTIC ++ -Wall $(EFI_INCLUDES) -DOPENSSL_SYSNAME_UWIN -DOPENSSL_SYS_UEFI -DL_ENDIAN -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_SEED -DOPENSSL_NO_RC5 -DOPENSSL_NO_MDC2 -DOPENSSL_NO_SOCK -DOPENSSL_NO_CMS -DOPENSSL_NO_JPAKE -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_ERR -DOPENSSL_NO_KRB5 -DOPENSSL_NO_DYNAMIC_ENGINE -DGETPID_IS_MEANINGLESS -DOPENSSL_NO_STDIO -DOPENSSL_NO_FP_API -DOPENSSL_NO_DGRAM -DOPENSSL_NO_SHA0 -DOPENSSL_NO_LHASH -DOPENSSL_NO_HW -DOPENSSL_NO_OCSP -DOPENSSL_NO_LOCKING -DOPENSSL_NO_DEPRECATED -DOPENSSL_SMALL_FOOTPRINT -DPEDANTIC + ifeq ($(ARCH),x86_64) +- CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI ++ CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI -DSIXTY_FOUR_BIT_LONG ++endif ++ifeq ($(ARCH),ia32) ++ CFLAGS += -DTHIRTY_TWO_BIT + endif + LDFLAGS = -nostdlib -znocombreloc + +-- +1.8.5.3 + diff --git a/SOURCES/0005-fallback.c-fix-32-bit-compilation.patch b/SOURCES/0005-fallback.c-fix-32-bit-compilation.patch new file mode 100644 index 0000000..1d89b3c --- /dev/null +++ b/SOURCES/0005-fallback.c-fix-32-bit-compilation.patch @@ -0,0 +1,38 @@ +From d74ab697f7f20418eeb09f0291cc480d43241dea Mon Sep 17 00:00:00 2001 +From: Andrew Boie +Date: Mon, 11 Nov 2013 16:12:23 -0800 +Subject: [PATCH 05/19] fallback.c: fix 32-bit compilation + +fh->Read expects pointer to 32-bit int, use UINTN + +Change-Id: If1a728efd51a9a24dfcd8123e84bf4c0713491fe +Signed-off-by: Andrew Boie +--- + fallback.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fallback.c b/fallback.c +index 82ddbf2..c875144 100644 +--- a/fallback.c ++++ b/fallback.c +@@ -15,7 +15,7 @@ + EFI_LOADED_IMAGE *this_image = NULL; + + static EFI_STATUS +-get_file_size(EFI_FILE_HANDLE fh, UINT64 *retsize) ++get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize) + { + EFI_STATUS rc; + void *buffer = NULL; +@@ -60,7 +60,7 @@ read_file(EFI_FILE_HANDLE fh, CHAR16 *fullpath, CHAR16 **buffer, UINT64 *bs) + return rc; + } + +- UINT64 len = 0; ++ UINTN len = 0; + CHAR16 *b = NULL; + rc = get_file_size(fh2, &len); + if (EFI_ERROR(rc)) { +-- +1.8.5.3 + diff --git a/SOURCES/0006-fix-fallback.so-build-dependency.patch b/SOURCES/0006-fix-fallback.so-build-dependency.patch new file mode 100644 index 0000000..883bc85 --- /dev/null +++ b/SOURCES/0006-fix-fallback.so-build-dependency.patch @@ -0,0 +1,29 @@ +From 06e15d762966d4224f7e54480b9213c4dcf1fe35 Mon Sep 17 00:00:00 2001 +From: Andrew Boie +Date: Mon, 11 Nov 2013 16:14:22 -0800 +Subject: [PATCH 06/19] fix fallback.so build dependency + +Exposed during parallel builds + +Change-Id: I9867858166dcafd69438f37ee5da14a267ace8f4 +Signed-off-by: Andrew Boie +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index a22c6b3..2eab862 100644 +--- a/Makefile ++++ b/Makefile +@@ -83,7 +83,7 @@ shim.so: $(OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a lib/lib.a + + fallback.o: $(FALLBACK_SRCS) + +-fallback.so: $(FALLBACK_OBJS) ++fallback.so: $(FALLBACK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a lib/lib.a + $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) + + MokManager.o: $(MOK_SOURCES) +-- +1.8.5.3 + diff --git a/SOURCES/0007-propagate-some-path-variables.patch b/SOURCES/0007-propagate-some-path-variables.patch new file mode 100644 index 0000000..83dcdb4 --- /dev/null +++ b/SOURCES/0007-propagate-some-path-variables.patch @@ -0,0 +1,38 @@ +From 476d376ed08e1431bf7e20bf47ea3fc6c36dd168 Mon Sep 17 00:00:00 2001 +From: Andrew Boie +Date: Mon, 11 Nov 2013 16:15:39 -0800 +Subject: [PATCH 07/19] propagate some path variables + +If these are overridden on the command line, pass them along to +the sub-makes. + +Change-Id: I531ccb5d2f5e4be8e99d4892cdcfffffc1ad9877 +Signed-off-by: Andrew Boie +--- + Makefile | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Makefile b/Makefile +index 2eab862..d619ff4 100644 +--- a/Makefile ++++ b/Makefile +@@ -92,13 +92,13 @@ MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a + $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) lib/lib.a + + Cryptlib/libcryptlib.a: +- $(MAKE) -C Cryptlib ++ $(MAKE) -C Cryptlib EFI_PATH=$(EFI_PATH) EFI_INCLUDE=$(EFI_INCLUDE) ARCH=$(ARCH) + + Cryptlib/OpenSSL/libopenssl.a: +- $(MAKE) -C Cryptlib/OpenSSL ++ $(MAKE) -C Cryptlib/OpenSSL EFI_PATH=$(EFI_PATH) EFI_INCLUDE=$(EFI_INCLUDE) ARCH=$(ARCH) + + lib/lib.a: +- $(MAKE) -C lib EFI_PATH=$(EFI_PATH) ++ $(MAKE) -C lib EFI_PATH=$(EFI_PATH) EFI_INCLUDE=$(EFI_INCLUDE) ARCH=$(ARCH) + + %.efi: %.so + objcopy -j .text -j .sdata -j .data \ +-- +1.8.5.3 + diff --git a/SOURCES/0008-allow-32-bit-compilation-with-64-bit-compiler.patch b/SOURCES/0008-allow-32-bit-compilation-with-64-bit-compiler.patch new file mode 100644 index 0000000..291c16b --- /dev/null +++ b/SOURCES/0008-allow-32-bit-compilation-with-64-bit-compiler.patch @@ -0,0 +1,90 @@ +From 9712a7e77dc12f7569858b81d620d85301f50ede Mon Sep 17 00:00:00 2001 +From: Andrew Boie +Date: Mon, 11 Nov 2013 16:17:20 -0800 +Subject: [PATCH 08/19] allow 32-bit compilation with 64-bit compiler + +Also removed unused LIB_PATH from some Makefiles. + +Change-Id: I7d28d18f7531b51b6121a2ffb88bcaedec57c467 +Signed-off-by: Andrew Boie +--- + Cryptlib/Makefile | 5 +++-- + Cryptlib/OpenSSL/Makefile | 4 +--- + Makefile | 3 +++ + lib/Makefile | 3 +++ + 4 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile +index a05a4db..d24e59e 100644 +--- a/Cryptlib/Makefile ++++ b/Cryptlib/Makefile +@@ -1,7 +1,5 @@ + ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) + +-LIB_PATH = /usr/lib64 +- + EFI_INCLUDE = /usr/include/efi + EFI_INCLUDES = -nostdinc -IInclude -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol + EFI_PATH = /usr/lib64/gnuefi +@@ -14,6 +12,9 @@ CFLAGS = -ggdb -O0 -I. -fno-stack-protector -fno-strict-aliasing -fpic -fshort- + ifeq ($(ARCH),x86_64) + CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI + endif ++ifeq ($(ARCH),ia32) ++ CFLAGS += -m32 ++endif + LDFLAGS = -nostdlib -znocombreloc + + TARGET = libcryptlib.a +diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile +index 3d5a87c..8e2f2a6 100644 +--- a/Cryptlib/OpenSSL/Makefile ++++ b/Cryptlib/OpenSSL/Makefile +@@ -1,7 +1,5 @@ + ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) + +-LIB_PATH = /usr/lib64 +- + EFI_INCLUDE = /usr/include/efi + EFI_INCLUDES = -I../Include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol + EFI_PATH = /usr/lib64/gnuefi +@@ -15,7 +13,7 @@ ifeq ($(ARCH),x86_64) + CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI -DSIXTY_FOUR_BIT_LONG + endif + ifeq ($(ARCH),ia32) +- CFLAGS += -DTHIRTY_TWO_BIT ++ CFLAGS += -m32 -DTHIRTY_TWO_BIT + endif + LDFLAGS = -nostdlib -znocombreloc + +diff --git a/Makefile b/Makefile +index d619ff4..e65d28d 100644 +--- a/Makefile ++++ b/Makefile +@@ -28,6 +28,9 @@ endif + ifeq ($(ARCH),x86_64) + CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI + endif ++ifeq ($(ARCH),ia32) ++ CFLAGS += -m32 ++endif + ifneq ($(origin VENDOR_CERT_FILE), undefined) + CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\" + endif +diff --git a/lib/Makefile b/lib/Makefile +index adb0347..a9c9cf6 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -17,6 +17,9 @@ CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ + ifeq ($(ARCH),x86_64) + CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI + endif ++ifeq ($(ARCH),ia32) ++ CFLAGS += -m32 ++endif + + lib.a: $(LIBFILES) + ar rcs lib.a $(LIBFILES) +-- +1.8.5.3 + diff --git a/SOURCES/0009-shim-improve-error-messages.patch b/SOURCES/0009-shim-improve-error-messages.patch new file mode 100644 index 0000000..81ab3fd --- /dev/null +++ b/SOURCES/0009-shim-improve-error-messages.patch @@ -0,0 +1,186 @@ +From 2f09d0ab290d9b0d8aa14c3243f1d85a20bc34e6 Mon Sep 17 00:00:00 2001 +From: Andrew Boie +Date: Mon, 11 Nov 2013 17:29:06 -0800 +Subject: [PATCH 09/19] shim: improve error messages + +%r when used in Print() will show a string representation of +an EFI_STATUS code. + +Change-Id: I6db47f5213454603bd66177aca378ad01e9f0bd4 +Signed-off-by: Andrew Boie +--- + shim.c | 38 +++++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +diff --git a/shim.c b/shim.c +index a043779..9ae1936 100644 +--- a/shim.c ++++ b/shim.c +@@ -914,7 +914,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, + */ + efi_status = read_header(data, datasize, &context); + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to read header\n"); ++ Print(L"Failed to read header: %r\n", efi_status); + return efi_status; + } + +@@ -981,7 +981,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, + efi_status = relocate_coff(&context, buffer); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Relocation failed\n"); ++ Print(L"Relocation failed: %r\n", efi_status); + FreePool(buffer); + return efi_status; + } +@@ -1022,7 +1022,7 @@ should_use_fallback(EFI_HANDLE image_handle) + rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, + &loaded_image_protocol, (void **)&li); + if (EFI_ERROR(rc)) { +- Print(L"Could not get image for bootx64.efi: %d\n", rc); ++ Print(L"Could not get image for bootx64.efi: %r\n", rc); + return 0; + } + +@@ -1044,13 +1044,13 @@ should_use_fallback(EFI_HANDLE image_handle) + rc = uefi_call_wrapper(BS->HandleProtocol, 3, li->DeviceHandle, + &FileSystemProtocol, (void **)&fio); + if (EFI_ERROR(rc)) { +- Print(L"Could not get fio for li->DeviceHandle: %d\n", rc); ++ Print(L"Could not get fio for li->DeviceHandle: %r\n", rc); + return 0; + } + + rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &vh); + if (EFI_ERROR(rc)) { +- Print(L"Could not open fio volume: %d\n", rc); ++ Print(L"Could not open fio volume: %r\n", rc); + return 0; + } + +@@ -1172,14 +1172,14 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + (void **)&drive); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to find fs\n"); ++ Print(L"Failed to find fs: %r\n", efi_status); + goto error; + } + + efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to open fs\n"); ++ Print(L"Failed to open fs: %r\n", efi_status); + goto error; + } + +@@ -1190,7 +1190,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + EFI_FILE_MODE_READ, 0); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to open %s - %lx\n", PathName, efi_status); ++ Print(L"Failed to open %s - %r\n", PathName, efi_status); + goto error; + } + +@@ -1223,7 +1223,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + } + + if (efi_status != EFI_SUCCESS) { +- Print(L"Unable to get file info\n"); ++ Print(L"Unable to get file info: %r\n", efi_status); + goto error; + } + +@@ -1251,7 +1251,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + } + + if (efi_status != EFI_SUCCESS) { +- Print(L"Unexpected return from initial read: %x, buffersize %x\n", efi_status, buffersize); ++ Print(L"Unexpected return from initial read: %r, buffersize %x\n", efi_status, buffersize); + goto error; + } + +@@ -1328,20 +1328,20 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + efi_status = generate_path(li, ImagePath, &path, &PathName); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Unable to generate path: %s\n", ImagePath); ++ Print(L"Unable to generate path %s: %r\n", ImagePath, efi_status); + goto done; + } + + if (findNetboot(image_handle)) { + efi_status = parseNetbootinfo(image_handle); + if (efi_status != EFI_SUCCESS) { +- Print(L"Netboot parsing failed: %d\n", efi_status); ++ Print(L"Netboot parsing failed: %r\n", efi_status); + return EFI_PROTOCOL_ERROR; + } + efi_status = FetchNetbootimage(image_handle, &sourcebuffer, + &sourcesize); + if (efi_status != EFI_SUCCESS) { +- Print(L"Unable to fetch TFTP image\n"); ++ Print(L"Unable to fetch TFTP image: %r\n", efi_status); + return efi_status; + } + data = sourcebuffer; +@@ -1353,7 +1353,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + efi_status = load_image(li, &data, &datasize, PathName); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to load image\n"); ++ Print(L"Failed to load image %s: %r\n", PathName, efi_status); + goto done; + } + } +@@ -1370,7 +1370,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + efi_status = handle_image(data, datasize, li); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to load image\n"); ++ Print(L"Failed to load image: %r\n", efi_status); + CopyMem(li, &li_bak, sizeof(li_bak)); + goto done; + } +@@ -1473,7 +1473,7 @@ EFI_STATUS mirror_mok_list() + | EFI_VARIABLE_RUNTIME_ACCESS, + FullDataSize, FullData); + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to set MokListRT %d\n", efi_status); ++ Print(L"Failed to set MokListRT: %r\n", efi_status); + } + + return efi_status; +@@ -1514,7 +1514,7 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle) + efi_status = start_image(image_handle, MOK_MANAGER); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to start MokManager\n"); ++ Print(L"Failed to start MokManager: %r\n", efi_status); + return efi_status; + } + } +@@ -1621,7 +1621,7 @@ static EFI_STATUS mok_ignore_db() + | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, (void *)&Data); + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to set MokIgnoreDB %d\n", efi_status); ++ Print(L"Failed to set MokIgnoreDB: %r\n", efi_status); + } + } + +@@ -1648,7 +1648,7 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) + status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, + &LoadedImageProtocol, (void **) &li); + if (status != EFI_SUCCESS) { +- Print (L"Failed to get load options\n"); ++ Print (L"Failed to get load options: %r\n", status); + return status; + } + +-- +1.8.5.3 + diff --git a/SOURCES/0010-Clarify-meaning-of-insecure_mode.patch b/SOURCES/0010-Clarify-meaning-of-insecure_mode.patch new file mode 100644 index 0000000..71146ef --- /dev/null +++ b/SOURCES/0010-Clarify-meaning-of-insecure_mode.patch @@ -0,0 +1,99 @@ +From d95b24bd02cf41cca9adebd95f10609d6424d2b3 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 19 Nov 2013 10:09:13 -0500 +Subject: [PATCH 10/19] Clarify meaning of insecure_mode + +insecure_mode was intended to indicate that the user had explicity disabled +checks with mokutil, which means it wasn't the opposite of secure_mode(). +Change the names to clarify this and don't show the insecure mode message +unless the user has explicitly enabled that mode. + +Signed-off-by: Matthew Garrett +--- + replacements.c | 6 ------ + shim.c | 12 ++++++------ + 2 files changed, 6 insertions(+), 12 deletions(-) + +diff --git a/replacements.c b/replacements.c +index bac5e5d..5ea5c32 100644 +--- a/replacements.c ++++ b/replacements.c +@@ -64,13 +64,9 @@ static typeof(systab->BootServices->StartImage) system_start_image; + static typeof(systab->BootServices->Exit) system_exit; + static typeof(systab->BootServices->ExitBootServices) system_exit_boot_services; + +-extern UINT8 insecure_mode; +- + void + unhook_system_services(void) + { +- if (insecure_mode) +- return; + systab->BootServices->Exit = system_exit; + systab->BootServices->StartImage = system_start_image; + systab->BootServices->ExitBootServices = system_exit_boot_services; +@@ -123,8 +119,6 @@ exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus, + void + hook_system_services(EFI_SYSTEM_TABLE *local_systab) + { +- if (insecure_mode) +- return; + systab = local_systab; + + /* We need to hook various calls to make this work... */ +diff --git a/shim.c b/shim.c +index 9ae1936..524f5fc 100644 +--- a/shim.c ++++ b/shim.c +@@ -85,7 +85,7 @@ int loader_is_participating; + + #define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }} + +-UINT8 insecure_mode; ++UINT8 user_insecure_mode; + UINT8 ignore_db; + + typedef enum { +@@ -456,7 +456,7 @@ static BOOLEAN secure_mode (void) + UINT8 *Data; + UINT8 sb, setupmode; + +- if (insecure_mode) ++ if (user_insecure_mode) + return FALSE; + + status = get_variable(L"SecureBoot", &Data, &len, global_var); +@@ -1534,7 +1534,7 @@ static EFI_STATUS check_mok_sb (void) + UINTN MokSBStateSize = 0; + UINT32 attributes; + +- insecure_mode = 0; ++ user_insecure_mode = 0; + ignore_db = 0; + + status = get_variable_attr(L"MokSBState", &MokSBState, &MokSBStateSize, +@@ -1555,7 +1555,7 @@ static EFI_STATUS check_mok_sb (void) + status = EFI_ACCESS_DENIED; + } else { + if (*(UINT8 *)MokSBState == 1) { +- insecure_mode = 1; ++ user_insecure_mode = 1; + } + } + +@@ -1753,10 +1753,10 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) + /* + * Tell the user that we're in insecure mode if necessary + */ +- if (!secure_mode()) { ++ if (user_insecure_mode) { + Print(L"Booting in insecure mode\n"); + uefi_call_wrapper(BS->Stall, 1, 2000000); +- } else { ++ } else if (secure_mode()) { + /* + * Install our hooks for ExitBootServices() and StartImage() + */ +-- +1.8.5.3 + diff --git a/SOURCES/0011-Don-t-hook-system-services-if-shim-has-no-built-in-k.patch b/SOURCES/0011-Don-t-hook-system-services-if-shim-has-no-built-in-k.patch new file mode 100644 index 0000000..c07d207 --- /dev/null +++ b/SOURCES/0011-Don-t-hook-system-services-if-shim-has-no-built-in-k.patch @@ -0,0 +1,42 @@ +From 8b48ec5c70cd97d37f48581a4eab8139c1a95a1f Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 19 Nov 2013 10:15:55 -0500 +Subject: [PATCH 11/19] 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 +--- + shim.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/shim.c b/shim.c +index 524f5fc..cf93d65 100644 +--- a/shim.c ++++ b/shim.c +@@ -1757,11 +1757,15 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) + Print(L"Booting in insecure mode\n"); + uefi_call_wrapper(BS->Stall, 1, 2000000); + } else if (secure_mode()) { +- /* +- * Install our hooks for ExitBootServices() and StartImage() +- */ +- hook_system_services(systab); +- loader_is_participating = 0; ++ if (vendor_cert_size || vendor_dbx_size) { ++ /* ++ * If shim includes its own certificates then ensure ++ * that anything it boots has performed some ++ * validation of the next image. ++ */ ++ hook_system_services(systab); ++ loader_is_participating = 0; ++ } + } + + /* +-- +1.8.5.3 + diff --git a/SOURCES/0012-Fix-path-generation-for-Dhcpv4-bootloader.patch b/SOURCES/0012-Fix-path-generation-for-Dhcpv4-bootloader.patch new file mode 100644 index 0000000..9591b28 --- /dev/null +++ b/SOURCES/0012-Fix-path-generation-for-Dhcpv4-bootloader.patch @@ -0,0 +1,124 @@ +From e62b69a5b0b87c6df7a4fc23906134945309e927 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 20 Nov 2013 12:20:23 -0500 +Subject: [PATCH 12/19] 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 +--- + include/str.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ + netboot.c | 28 +++++++++++++++++++++------- + 2 files changed, 66 insertions(+), 7 deletions(-) + create mode 100644 include/str.h + +diff --git a/include/str.h b/include/str.h +new file mode 100644 +index 0000000..0f3e003 +--- /dev/null ++++ b/include/str.h +@@ -0,0 +1,45 @@ ++#ifndef SHIM_STR_H ++#define SHIM_STR_H ++ ++static inline ++__attribute__((unused)) ++unsigned long strnlena(const CHAR8 *s, unsigned long n) ++{ ++ unsigned long i; ++ for (i = 0; i <= n; i++) ++ if (s[i] == '\0') ++ break; ++ return i; ++} ++ ++static inline ++__attribute__((unused)) ++CHAR8 * ++strncpya(CHAR8 *dest, const CHAR8 *src, unsigned long n) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < n && src[i] != '\0'; i++) ++ dest[i] = src[i]; ++ for (; i < n; i++) ++ dest[i] = '\0'; ++ ++ return dest; ++} ++ ++static inline ++__attribute__((unused)) ++CHAR8 * ++strcata(CHAR8 *dest, const CHAR8 *src) ++{ ++ unsigned long dest_len = strlena(dest); ++ unsigned long i; ++ ++ for (i = 0; src[i] != '\0'; i++) ++ dest[dest_len + i] = src[i]; ++ dest[dest_len + i] = '\0'; ++ ++ return dest; ++} ++ ++#endif /* SHIM_STR_H */ +diff --git a/netboot.c b/netboot.c +index a83c82a..1732dc7 100644 +--- a/netboot.c ++++ b/netboot.c +@@ -38,6 +38,7 @@ + #include + #include "shim.h" + #include "netboot.h" ++#include "str.h" + + static inline unsigned short int __swap16(unsigned short int x) + { +@@ -305,19 +306,32 @@ static EFI_STATUS parseDhcp6() + + static EFI_STATUS parseDhcp4() + { +- CHAR8 *template = (CHAR8 *)DEFAULT_LOADER_CHAR; +- full_path = AllocateZeroPool(strlen(template)+1); ++ CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); ++ UINTN template_len = strlen(template) + 1; ++ ++ UINTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); ++ UINTN i; ++ UINT8 *dir = pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile; ++ ++ for (i = dir_len; i >= 0; i--) { ++ if (dir[i] == '/') ++ break; ++ } ++ dir_len = (i >= 0) ? i + 1 : 0; ++ ++ full_path = AllocateZeroPool(dir_len + template_len); + + if (!full_path) + return EFI_OUT_OF_RESOURCES; + ++ if (dir_len > 0) { ++ strncpya(full_path, dir, dir_len); ++ if (full_path[dir_len-1] == '/' && template[0] == '/') ++ full_path[dir_len-1] = '\0'; ++ } ++ strcata(full_path, template); + memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); + +- memcpy(full_path, template, strlen(template)); +- +- /* Note we don't capture the filename option here because we know its shim.efi +- * We instead assume the filename at the end of the path is going to be grubx64.efi +- */ + return EFI_SUCCESS; + } + +-- +1.8.5.3 + diff --git a/SOURCES/0013-Lengths-that-might-be-1-can-t-be-unsigned-Peter.patch b/SOURCES/0013-Lengths-that-might-be-1-can-t-be-unsigned-Peter.patch new file mode 100644 index 0000000..c057508 --- /dev/null +++ b/SOURCES/0013-Lengths-that-might-be-1-can-t-be-unsigned-Peter.patch @@ -0,0 +1,40 @@ +From 27129a5a05d1947e6f7479766e8281d50d6031f6 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 Nov 2013 11:26:08 -0500 +Subject: [PATCH 13/19] Lengths that might be -1 can't be unsigned, Peter. + +Signed-off-by: Peter Jones +--- + netboot.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/netboot.c b/netboot.c +index 1732dc7..07e2773 100644 +--- a/netboot.c ++++ b/netboot.c +@@ -307,10 +307,10 @@ static EFI_STATUS parseDhcp6() + static EFI_STATUS parseDhcp4() + { + CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); +- UINTN template_len = strlen(template) + 1; ++ INTN template_len = strlen(template) + 1; + +- UINTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); +- UINTN i; ++ INTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); ++ INTN i; + UINT8 *dir = pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile; + + for (i = dir_len; i >= 0; i--) { +@@ -329,6 +329,8 @@ static EFI_STATUS parseDhcp4() + if (full_path[dir_len-1] == '/' && template[0] == '/') + full_path[dir_len-1] = '\0'; + } ++ if (dir_len == 0 && dir[0] != '/' && template[0] == '/') ++ template++; + strcata(full_path, template); + memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); + +-- +1.8.5.3 + diff --git a/SOURCES/0014-Fix-wrong-sizeof.patch b/SOURCES/0014-Fix-wrong-sizeof.patch new file mode 100644 index 0000000..e548615 --- /dev/null +++ b/SOURCES/0014-Fix-wrong-sizeof.patch @@ -0,0 +1,30 @@ +From af25679e166da9bd32a0ed7fbf67a408dda7f71a Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 09:21:53 -0500 +Subject: [PATCH 14/19] Fix wrong sizeof(). + +CHAR16* vs CHAR16**, so the result is the same on all platforms. + +Detected by coverity. + +Signed-off-by: Peter Jones +--- + lib/shell.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/shell.c b/lib/shell.c +index 51de4e0..7337834 100644 +--- a/lib/shell.c ++++ b/lib/shell.c +@@ -35,7 +35,7 @@ argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV) + + (*argc)++; /* we counted spaces, so add one for initial */ + +- *ARGV = AllocatePool(*argc * sizeof(*ARGV)); ++ *ARGV = AllocatePool(*argc * sizeof(**ARGV)); + if (!*ARGV) { + return EFI_OUT_OF_RESOURCES; + } +-- +1.8.5.3 + diff --git a/SOURCES/0015-Initialize-entries-before-we-pass-it-to-another-func.patch b/SOURCES/0015-Initialize-entries-before-we-pass-it-to-another-func.patch new file mode 100644 index 0000000..855c7a0 --- /dev/null +++ b/SOURCES/0015-Initialize-entries-before-we-pass-it-to-another-func.patch @@ -0,0 +1,30 @@ +From 4dbef508ab6359e8ca14df53b83f970bdeec17ba Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 09:24:01 -0500 +Subject: [PATCH 15/19] 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 +--- + lib/simple_file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/simple_file.c b/lib/simple_file.c +index 3af0ec8..d345d87 100644 +--- a/lib/simple_file.c ++++ b/lib/simple_file.c +@@ -415,7 +415,7 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, + CHAR16 *filter, CHAR16 **result) + { + EFI_STATUS status; +- CHAR16 **entries; ++ CHAR16 **entries = NULL; + EFI_FILE_INFO *dmp; + int count, select, len; + CHAR16 *newname, *selected; +-- +1.8.5.3 + diff --git a/SOURCES/0016-Rewrite-directory-traversal-allocation-path-so-cover.patch b/SOURCES/0016-Rewrite-directory-traversal-allocation-path-so-cover.patch new file mode 100644 index 0000000..bce4434 --- /dev/null +++ b/SOURCES/0016-Rewrite-directory-traversal-allocation-path-so-cover.patch @@ -0,0 +1,63 @@ +From 3a7feeff6cdb3b96a1ef2ccff8c150e2324d50a9 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 09:38:41 -0500 +Subject: [PATCH 16/19] 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 +--- + fallback.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/fallback.c b/fallback.c +index c875144..ba864ee 100644 +--- a/fallback.c ++++ b/fallback.c +@@ -445,25 +445,32 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname) + return EFI_SUCCESS; + } + FreePool(buffer); ++ buffer = NULL; + + bs = 0; + do { + bs = 0; + rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, NULL); +- if (rc == EFI_BUFFER_TOO_SMALL) { +- buffer = AllocateZeroPool(bs); +- if (!buffer) { +- Print(L"Could not allocate memory\n"); +- return EFI_OUT_OF_RESOURCES; +- } ++ if (EFI_ERROR(rc) && rc != EFI_BUFFER_TOO_SMALL) { ++ Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc); ++ if (buffer) ++ FreePool(buffer); ++ return rc; ++ } + +- rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, buffer); ++ buffer = AllocateZeroPool(bs); ++ if (!buffer) { ++ Print(L"Could not allocate memory\n"); ++ return EFI_OUT_OF_RESOURCES; + } ++ ++ rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, buffer); + if (EFI_ERROR(rc)) { + Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc); + FreePool(buffer); + return rc; + } ++ + if (bs == 0) + break; + +-- +1.8.5.3 + diff --git a/SOURCES/0017-Error-check-the-right-thing-in-get_variable_attr-whe.patch b/SOURCES/0017-Error-check-the-right-thing-in-get_variable_attr-whe.patch new file mode 100644 index 0000000..c76d442 --- /dev/null +++ b/SOURCES/0017-Error-check-the-right-thing-in-get_variable_attr-whe.patch @@ -0,0 +1,27 @@ +From 293f28d1fe3921c5348c60948b4dedcef5042d5b Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 10:55:37 -0500 +Subject: [PATCH 17/19] Error check the right thing in get_variable_attr() when + allocating. + +Signed-off-by: Peter Jones +--- + lib/variables.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/variables.c b/lib/variables.c +index 81bd34d..3a9735e 100644 +--- a/lib/variables.c ++++ b/lib/variables.c +@@ -224,7 +224,7 @@ get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, + return efi_status; + + *data = AllocateZeroPool(*len); +- if (!data) ++ if (!*data) + return EFI_OUT_OF_RESOURCES; + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, +-- +1.8.5.3 + diff --git a/SOURCES/0018-fallback-For-HD-device-paths-use-just-the-media-node.patch b/SOURCES/0018-fallback-For-HD-device-paths-use-just-the-media-node.patch new file mode 100644 index 0000000..2d3ba26 --- /dev/null +++ b/SOURCES/0018-fallback-For-HD-device-paths-use-just-the-media-node.patch @@ -0,0 +1,219 @@ +From dfd6c73a212f8cf6b32ce74807de9a08a87f0b79 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 31 Jan 2014 10:30:24 -0500 +Subject: [PATCH 18/19] [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. +--- + fallback.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 78 insertions(+), 25 deletions(-) + +diff --git a/fallback.c b/fallback.c +index ba864ee..a12bb74 100644 +--- a/fallback.c ++++ b/fallback.c +@@ -15,6 +15,27 @@ + EFI_LOADED_IMAGE *this_image = NULL; + + static EFI_STATUS ++FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType, ++ EFI_DEVICE_PATH **Out) ++{ ++ EFI_DEVICE_PATH *dp = In; ++ if (!In || !Out) ++ return EFI_INVALID_PARAMETER; ++ ++ for (dp = In; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { ++ if (DevicePathType(dp) == Type && ++ DevicePathSubType(dp) == SubType) { ++ *Out = DuplicateDevicePath(dp); ++ if (!*Out) ++ return EFI_OUT_OF_RESOURCES; ++ return EFI_SUCCESS; ++ } ++ } ++ *Out = NULL; ++ return EFI_NOT_FOUND; ++} ++ ++static EFI_STATUS + get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize) + { + EFI_STATUS rc; +@@ -93,7 +114,9 @@ make_full_path(CHAR16 *dirname, CHAR16 *filename, CHAR16 **out, UINT64 *outlen) + { + UINT64 len; + +- len = StrLen(dirname) + StrLen(filename) + StrLen(L"\\EFI\\\\") + 2; ++ len = StrLen(L"\\EFI\\") + StrLen(dirname) ++ + StrLen(L"\\") + StrLen(filename) ++ + 2; + + CHAR16 *fullpath = AllocateZeroPool(len*sizeof(CHAR16)); + if (!fullpath) { +@@ -119,7 +142,8 @@ VOID *first_new_option_args = NULL; + UINTN first_new_option_size = 0; + + EFI_STATUS +-add_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) ++add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, ++ CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) + { + static int i = 0; + CHAR16 varname[] = L"Boot0000"; +@@ -136,24 +160,31 @@ add_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label, CHAR16 *ar + void *var = LibGetVariable(varname, &global); + if (!var) { + int size = sizeof(UINT32) + sizeof (UINT16) + +- StrLen(label)*2 + 2 + DevicePathSize(dp) + +- StrLen(arguments) * 2 + 2; ++ StrLen(label)*2 + 2 + DevicePathSize(hddp) + ++ StrLen(arguments) * 2; + + CHAR8 *data = AllocateZeroPool(size); + CHAR8 *cursor = data; + *(UINT32 *)cursor = LOAD_OPTION_ACTIVE; + cursor += sizeof (UINT32); +- *(UINT16 *)cursor = DevicePathSize(dp); ++ *(UINT16 *)cursor = DevicePathSize(hddp); + cursor += sizeof (UINT16); + StrCpy((CHAR16 *)cursor, label); + cursor += StrLen(label)*2 + 2; +- CopyMem(cursor, dp, DevicePathSize(dp)); +- cursor += DevicePathSize(dp); ++ CopyMem(cursor, hddp, DevicePathSize(hddp)); ++ cursor += DevicePathSize(hddp); + StrCpy((CHAR16 *)cursor, arguments); + + Print(L"Creating boot entry \"%s\" with label \"%s\" " + L"for file \"%s\"\n", + varname, label, filename); ++ ++ if (!first_new_option) { ++ first_new_option = DuplicateDevicePath(fulldp); ++ first_new_option_args = arguments; ++ first_new_option_size = StrLen(arguments) * sizeof (CHAR16); ++ } ++ + rc = uefi_call_wrapper(RT->SetVariable, 5, varname, + &global, EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | +@@ -254,7 +285,10 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 * + if (EFI_ERROR(rc)) + return rc; + +- EFI_DEVICE_PATH *dph = NULL, *dpf = NULL, *dp = NULL; ++ EFI_DEVICE_PATH *dph = NULL; ++ EFI_DEVICE_PATH *file = NULL; ++ EFI_DEVICE_PATH *full_device_path = NULL; ++ EFI_DEVICE_PATH *dp = NULL; + + dph = DevicePathFromHandle(this_image->DeviceHandle); + if (!dph) { +@@ -262,19 +296,31 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 * + goto err; + } + +- dpf = FileDevicePath(fh, fullpath); +- if (!dpf) { ++ file = FileDevicePath(fh, fullpath); ++ if (!file) { + rc = EFI_OUT_OF_RESOURCES; + goto err; + } + +- dp = AppendDevicePath(dph, dpf); +- if (!dp) { ++ full_device_path = AppendDevicePath(dph, file); ++ if (!full_device_path) { + rc = EFI_OUT_OF_RESOURCES; + goto err; + } + ++ rc = FindSubDevicePath(full_device_path, ++ MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, &dp); ++ if (EFI_ERROR(rc)) { ++ if (rc == EFI_NOT_FOUND) { ++ dp = full_device_path; ++ } else { ++ rc = EFI_OUT_OF_RESOURCES; ++ goto err; ++ } ++ } ++ + #ifdef DEBUG_FALLBACK ++ { + UINTN s = DevicePathSize(dp); + int i; + UINT8 *dpv = (void *)dp; +@@ -287,20 +333,16 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 * + + CHAR16 *dps = DevicePathToStr(dp); + Print(L"device path: \"%s\"\n", dps); +-#endif +- if (!first_new_option) { +- CHAR16 *dps = DevicePathToStr(dp); +- Print(L"device path: \"%s\"\n", dps); +- first_new_option = DuplicateDevicePath(dp); +- first_new_option_args = arguments; +- first_new_option_size = StrLen(arguments) * sizeof (CHAR16); + } ++#endif + +- add_boot_option(dp, fullpath, label, arguments); ++ add_boot_option(dp, full_device_path, fullpath, label, arguments); + + err: +- if (dpf) +- FreePool(dpf); ++ if (file) ++ FreePool(file); ++ if (full_device_path) ++ FreePool(full_device_path); + if (dp) + FreePool(dp); + if (fullpath) +@@ -629,8 +671,19 @@ try_start_first_option(EFI_HANDLE parent_image_handle) + first_new_option, NULL, 0, + &image_handle); + if (EFI_ERROR(rc)) { +- Print(L"LoadImage failed: %d\n", rc); +- uefi_call_wrapper(BS->Stall, 1, 2000000); ++ CHAR16 *dps = DevicePathToStr(first_new_option); ++ UINTN s = DevicePathSize(first_new_option); ++ int i; ++ UINT8 *dpv = (void *)first_new_option; ++ Print(L"LoadImage failed: %d\nDevice path: \"%s\"\n", rc, dps); ++ for (i = 0; i < s; i++) { ++ if (i > 0 && i % 16 == 0) ++ Print(L"\n"); ++ Print(L"%02x ", dpv[i]); ++ } ++ Print(L"\n"); ++ ++ uefi_call_wrapper(BS->Stall, 1, 500000000); + return rc; + } + +@@ -644,7 +697,7 @@ try_start_first_option(EFI_HANDLE parent_image_handle) + rc = uefi_call_wrapper(BS->StartImage, 3, image_handle, NULL, NULL); + if (EFI_ERROR(rc)) { + Print(L"StartImage failed: %d\n", rc); +- uefi_call_wrapper(BS->Stall, 1, 2000000); ++ uefi_call_wrapper(BS->Stall, 1, 500000000); + } + return rc; + } +-- +1.8.5.3 + diff --git a/SOURCES/0019-fallback-Attempt-to-re-use-existing-entries-when-pos.patch b/SOURCES/0019-fallback-Attempt-to-re-use-existing-entries-when-pos.patch new file mode 100644 index 0000000..86ab395 --- /dev/null +++ b/SOURCES/0019-fallback-Attempt-to-re-use-existing-entries-when-pos.patch @@ -0,0 +1,147 @@ +From 894a2738d6c843a7b51245fb92bb2f835901e613 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 31 Jan 2014 10:31:10 -0500 +Subject: [PATCH 19/19] [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 +--- + fallback.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 98 insertions(+), 1 deletion(-) + +diff --git a/fallback.c b/fallback.c +index a12bb74..44638ec 100644 +--- a/fallback.c ++++ b/fallback.c +@@ -226,6 +226,85 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, + } + + EFI_STATUS ++find_boot_option(EFI_DEVICE_PATH *dp, CHAR16 *filename, CHAR16 *label, ++ CHAR16 *arguments, UINT16 *optnum) ++{ ++ int size = sizeof(UINT32) + sizeof (UINT16) + ++ StrLen(label)*2 + 2 + DevicePathSize(dp) + ++ StrLen(arguments) * 2 + 2; ++ ++ CHAR8 *data = AllocateZeroPool(size); ++ if (!data) ++ return EFI_OUT_OF_RESOURCES; ++ CHAR8 *cursor = data; ++ *(UINT32 *)cursor = LOAD_OPTION_ACTIVE; ++ cursor += sizeof (UINT32); ++ *(UINT16 *)cursor = DevicePathSize(dp); ++ cursor += sizeof (UINT16); ++ StrCpy((CHAR16 *)cursor, label); ++ cursor += StrLen(label)*2 + 2; ++ CopyMem(cursor, dp, DevicePathSize(dp)); ++ cursor += DevicePathSize(dp); ++ StrCpy((CHAR16 *)cursor, arguments); ++ ++ int i = 0; ++ CHAR16 varname[] = L"Boot0000"; ++ CHAR16 hexmap[] = L"0123456789ABCDEF"; ++ EFI_GUID global = EFI_GLOBAL_VARIABLE; ++ EFI_STATUS rc; ++ ++ CHAR8 *candidate = AllocateZeroPool(size); ++ if (!candidate) { ++ FreePool(data); ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ for(i = 0; i < nbootorder && i < 0x10000; i++) { ++ varname[4] = hexmap[(bootorder[i] & 0xf000) >> 12]; ++ varname[5] = hexmap[(bootorder[i] & 0x0f00) >> 8]; ++ varname[6] = hexmap[(bootorder[i] & 0x00f0) >> 4]; ++ varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0]; ++ ++ UINTN candidate_size = size; ++ rc = uefi_call_wrapper(RT->GetVariable, 5, varname, &global, ++ NULL, &candidate_size, candidate); ++ if (EFI_ERROR(rc)) ++ continue; ++ ++ if (candidate_size != size) ++ continue; ++ ++ if (CompareMem(candidate, data, size)) ++ continue; ++ ++ /* at this point, we have duplicate data. */ ++ *optnum = i; ++ FreePool(candidate); ++ FreePool(data); ++ return EFI_SUCCESS; ++ } ++ FreePool(candidate); ++ FreePool(data); ++ return EFI_NOT_FOUND; ++} ++ ++EFI_STATUS ++set_boot_order(void) ++{ ++ CHAR16 *oldbootorder; ++ UINTN size; ++ EFI_GUID global = EFI_GLOBAL_VARIABLE; ++ ++ oldbootorder = LibGetVariableAndSize(L"BootOrder", &global, &size); ++ if (oldbootorder) { ++ nbootorder = size / sizeof (CHAR16); ++ bootorder = oldbootorder; ++ } ++ return EFI_SUCCESS; ++ ++} ++ ++EFI_STATUS + update_boot_order(void) + { + CHAR16 *oldbootorder; +@@ -336,7 +415,23 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 * + } + #endif + +- add_boot_option(dp, full_device_path, fullpath, label, arguments); ++ UINT16 option; ++ rc = find_boot_option(dp, fullpath, label, arguments, &option); ++ if (EFI_ERROR(rc)) { ++ add_boot_option(dp, full_device_path, fullpath, label, arguments); ++ } else if (option != 0) { ++ CHAR16 *newbootorder; ++ newbootorder = AllocateZeroPool(sizeof (CHAR16) * nbootorder); ++ if (!newbootorder) ++ return EFI_OUT_OF_RESOURCES; ++ ++ newbootorder[0] = bootorder[option]; ++ CopyMem(newbootorder + 1, bootorder, sizeof (CHAR16) * option); ++ CopyMem(newbootorder + option + 1, bootorder + option + 1, ++ sizeof (CHAR16) * (nbootorder - option - 1)); ++ FreePool(bootorder); ++ bootorder = newbootorder; ++ } + + err: + if (file) +@@ -717,6 +812,8 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) + + Print(L"System BootOrder not found. Initializing defaults.\n"); + ++ set_boot_order(); ++ + rc = find_boot_options(this_image->DeviceHandle); + if (EFI_ERROR(rc)) { + Print(L"Error: could not find boot options: %d\n", rc); +-- +1.8.5.3 + diff --git a/SPECS/shim.spec b/SPECS/shim.spec index 1867183..4ba9aa6 100644 --- a/SPECS/shim.spec +++ b/SPECS/shim.spec @@ -1,6 +1,6 @@ Name: shim Version: 0.7 -Release: 4%{?dist} +Release: 5%{?dist} Summary: First-stage UEFI bootloader License: BSD @@ -10,18 +10,34 @@ Source1: securebootca.cer # incorporate mokutil for packaging simplicity %global mokutilver 0.2.0 -Source2: https://github.com/lcp/mokutil/archive/mokutil-%{mokutilver}.tar.bz2 +Source2: https://github.com/lcp/mokutil/archive/mokutil-%{mokutilver}.tar.gz # currently here's what's in our dbx: # nothing. #Source3: dbx.esl -%global lockdownver 0.3 -Source4: https://github.com/vathpela/lockdown/archive/%{lockdownver}.tar.gz -Source5: DB.auth -Source6: KEK.auth -Source7: PK.auth -Patch0000: 0001-Fix-path-generation-for-Dhcpv4-bootloader.patch -Patch0002: 0001-Lengths-that-might-be-1-can-t-be-unsigned-Peter.patch +Patch0001: 0001-fix-verify_mok.patch +Patch0002: 0002-shim.c-Add-support-for-hashing-relocation-of-32-bit-.patch +Patch0003: 0003-netboot.h-fix-build-error-on-32-bit-systems.patch +Patch0004: 0004-properly-compile-OpenSSL-in-32-bit-mode.patch +Patch0005: 0005-fallback.c-fix-32-bit-compilation.patch +Patch0006: 0006-fix-fallback.so-build-dependency.patch +Patch0007: 0007-propagate-some-path-variables.patch +Patch0008: 0008-allow-32-bit-compilation-with-64-bit-compiler.patch +Patch0009: 0009-shim-improve-error-messages.patch +Patch0010: 0010-Clarify-meaning-of-insecure_mode.patch +Patch0011: 0011-Don-t-hook-system-services-if-shim-has-no-built-in-k.patch +Patch0012: 0012-Fix-path-generation-for-Dhcpv4-bootloader.patch +Patch0013: 0013-Lengths-that-might-be-1-can-t-be-unsigned-Peter.patch +Patch0014: 0014-Fix-wrong-sizeof.patch +Patch0015: 0015-Initialize-entries-before-we-pass-it-to-another-func.patch +Patch0016: 0016-Rewrite-directory-traversal-allocation-path-so-cover.patch +Patch0017: 0017-Error-check-the-right-thing-in-get_variable_attr-whe.patch +Patch0018: 0018-fallback-For-HD-device-paths-use-just-the-media-node.patch +Patch0019: 0019-fallback-Attempt-to-re-use-existing-entries-when-pos.patch +Patch0020: 0001-Add-a-preliminary-test-plan.patch +Patch0021: 0002-Fix-a-part-of-the-test-plan-that-was-out-of-order.patch +Patch0022: 0003-Allow-fallback-to-use-the-system-s-LoadImage-StartIm.patch +Patch0023: 0001-Actually-reflect-the-upstream-commit-this-patchset-g.patch BuildRequires: git openssl-devel openssl BuildRequires: pesign >= 0.106-1 @@ -30,6 +46,9 @@ BuildRequires: gnu-efi = 3.0u, gnu-efi-devel = 3.0u # for xxd BuildRequires: vim-common +# for mokutil's configure +BuildRequires: autoconf automake + # Shim uses OpenSSL, but cannot use the system copy as the UEFI ABI is not # compatible with SysV (there's no red zone under UEFI) and there isn't a # POSIX-style C library. @@ -69,7 +88,6 @@ Utilities for managing the "Machine's Own Keys" list. %prep %setup -q %setup -q -a 2 -D -T -%setup -q -a 4 -D -T git init git config user.email "shim-owner@fedoraproject.org" @@ -86,14 +104,9 @@ fi # MAKEFLAGS="$MAKEFLAGS VENDOR_DBX_FILE=%{SOURCE3}" make 'DEFAULT_LOADER=\\\\grubx64.efi' ${MAKEFLAGS} shim.efi MokManager.efi fallback.efi cd mokutil-%{mokutilver} +./autogen.sh %configure make %{?_smp_mflags} -cd ../lockdown-%{lockdownver}/ -cp %{SOURCE5} %{SOURCE6} %{SOURCE7} ./ -xxd -i DB.auth > DB.h -xxd -i KEK.auth > KEK.h -xxd -i PK.auth > PK.h -make DB_FILE=%{SOURCE5} KEK_FILE=%{SOURCE6} PK_FILE=%{SOURCE7} lockdown.efi %install rm -rf $RPM_BUILD_ROOT @@ -105,8 +118,6 @@ install -m 0644 fallback.efi $RPM_BUILD_ROOT%{_datadir}/shim/fallback.efi install -m 0644 MokManager.efi $RPM_BUILD_ROOT%{_datadir}/shim/MokManager.efi cd mokutil-%{mokutilver} make PREFIX=%{_prefix} LIBDIR=%{_libdir} DESTDIR=%{buildroot} install -cd ../lockdown-%{lockdownver} -install -m 0644 lockdown.efi $RPM_BUILD_ROOT%{_datadir}/shim/lockdown.efi %files -n shim-unsigned %doc @@ -118,6 +129,11 @@ install -m 0644 lockdown.efi $RPM_BUILD_ROOT%{_datadir}/shim/lockdown.efi /usr/share/man/man1/mokutil.1.gz %changelog +* Tue Feb 18 2014 Peter Jones - 0.7-5 +- Update for production signing + Resolves: rhbz#1064424 + Related: rhbz#1064449 + * Thu Nov 21 2013 Peter Jones - 0.7-4 - Make dhcpv4 paths work better when netbooting. Resolves: rhbz#1032583