Skip to content

SIGSEGV in tr_from_tpm_public #565

@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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions