summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2018-03-12shim: generate_hash(): make clang-analyzer not get confused.Peter Jones
clang-analyzer thinks that because we're not checking for NULL from ImageAddress() it can be NULL, but doesn't realize we've already checked that value once before. Check it again, it can't hurt. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12shim: Mitigate a minor clang-analyzer complaint.Peter Jones
Clang believes "SumOfBytesHashed" is never used, because the thing that uses that computed value is #if 0'd currently. Just swizzle the #if's so that line is also not compiled. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12shim: tpm.c: Make sure old_caps is initialized in tpm2 code.Peter Jones
clang-analyzer caught this. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Don't use uefi_call_wrapper(), ever.Peter Jones
I'm pretty done with typing uefi_call_wrapper() and counting arguments every time. Instead, just make the compiler error if we don't have ms_abi. Also, make it so nothing can use uefi_call_wrapper() directly. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12shim: Use EFI_ERROR() instead of comparing to EFI_SUCCESS everywhere.Peter Jones
Also consistently name our status variable "efi_status" unless there's a good reason not to, such as already having another one of those. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12shim: relocate_coff(): get rid of "FixupData" stuffPeter Jones
"FixupData" in the edk2 tree is a log of the relocations that happened, which is allocated by the "client" calling relocate, and written into while it does relocations. Since we never allocate that log anywhere, FixupData is always NULL, and so covscan says: 318 case EFI_IMAGE_REL_BASED_HIGH: 319 Fixup16 = (UINT16 *) Fixup; 320 *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16))); null: At condition FixupData != NULL, the value of FixupData must be NULL. dead_error_condition: The condition FixupData != NULL cannot be true. 321 if (FixupData != NULL) { CID 182859 (#1 of 4): Logically dead code (DEADCODE)dead_error_begin: Execution cannot reach this statement: *((UINT16 *)FixupData) = *F.... 322 *(UINT16 *) FixupData = *Fixup16; 323 FixupData = FixupData + sizeof (UINT16); 324 } 325 break; And it's right; all four occurrances are deadcode that never do anything but confuse the reader. Kill it with fire. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12shim: check_db_cert_in_ram(): clear openssl errors /before/ returning.Peter Jones
Covscan says: 455 if (IsFound) { 456 tpm_measure_variable(dbname, guid, CertSize, Cert->SignatureData); 457 return DATA_FOUND; CID 182850 (#1 of 1): Structurally dead code (UNREACHABLE)unreachable: This code cannot be reached: drain_openssl_errors();. 458 drain_openssl_errors(); 459 } else { 460 LogError(L"AuthenticodeVerify(): %d\n", IsFound); 461 } And, well... woops. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12shim: ensure generate_hash() never operates on a negative (signed) number.Peter Jones
Covscan noticed: 746static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, 747 PE_COFF_LOADER_IMAGE_CONTEXT *context, 748 UINT8 *sha256hash, UINT8 *sha1hash) 749 750{ ... 764 CID 182849 (#1 of 1): Unsigned compared against 0 (NO_EFFECT)unsigned_compare: This less-than-zero comparison of an unsigned value is never true. datasize_in < 0U. 765 if (datasize_in < 0) { 766 perror(L"Invalid data size\n"); 767 return EFI_INVALID_PARAMETER; 768 } And I guess that's a fair point, but some of the callers take the size as a signed integer. So we should be handling that on all the input cases instead of getting that far. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12fallback: find_boot_options(): don't leak a file handle.Peter Jones
If we open it, we have to close it. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12fallback: Use EFI_ERROR() instead of comparing to EFI_SUCCESS everywhere.Peter Jones
Also consistently name our status variable "efi_status" unless there's a good reason not to, such as already having another one of those. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12fallback: find_boot_options(): make the allocation path prettier.Peter Jones
Covscan believes all this stuff: 852 bs = 0; 853 rc = uefi_call_wrapper(fh2->Read, 3, fh2, &bs, NULL); 7. Condition rc == (9223372036854775813UL /* 0x8000000000000000UL | 5 */), taking false branch. 8. Condition rc == 0, taking false branch. 15. Condition rc == (9223372036854775813UL /* 0x8000000000000000UL | 5 */), taking false branch. 16. Condition rc == 0, taking true branch. 17. Condition bs != 0, taking true branch. 30. Condition rc == (9223372036854775813UL /* 0x8000000000000000UL | 5 */), taking false branch. 31. Condition rc == 0, taking false branch. 854 if (rc == EFI_BUFFER_TOO_SMALL || 855 (rc == EFI_SUCCESS && bs != 0)) { 856 buffer = AllocateZeroPool(bs); 18. Condition !buffer, taking false branch. 857 if (!buffer) { 858 Print(L"Could not allocate memory\n"); 859 /* sure, this might work, why not? */ 860 uefi_call_wrapper(fh2->Close, 1, fh2); 861 uefi_call_wrapper(fh->Close, 1, fh); 862 return EFI_OUT_OF_RESOURCES; 863 } 864 865 rc = uefi_call_wrapper(fh2->Read, 3, fh2, &bs, buffer); 866 } 9. Condition bs == 0, taking false branch. 19. Condition bs == 0, taking false branch. 32. Condition bs == 0, taking false branch. 867 if (bs == 0) 868 break; 869 10. Condition (INTN)rc < 0, taking false branch. 20. Condition (INTN)rc < 0, taking false branch. 33. Condition (INTN)rc < 0, taking false branch. 870 if (EFI_ERROR(rc)) { 871 Print(L"Could not read \\EFI\\: %d\n", rc); 872 if (buffer) { 873 FreePool(buffer); 874 buffer = NULL; 875 } 876 uefi_call_wrapper(fh2->Close, 1, fh2); 877 uefi_call_wrapper(fh->Close, 1, fh); 878 return rc; 879 } 34. alias_transfer: Assigning: fi = buffer. 880 EFI_FILE_INFO *fi = buffer; 881 11. Condition !(fi->Attribute & 16), taking false branch. 21. Condition !(fi->Attribute & 16), taking false branch. CID 182858 (#1-3 of 3): Explicit null dereferenced (FORWARD_NULL)35. var_deref_op: Dereferencing null pointer fi. 882 if (!(fi->Attribute & EFI_FILE_DIRECTORY)) { 883 FreePool(buffer); 884 buffer = NULL; 885 continue; 886 } Because it doesn't know that when bs==0, fh2->Read() will return EFI_BUFFER_TOO_SMALL and set bs to the size we need to allocate, so the allocation path is always taken. Instead, handle our exit/error paths directly there, and make the allocation path nonconditional. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12fallback: find_boot_csv(): eliminate dead code.Peter Jones
Covscan sez: 720 FreePool(buffer); assignment: Assigning: buffer = NULL. 721 buffer = NULL; 722 723 CHAR16 *bootcsv=NULL, *bootarchcsv=NULL; 724 725 bs = 0; 726 do { 727 bs = 0; 728 rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, NULL); 729 if (EFI_ERROR(rc) && rc != EFI_BUFFER_TOO_SMALL) { 730 Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc); null: At condition buffer, the value of buffer must be NULL. dead_error_condition: The condition buffer cannot be true. 731 if (buffer) CID 182851 (#1 of 1): Logically dead code (DEADCODE)dead_error_line: Execution cannot reach this statement: FreePool(buffer);. 732 FreePool(buffer); 733 return rc; 734 } And it's right; buffer can never be non-NULL there. So just take that out. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12fallback: find_boot_csv(): Print the error from try_boot_csv()Peter Jones
Covscan believes the following: 782 if ((EFI_ERROR(rc) || !bootarchcsv) && bootcsv) { 783 EFI_FILE_HANDLE fh2; 784 rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, 785 bootcsv, EFI_FILE_READ_ONLY, 0); 786 if (EFI_ERROR(rc) || fh2 == NULL) { 787 Print(L"Couldn't open \\EFI\\%s\\%s: %d\n", 788 dirname, bootcsv, rc); 789 } else { CID 182829 (#1 of 1): Unused value (UNUSED_VALUE)returned_value: Assigning value from try_boot_csv(fh2, dirname, bootcsv) to rc here, but that stored value is overwritten before it can be used. 790 rc = try_boot_csv(fh2, dirname, bootcsv); 791 uefi_call_wrapper(fh2->Close, 1, fh2); 792 } 793 } value_overwrite: Overwriting previous write to rc with value 0UL. 794 rc = EFI_SUCCESS; 795 796 return rc; 797} Which isn't untrue, we just don't happen to be using the return code for anything, before we intentionally return success to our caller. So that's annoying, but whatever. Just print the error as well. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12fallback: read_file(): limit how big the file can be and still be validPeter Jones
Covscan says: 146 UINTN len = 0; 147 CHAR16 *b = NULL; 2. tainted_data_argument: Calling function get_file_size taints argument len. 148 rc = get_file_size(fh2, &len); 3. Condition (INTN)rc < 0, taking false branch. 149 if (EFI_ERROR(rc)) { 150 uefi_call_wrapper(fh2->Close, 1, fh2); 151 return rc; 152 } 153 4. overflow_assign: Assigning overflowed or truncated value (or a value computed from an overflowed or a truncated value) to b. 8. overflow: Add operation overflows on operands len and 2UL. Example value for operand: len = 18446744073709551614. 154 b = AllocateZeroPool(len + 2); Technically we can't handle a file larger than 0xfffffffffffffffd (on x86_64) because when we try to allocate the buffer to hold it with a trailing UCS-2 NUL we overflow to 0. Also our filesystem can't hold a file bigger than 4GB... So this is probably actually broken on 32-bit platforms. This patch limits it to some handy amount like 1024 * PAGE_SIZE, aka 4MB. Note that this doesn't appear to be exploitable (at least on edk2-based firmwares), because AllocateZeroPool() has a minimum granularity of 1 page, so even if you overflow it with a 4GB file, we'll get 1 page out of it and then try to read 1 byte into it, and then it's just going to be a parse error on the CSV. Even if we error on the sentinal UCS-2 NUL we put at the end, it'll still be inside of the zeroed page, and it still won't fault or overwrite any meaningful data. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12fallback: handle buffer allocations for fh->GetInfo() prettier.Peter Jones
At all the places we use fh->GetInfo, covscan can't tell that fh->GetInfo() will return EFI_BUFFER_TOO_SMALL and we'll allocate on the first try. If we just explicitly check for "buffer == NULL" as well, covscan believes we're doing work we don't need to (which is true!) So instead, put an rc test to return error for everything else there, so the allocation isn't in a conditional. Yet another stupid one, but it's easier to nerf it this way than write the false-positive rule, and it also hardens against incorrect UEFI implementations (though we've not seen any yet with the problem this avoids). Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12MokManager: get rid of struct menu_item, it is unused.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12MokManager: Fix a conditional on an uninitialized value in one error path.Peter Jones
clang-analyzer says: MokManager.c:1431:6: warning: Branch condition evaluates to a garbage value if (mok) ^~~ MokManager.c:1433:6: warning: Branch condition evaluates to a garbage value if (del_key) ^~~~~~~ And it's right; if we take the first error exit in the function, those never get initialized. This patch sets them to NULL to begin with. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12MokManager: handle mok parameter allocations better.Peter Jones
Covscan daftly claims: 288. var_compare_op: Comparing MokSB to null implies that MokSB might be null. 2330 if (MokSB) { 2331 menu_strings[i] = L"Change Secure Boot state"; 2332 menu_item[i] = MOK_CHANGE_SB; 2333 i++; 2334 } 2335 ... 2358 choice = console_select(perform_mok_mgmt, menu_strings, 0); 2359 if (choice < 0) 2360 goto out; ... 2362 switch (menu_item[choice]) { ... 2395 case MOK_CHANGE_SB: CID 182841 (#1 of 1): Dereference after null check (FORWARD_NULL)293. var_deref_model: Passing null pointer MokSB to mok_sb_prompt, which dereferences it. [show details] 2396 efi_status = mok_sb_prompt(MokSB, MokSBSize); Which is, of course, entirely false, beause for menu_item[choice] to be MOK_CHANGE_SB, MokSB must be !NULL. And then: 252. Condition efi_status == 0, taking true branch. 2397 if (efi_status == EFI_SUCCESS) 2398 MokSB = NULL; This guarantees it won't be in the list the next time through the loop. This adds tests for NULLness before mok_sb_prompt(), just to make it more clear to covscan what's going on. Also do the same thing for all of: MOK_CHANGE_SB MOK_SET_PW MOK_CHANGE_DB MOK_ENROLL_MOKX MOK_DELETE_MOKX I also Lindent-ed everything I had to touch. Three other minor errors are also fixed: 1) the loop in enter_mok_menu() leaked the menu allocations each time through the loop 2) mok_sb_prompt(), mok_pw_prompt(), and mok_db_prompt() all call FreePool() on their respective variables (MokSB, etc), and check_mok_request() also calls FreePool() on these. This sounds horrible, but it turns out it's not an issue, because they only free them in their EFI_SUCCESS paths, and enter_mok_menu() resets the system if any of the mok_XX_prompt() calls actually returned EFI_SUCCESS, so we never get back to check_mok_request() for it to do its FreePool() calls. 3) the loop in enter_mok_menu() winds up introducing a double free in the call to free_menu(), but we also can't hit this bug, because all the exit paths from the loop are "goto out" (or return error) rather than actually exiting on the loop conditional. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12MokManager: use EFI_ERROR() instead of comparing to EFI_SUCCESS.Peter Jones
Also consistently name our status variable "efi_status" unless there's a good reason not to, such as already having another one of those. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12MokManager: check_der_suffix(): use StrnCat() on our suffix checker.Peter Jones
We know it's legit already because we computed the pointer from the end, but covscan gets confused, and we have StrnCat, so we should just use it anyway. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12MokManager: Lindent (and other reformats) the whole file.Peter Jones
I'm just tired of all the little quirks. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12lib/shell.c: minor cleanupPeter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12lib/simple_file.c: minor cleanupPeter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12lib: Use EFI_ERROR() instead of comparing to EFI_SUCCESS everywhere.Peter Jones
Also consistently name our status variable "efi_status" unless there's a good reason not to, such as already having another one of those. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12lib: find_in_variable_esl(): Fix a tiny nitpick clang-analyze has.Peter Jones
clang-analyze believes the following: 311 EFI_STATUS 312 variable_enroll_hash(CHAR16 *var, EFI_GUID owner, 313 UINT8 hash[SHA256_DIGEST_SIZE]) 314 { 315 EFI_STATUS efi_status; 316 317 efi_status = find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE); > Calling 'find_in_variable_esl' → 260 EFI_STATUS 261 find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen) 262 { 263 UINTN DataSize; 264 UINT8 *Data; > ← 'Data' declared without an initial value → 265 EFI_STATUS efi_status; 266 267 efi_status = get_variable(var, &Data, &DataSize, owner); > ← Calling 'get_variable' → 237 EFI_STATUS 238 get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner) 239 { 240 return get_variable_attr(var, data, len, owner, NULL); > ← Calling 'get_variable_attr' → 213 EFI_STATUS 214 get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, 215 UINT32 *attributes) 216 { 217 EFI_STATUS efi_status; 218 219 *len = 0; 220 221 efi_status = GetVariable(var, &owner, NULL, len, NULL); > ← Calling 'GetVariable' → > ← Returning from 'GetVariable' → 222 if (efi_status != EFI_BUFFER_TOO_SMALL) > ← Assuming the condition is true → > ← Taking true branch → 223 return efi_status; 224 225 *data = AllocateZeroPool(*len); 226 if (!*data) 227 return EFI_OUT_OF_RESOURCES; 228 229 efi_status = GetVariable(var, &owner, attributes, len, *data); 230 if (EFI_ERROR(efi_status)) { 231 FreePool(*data); 232 *data = NULL; 233 } 234 return efi_status; 235 } And it can't figure out that the first GetVariable() call will, in fact, always return EFI_BUFFER_TOO_SMALL, and that AllocateZeroPool() will then *correctly* clobber the two variables we never assigned the value from. It also then believes that efi_status might have been returned /without/ being an error, and thinks that means we'll use the uninitialized pointer. This won't happen, but hey, let's make the code better express to the checker what is intended. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12lib: simple_file_selector(): remove some dead code.Peter Jones
clang-analyzer correctly believes this: 465 int i; 466 467 i = StrLen(name) - 1; ^ Value stored to 'i' is never read 468 469 for (i = StrLen(name); i > 0; --i) { 470 if (name[i] == '\\') 471 break; 472 } And it's right; that's completely dead code. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12lib: simple_file_selector(): simplify the error path to confuse covscan less.Peter Jones
Because they don't believe code should be defensive against future changes, covscan believes: 520 out_free: 521 FreePool(dmp); CID 182824 (#1 of 1): Dereference before null check (REVERSE_INULL)check_after_deref: Null-checking entries suggests that it may be null, but it has already been dereferenced on all paths leading to the check. 522 if (entries) { 523 free_entries(entries, count); 524 FreePool(entries); 525 } 526 out_free_name: 527 FreePool(name); 528} Which is technically correct, but still kind of dumb. So this patch combines the two error out paths into just being out_free, so that the first path there is before entries is allocated. (It also initializes dmp to NULL and checks that before freeing it.) I also Lindent-ed that function. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Use gcc's offsetof() instead of hacking out our own.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12CryptLib: Add the AsciiStrCpy() decl.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Get rid of all the places we cast to (CHAR16 *[])Peter Jones
Lindent gets confused by these, and they're hard to read anyway. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Fix some "if (x < 0)" tests where x is UINTN.Peter Jones
Obviously, these are not correct. Most of them are just useless; one can be changed to a more useful test. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Don't have tons of local guid definitions for no reason at all.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12lib/variables.c: reformat CreateTimeBasedPayload()Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Clean up efiauthenticated.h a lot.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Make sure all of our include files have proper guards.Peter Jones
... and make them all the same formatting too. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Move includes around to clean the source tree up a bit.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Rename generate_path() because we have 2 of it.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Fix the declaration of find_httpboot() to match its implementation.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Add "make scan-build" target.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Add a model file for coverity.Peter Jones
This is useful to hide some false positives from the covscan results. We never build it. Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Add 'make coverity' target.Peter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Split makefiles up a bitPeter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-12Document REQUIRE_TPMPeter Jones
Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-08Fix failure to boot on systems without a TPMHans de Goede
This commit fixes 2 issues with the TPM support code: 1) Remove "REQUIRE_TPM ?=" line from the Makefile, further down the Makefile checks if REQUIRE_TPM is undefined, but the above line sets it to an empty string, which is not the same as undefined. Without this handle_image fails after the tpm_log_pe() call even if REQUIRE_TPM=1 once was not set when building the shim 2) When secure-boot is disabled then shim_verify() would exit with the status of tpm_log_pe(), which on systems with a TPM is an error. Combined with the recent change to always install the shim protocols, this causes grub to refuse to boot any kernel since the verify() call now always fails. This commit fixes this by explicitly setting status = EFI_SUCCESS when secure-boot is disabled. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2018-03-06shim: Ignore UEFI LoadOptions that are just NUL characters.Peter Jones
I don't know when or why we ever see this, but it's easy enough to avoid. Resolves github issue #95 Signed-off-by: Peter Jones <pjones@redhat.com>
2018-03-06Install shim_lock protocol even when SecureBoot is offTamas K Lengyel
Currently the shim_lock protocol is only installed when SecureBoot is enabled. However, having Verify just measure into the TPM without SecureBoot is a useful feature. Signed-off-by: Tamas K Lengyel <lengyelt@ainfosec.com>
2018-03-06Fall-back TPM2 measurement if it fails with PE_COFF_IMAGE flagTamas K Lengyel
Signed-off-by: Tamas K Lengyel <lengyelt@ainfosec.com>
2018-03-06Add REQUIRE_TPM flag to treat TPM related errors as criticalTamas K Lengyel
Currently TPM related errors are being silently discarded. Signed-off-by: Tamas K Lengyel <lengyelt@ainfosec.com>
2018-03-06Measure into the TPM even if SecureBoot is off in shim_lock verifyTamas K Lengyel
Signed-off-by: Tamas K Lengyel <lengyelt@ainfosec.com>
2018-03-06Log measurements in PCR4 for applications being verified through shim_lockTamas K Lengyel
Currently the only measurement the shim logs in the TPM is that of the EFI application it directly loads. However, there are no measurements being taken of application that are being verified through the shim_lock protocol. In this patch we extend PCR4 for any binary for which Verify is being called through the shim_lock protocol. Signed-off-by: Tamas K Lengyel <lengyelt@ainfosec.com>