Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't make shim abort when TPM log event fails (RHBZ #2002265) #414

Merged
merged 1 commit into from
Sep 13, 2021

Conversation

rmetrich
Copy link
Contributor

@rmetrich rmetrich commented Sep 9, 2021

On Dell hardware booted in UEFI with option TPM 1.2 "On without Pre-Boot
Measurements", it appears that tpm_log_event() fails with Unsupported,
which causes Shim to abort due to believing it couldn't set up the
MokListRT, MokListXRT and SbatLevelRT variables.

This patch mimics what is done in Grub code: just ignore failures
related to the TPM.

Below is the verbose output of Shim.

  1. With original code
mok.c:358:mirror_mok_db() SetVariable("MokListRT", ... varsz=0x826) = Success^M
mok.c:792:mirror_one_mok_variable() mirror_mok_db("MokListRT",  datasz=2086) returned Success^M
mok.c:823:mirror_one_mok_variable() tpm_log_event(0x5C506020, 2086, 14, "MokList")->Unsupported^M
Could not create MokListRT: Unsupported^M
mok.c:940:import_one_mok_state() returning Unsupported^M
[... same for other variables ...]

Something has gone seriously wrong: import_mok_state() failed: Unsupported^M
  1. With the patch, the boot continues
mok.c:358:mirror_mok_db() SetVariable("MokListRT", ... varsz=0x826) = Success^M
mok.c:792:mirror_one_mok_variable() mirror_mok_db("MokListRT",  datasz=2086) returned Success^M
mok.c:824:mirror_one_mok_variable() tpm_log_event(0x5C506020, 2086, 14, "MokList")->Unsupported (ignored)^M
mok.c:836:mirror_one_mok_variable() returning Success^M
mok.c:940:import_one_mok_state() returning Success^M
[... same for other variables ...]

shim.c:1727:shim_init() UEFI SHIM^M

Copy link
Member

@frozencemetery frozencemetery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine to me.

mok.c Outdated
return efi_status;
if (EFI_ERROR(tpm_status)) {
dprint(L"tpm_measure_variable(\"%s\",%lu,0x%llx)->%r (ignored)\n",
v->name, FullDataSize, FullData, tpm_status);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know the codebase isn't great about this and the problem predates your change, but it would be nice to keep lines <80 characters when it's easy to do so.

Copy link
Contributor

@vathpela vathpela Sep 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I agree, but I also really don't like breaking output strings in the middle, as that makes them harder to grep for. So in this case not wrapping is the right thing IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed on the output string, but I'm actually talking about the next line (that supplies the other args to dprint()).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see. github's elision of most of the whitespace has fooled me.

@vathpela vathpela self-requested a review September 10, 2021 20:19
Copy link
Contributor

@vathpela vathpela left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like this approach. Firstly, I think this firmware is really broken. As I said in the private RH bugzilla:

Just reading code and not having any debugging information, this appears that when
"On without Pre-Boot Measurements" is selected, the firmware is registering a protocol
using EFI_TCG_PROTOCOL_GUID that has the expected methods.  That protocol provides
a ->StatusCheck() method which returns EFI_SUCCESS and sets the capabilities to
{.TPMPresentFlag = 1, .TPMDeactivatedFlag = 0}.  But then, it also provides a
->HashLogExtendEvent() method that returns EFI_UNSUPPORTED?

Is that what's happening?  If so, this seems wrong to me. Surely one of the following is
the correct way to implement this:

- set TPMPresentFlag = 0
- set TPMDeactivatedFlag = 1
- don't register the protocol if it's not going to implement anything

But also I'd like a more targeted workaround than ignoring all errors. In this case we're getting EFI_UNSUPPORTED back from calls that should be present, indicating that ->StatusCheck() is lying to us and providing a stubbed out, broken implementation. If that is what's going on, what we should do is add a "tpm_defective" status variable that defaults to false, make tpm_present() always return false if it is set, and make tpm 1.2 calls in tpm.c set it to false if the protocol method they're using gives us EFI_UNSUPPORTED.

On Dell hardware booted in UEFI with option TPM 1.2 "On without Pre-Boot
Measurements", it appears that `tpm_log_event()` fails with Unsupported,
which causes Shim to abort due to believing it couldn't set up the
MokListRT, MokListXRT and SbatLevelRT variables.

This patch ignore the error when trying to write to the TPM and sets the
TPM as 'defective' to not try to write to it anymore.

Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
@rmetrich
Copy link
Contributor Author

@vathpela Thanks for the review. I updated the code according to your suggestion.

@rmetrich
Copy link
Contributor Author

Log excerpt of the proposed code:

mok.c:896:import_one_mok_state() importing mok state for "MokList"
mok.c:936:import_one_mok_state() maybe mirroring "MokList".  original data:
[...]
lib/variables.c:24:fill_esl() fill_esl: first_sig=0x0, data_len=936
mok.c:606:mirror_one_mok_variable() FullDataSize:964 FullData:0x0
mok.c:640:mirror_one_mok_variable() v->name:"MokList" v->rtname:"MokListRT"
mok.c:641:mirror_one_mok_variable() v->data_size:1122 v->data:0x5C508020
mok.c:642:mirror_one_mok_variable() FullDataSize:964 FullData:0x0
mok.c:646:mirror_one_mok_variable() FullDataSize:2086 FullData:0x0
mok.c:669:mirror_one_mok_variable() FullDataSize:2086 FullData:0x0 allocating FullData
mok.c:689:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C506020 p:0x5C506020 pos:0
lib/variables.c:24:fill_esl() fill_esl: first_sig=0x5C508720, data_len=936
mok.c:718:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C506020 p:0x5C5063E4 pos:964
mok.c:731:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C506020 p:0x5C5063E4 pos:964
mok.c:755:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C506020 p:0x5C5063E4 pos:964
mok.c:761:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C506020 p:0x5C506846 pos:2086
mok.c:784:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C506020 p:0x5C506846 pos:2086
mok.c:787:mirror_one_mok_variable() calling mirror_mok_db("MokListRT",  datasz=2086)
mok.c:285:get_max_var_sz() max_var_sz:FFC4 remaining_sz:7B874 max_storage_sz:7FFE4
mok.c:358:mirror_mok_db() SetVariable("MokListRT", ... varsz=0x826) = Success
mok.c:792:mirror_one_mok_variable() mirror_mok_db("MokListRT",  datasz=2086) returned Success
Could not write TPM event: Unsupported. Considering the TPM as defective.
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:896:import_one_mok_state() importing mok state for "MokListX"
mok.c:936:import_one_mok_state() maybe mirroring "MokListX".  original data:
mok.c:611:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:640:mirror_one_mok_variable() v->name:"MokListX" v->rtname:"MokListXRT"
mok.c:641:mirror_one_mok_variable() v->data_size:0 v->data:0x0
mok.c:642:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:689:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:723:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:731:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
lib/variables.c:24:fill_esl() fill_esl: first_sig=0x0, data_len=48
lib/variables.c:24:fill_esl() fill_esl: first_sig=0x5C508520, data_len=48
mok.c:780:mirror_one_mok_variable() FullDataSize:76 FullData:0x5C508020 p:0x5C50806C pos:76
mok.c:784:mirror_one_mok_variable() FullDataSize:76 FullData:0x5C508020 p:0x5C50806C pos:76
mok.c:787:mirror_one_mok_variable() calling mirror_mok_db("MokListXRT",  datasz=76)
mok.c:285:get_max_var_sz() max_var_sz:FFC4 remaining_sz:7AFFC max_storage_sz:7FFE4
mok.c:358:mirror_mok_db() SetVariable("MokListXRT", ... varsz=0x4C) = Success
mok.c:792:mirror_one_mok_variable() mirror_mok_db("MokListXRT",  datasz=76) returned Success
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:896:import_one_mok_state() importing mok state for "MokSBState"
mok.c:936:import_one_mok_state() maybe mirroring "MokSBState".  original data:
mok.c:640:mirror_one_mok_variable() v->name:"MokSBState" v->rtname:"MokSBStateRT"
mok.c:641:mirror_one_mok_variable() v->data_size:0 v->data:0x0
mok.c:642:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:689:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:784:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:896:import_one_mok_state() importing mok state for "MokDBState"
mok.c:936:import_one_mok_state() maybe mirroring "MokDBState".  original data:
mok.c:640:mirror_one_mok_variable() v->name:"MokDBState" v->rtname:"MokIgnoreDB"
mok.c:641:mirror_one_mok_variable() v->data_size:0 v->data:0x0
mok.c:642:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:689:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:784:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:896:import_one_mok_state() importing mok state for "SbatLevel"
mok.c:936:import_one_mok_state() maybe mirroring "SbatLevel".  original data:
mok.c:937:import_one_mok_state() 00000000  73 62 61 74 2c 31 2c 32  30 32 31 30 33 30 32 31  |sbat,1,202103021|
mok.c:937:import_one_mok_state() 00000010  38 0a XX XX XX XX XX XX  XX XX XX XX XX XX XX XX  |8.|
mok.c:640:mirror_one_mok_variable() v->name:"SbatLevel" v->rtname:"SbatLevelRT"
mok.c:641:mirror_one_mok_variable() v->data_size:18 v->data:0x5C508520
mok.c:642:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:646:mirror_one_mok_variable() FullDataSize:18 FullData:0x0
mok.c:664:mirror_one_mok_variable() FullDataSize:18 FullData:0x5C508520 p:0x5C508532 pos:18
mok.c:689:mirror_one_mok_variable() FullDataSize:18 FullData:0x5C508520 p:0x5C508532 pos:18
mok.c:784:mirror_one_mok_variable() FullDataSize:18 FullData:0x5C508520 p:0x5C508532 pos:18
mok.c:791:mirror_one_mok_variable() SetVariable("SbatLevelRT", ... varsz=0x12) = Success
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:1045:import_mok_state() importing full mok state variables
[...]
mok.c:853:maybe_mirror_one_mok_variable() deleting "MokListRT"
mok.c:855:maybe_mirror_one_mok_variable() LibDeleteVariable("MokListRT",...) => Invalid Parameter
lib/variables.c:24:fill_esl() fill_esl: first_sig=0x0, data_len=936
mok.c:606:mirror_one_mok_variable() FullDataSize:964 FullData:0x0
mok.c:640:mirror_one_mok_variable() v->name:"MokList" v->rtname:"MokListRT"
mok.c:641:mirror_one_mok_variable() v->data_size:1122 v->data:0x5C505520
mok.c:642:mirror_one_mok_variable() FullDataSize:964 FullData:0x0
mok.c:646:mirror_one_mok_variable() FullDataSize:2086 FullData:0x0
mok.c:669:mirror_one_mok_variable() FullDataSize:2086 FullData:0x0 allocating FullData
mok.c:689:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C503020 p:0x5C503020 pos:0
lib/variables.c:24:fill_esl() fill_esl: first_sig=0x5C505A20, data_len=936
mok.c:718:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C503020 p:0x5C5033E4 pos:964
mok.c:731:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C503020 p:0x5C5033E4 pos:964
mok.c:755:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C503020 p:0x5C5033E4 pos:964
mok.c:761:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C503020 p:0x5C503846 pos:2086
mok.c:784:mirror_one_mok_variable() FullDataSize:2086 FullData:0x5C503020 p:0x5C503846 pos:2086
mok.c:787:mirror_one_mok_variable() calling mirror_mok_db("MokListRT",  datasz=2086)
mok.c:285:get_max_var_sz() max_var_sz:FFC4 remaining_sz:7AEF4 max_storage_sz:7FFE4
mok.c:792:mirror_one_mok_variable() mirror_mok_db("MokListRT",  datasz=2086) returned Success
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:896:import_one_mok_state() importing mok state for "MokListX"
mok.c:936:import_one_mok_state() maybe mirroring "MokListX".  original data:
mok.c:853:maybe_mirror_one_mok_variable() deleting "MokListXRT"
mok.c:855:maybe_mirror_one_mok_variable() LibDeleteVariable("MokListXRT",...) => Invalid Parameter
mok.c:611:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:640:mirror_one_mok_variable() v->name:"MokListX" v->rtname:"MokListXRT"
mok.c:641:mirror_one_mok_variable() v->data_size:0 v->data:0x0
mok.c:642:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:689:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:723:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:731:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
lib/variables.c:24:fill_esl() fill_esl: first_sig=0x0, data_len=48
lib/variables.c:24:fill_esl() fill_esl: first_sig=0x5C505E20, data_len=48
mok.c:780:mirror_one_mok_variable() FullDataSize:76 FullData:0x5C508120 p:0x5C50816C pos:76
mok.c:784:mirror_one_mok_variable() FullDataSize:76 FullData:0x5C508120 p:0x5C50816C pos:76
mok.c:787:mirror_one_mok_variable() calling mirror_mok_db("MokListXRT",  datasz=76)
mok.c:285:get_max_var_sz() max_var_sz:FFC4 remaining_sz:7AEF4 max_storage_sz:7FFE4
mok.c:792:mirror_one_mok_variable() mirror_mok_db("MokListXRT",  datasz=76) returned Success
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:896:import_one_mok_state() importing mok state for "MokSBState"
mok.c:936:import_one_mok_state() maybe mirroring "MokSBState".  original data:
mok.c:853:maybe_mirror_one_mok_variable() deleting "MokSBStateRT"
mok.c:855:maybe_mirror_one_mok_variable() LibDeleteVariable("MokSBStateRT",...) => Not Found
mok.c:640:mirror_one_mok_variable() v->name:"MokSBState" v->rtname:"MokSBStateRT"
mok.c:641:mirror_one_mok_variable() v->data_size:0 v->data:0x0
mok.c:642:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:689:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:784:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:896:import_one_mok_state() importing mok state for "MokDBState"
mok.c:936:import_one_mok_state() maybe mirroring "MokDBState".  original data:
mok.c:640:mirror_one_mok_variable() v->name:"MokDBState" v->rtname:"MokIgnoreDB"
mok.c:641:mirror_one_mok_variable() v->data_size:0 v->data:0x0
mok.c:642:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:689:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:784:mirror_one_mok_variable() FullDataSize:0 FullData:0x0 p:0x0 pos:0
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:896:import_one_mok_state() importing mok state for "SbatLevel"
mok.c:936:import_one_mok_state() maybe mirroring "SbatLevel".  original data:
mok.c:937:import_one_mok_state() 00000000  73 62 61 74 2c 31 2c 32  30 32 31 30 33 30 32 31  |sbat,1,202103021|
mok.c:937:import_one_mok_state() 00000010  38 0a XX XX XX XX XX XX  XX XX XX XX XX XX XX XX  |8.|
mok.c:853:maybe_mirror_one_mok_variable() deleting "SbatLevelRT"
mok.c:855:maybe_mirror_one_mok_variable() LibDeleteVariable("SbatLevelRT",...) => Invalid Parameter
mok.c:640:mirror_one_mok_variable() v->name:"SbatLevel" v->rtname:"SbatLevelRT"
mok.c:641:mirror_one_mok_variable() v->data_size:18 v->data:0x5C505FA0
mok.c:642:mirror_one_mok_variable() FullDataSize:0 FullData:0x0
mok.c:646:mirror_one_mok_variable() FullDataSize:18 FullData:0x0
mok.c:664:mirror_one_mok_variable() FullDataSize:18 FullData:0x5C505FA0 p:0x5C505FB2 pos:18
mok.c:689:mirror_one_mok_variable() FullDataSize:18 FullData:0x5C505FA0 p:0x5C505FB2 pos:18
mok.c:784:mirror_one_mok_variable() FullDataSize:18 FullData:0x5C505FA0 p:0x5C505FB2 pos:18
mok.c:836:mirror_one_mok_variable() returning Success
mok.c:940:import_one_mok_state() returning Success
mok.c:1057:import_mok_state() checking mok request
mok.c:1059:import_mok_state() mok returned Success
mok.c:1069:import_mok_state() returning Success
shim.c:1727:shim_init() UEFI SHIM
$Version: 15.4 $
$BuildMachine: Linux x86_64 x86_64 x86_64 GNU/Linux $
$Commit: master $
shim.c:898:load_image() attempting to load \EFI\redhat\grubx64.efi

@vathpela vathpela merged commit 11740ea into rhboot:main Sep 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants