Skip to content

SIGSEGV in tr_from_tpm_public #565

Open
@rucoder

Description

@rucoder

I suddenly caused a SIGSEGC in libtss2-esys.so.0

rust-lldb output with unimportant stuff omitted

running 1 test
Process 2162779 stopped and restarted: thread 2 received signal: SIGCHLD
Process 2162779 stopped
* thread #2, name = 'tpm::tests::cre', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0x0)
    frame #0: 0x00007ffff7eaab60 libtss2-esys.so.0`Esys_TR_FromTPMPublic_Finish + 288
libtss2-esys.so.0`Esys_TR_FromTPMPublic_Finish:
->  0x7ffff7eaab60 <+288>: movl   (%rax), %edx
    0x7ffff7eaab62 <+290>: movq   -0x58(%rbp), %rax
    0x7ffff7eaab66 <+294>: movl   0x48(%rax), %esi
    0x7ffff7eaab69 <+297>: callq  0x7ffff7eaa7c0 ; Esys_TR_FromTPMPublic_Async
(lldb) bt
* thread #2, name = 'tpm::tests::cre', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0x0)
  * frame #0: 0x00007ffff7eaab60 libtss2-esys.so.0`Esys_TR_FromTPMPublic_Finish + 288
    frame #1: 0x00007ffff7eab185 libtss2-esys.so.0`Esys_TR_FromTPMPublic + 85
    frame #2: 0x00005555556f4b91 micro_eve-33764688d1f6d89d`tss_esapi::context::general_esys_tr::_$LT$impl$u20$tss_esapi..context..Context$GT$::tr_from_tpm_public::h4782c5a79ff95a56(self=0x00007ffff73fe558, tpm_handle=TpmHandle @ 0x00007ffff73fe358) at general_esys_tr.rs:247:17
    frame #3: 0x000055555560251f micro_eve-33764688d1f6d89d`micro_eve::tpm::tests::__test_context_wrapped_create_primary_key_sigsegv::h6c963b7cc02eada8(test_context=0x00007ffff73ff500) at tests.rs:759:26
    frame #4: 0x000055555560e875 micro_eve-33764688d1f6d89d`micro_eve::tpm::tests::create_primary_key_sigsegv::_$u7b$$u7b$closure$u7d$$u7d$::h9bd64473262dd6bd at tests.rs:633:1
    frame #5: 0x0000555555609c99 micro_eve-33764688d1f6d89d`std::panicking::try::do_call::ha96e6dc036e27b27(data="") at panicking.rs:557:40
    frame #6: 0x000055555560c6cb micro_eve-33764688d1f6d89d`__rust_try + 27

here is the code I use to reproduce. This is a full test I run in my repo, it uses test-context crate but only to track sessions to swtpm so let mut tpm_context = get_tpm_context_from_tcti(&test_context.get_tcti_name()).unwrap(); can be changed to any call to get Context

Tested on main branch as well

fn create_primary_key_sigsegv(test_context: &SwtpmContext) -> Result<()> {
    fn create_primary_key_on_tpm(ctx: &mut Context) -> Result<CreatePrimaryKeyResult> {
        let creation_pcrs = PcrSelectionList::builder()
            .with_selection(HashingAlgorithm::Sha256, &[PcrSlot::Slot7])
            .build()?;

        let attrs = ObjectAttributes::builder()
            .with_no_da(true)
            .with_decrypt(true)
            .with_sensitive_data_origin(true)
            .with_user_with_auth(true)
            .with_sign_encrypt(true)
            .build()
            .context("Error creating ObjectAttributes")?;

        let ecc_params = PublicEccParameters::builder()
            .with_curve(EccCurve::NistP256)
            //TODO: check following two parameters
            .with_ecc_scheme(EccScheme::Null)
            .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
            .build()
            .context("Error creating PublicEccParameters")?;

        let public = Public::builder()
            .with_public_algorithm(PublicAlgorithm::Ecc)
            .with_ecc_parameters(ecc_params)
            .with_ecc_unique_identifier(EccPoint::default()) //TODO: this is not in GO
            .with_object_attributes(attrs)
            .with_name_hashing_algorithm(HashingAlgorithm::Sha256)
            .build()?;

        let key_handle = ctx.execute_with_session(Some(AuthSession::Password), |ctx| {
            ctx.create_primary(
                Hierarchy::Owner,
                public,
                None,
                None,
                None,
                Some(creation_pcrs),
            )
        });
        Ok(key_handle?)
    }

    let mut tpm_context = get_tpm_context_from_tcti(&test_context.get_tcti_name()).unwrap();
    tpm_context.set_sessions((Some(AuthSession::Password), None, None));

    // create 2 keys and make them persistent
    for i in 0..1 {
        let key_handle = create_primary_key_on_tpm(&mut tpm_context)?;
        let persistent_key_handle = PersistentTpmHandle::new(DEVICE_KEY_PERSISTENT_HANDLE - i)?;

        //debug!("Primary key created. Public {:#?}", key_handle.out_public);
        // make new key persistent
        let mut persistent_object_handle = tpm_context.evict_control(
            Provision::Owner,
            key_handle.key_handle.into(),
            persistent_key_handle.into(),
        )?;

        // TODO: this works, but should it be done?
        debug!("PH: {:#02x}", persistent_object_handle.value());
        tpm_context.tr_close(&mut persistent_object_handle)?;

        // the key is loaded into TPM and consumes resources. We need to flush it
        tpm_context.flush_context(key_handle.key_handle.into())?;
    }

    // PersistentTpmHandle implelemts Copy so we can treat it as integer and pass around without cloning
    let persistent_key_handle = PersistentTpmHandle::new(DEVICE_KEY_PERSISTENT_HANDLE)?;
    let _tpm_key_handle = tpm_context.tr_from_tpm_public(persistent_key_handle.into())?;

    Ok(())
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions