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

Use a single TPM context and avoid race conditions during tests #870

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ansasaki
Copy link
Contributor

@ansasaki ansasaki commented Nov 20, 2024

This implements a singleton to use a single instance of the
tss_espi::Context.

This also avoids race conditions by using a thread-safe mutex to access
the context.

The tests were modified to cleanup generated key handles between test
cases, preventing leftover handles to fill the TPM memory.

Introduce a mutex to allow only a single test that create keys in the
TPM to run at once. It is required that tests that create keys in the
TPM to run the tpm::testing::lock_tests() to obtain the mutex and be
able to continue executing without the risk of other tests filling the
TPM memory.

The QuoteData::fixture implementation (used only during tests) was
modified to flush the created key contexts when dropped. It also was
modified to lock the global mutex by calling the
tpm::testing::lock_tests() and provide the respective guard, preventing
other tests that use the fixture (which necessarily create TPM keys) to
run in parallel.

Note that it is necessary to drop the QuoteData fixture explicitly to guarantee
that the keys are flushed before releasing the global mutex.

Finally, the following changes were made to the tests/run.sh:

  • Do not use tpm2-abrmd anymore, and use only the swtpm socket instead
  • Stop the started processes at exit

With all these changes, the tests/run.sh can now be executed locally
without any special setting.

This also adds a script to initialize a software TPM locally for testing.

Fixes #259

Copy link
Member

@THS-on THS-on left a comment

Choose a reason for hiding this comment

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

Had a brief look and LGTM, only a small question

tests/run.sh Outdated Show resolved Hide resolved
@THS-on
Copy link
Member

THS-on commented Nov 21, 2024

/packit retest-failed

@ansasaki ansasaki marked this pull request as draft November 22, 2024 08:54
@ansasaki ansasaki marked this pull request as ready for review November 22, 2024 19:45
Copy link

codecov bot commented Nov 22, 2024

Codecov Report

Attention: Patch coverage is 75.26316% with 47 lines in your changes missing coverage. Please review.

Project coverage is 60.08%. Comparing base (2f7b3ad) to head (08c750a).
Report is 64 commits behind head on master.

Files with missing lines Patch % Lines
keylime/src/tpm.rs 79.38% 27 Missing ⚠️
keylime-agent/src/main.rs 64.70% 18 Missing ⚠️
keylime-agent/src/agent_handler.rs 0.00% 1 Missing ⚠️
keylime-agent/src/keys_handler.rs 75.00% 1 Missing ⚠️
Additional details and impacted files
Flag Coverage Δ
e2e-testsuite 60.08% <75.26%> (+2.49%) ⬆️
upstream-unit-tests 60.08% <75.26%> (+9.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
keylime-agent/src/common.rs 67.94% <ø> (ø)
keylime-agent/src/notifications_handler.rs 66.66% <100.00%> (ø)
keylime-agent/src/quotes_handler.rs 51.90% <100.00%> (+1.04%) ⬆️
keylime-agent/src/agent_handler.rs 57.44% <0.00%> (ø)
keylime-agent/src/keys_handler.rs 64.72% <75.00%> (-0.72%) ⬇️
keylime-agent/src/main.rs 22.29% <64.70%> (-3.73%) ⬇️
keylime/src/tpm.rs 72.05% <79.38%> (+5.86%) ⬆️

... and 9 files with indirect coverage changes

@ansasaki
Copy link
Contributor Author

ansasaki commented Nov 28, 2024

So I ended up implementing a mutex to let only a single test that creates keys in the TPM to run at once. This allows the tests to run in parallel, in multiple threads. I believe some of the flakyness we saw in the past is now solved.

@THS-on Could you please take a look again?

@ansasaki
Copy link
Contributor Author

/packit retest-failed

@ansasaki
Copy link
Contributor Author

/packit test

This implements a singleton to use a single instance of the
tss_espi::Context.

This also avoids race conditions by using a thread-safe mutex to access
the context.

The tests were modified to cleanup generated key handles between test
cases, preventing leftover handles to fill the TPM memory.

Introduce a mutex to allow only a single test that create keys in the
TPM to run at once.  It is required that tests that create keys in the
TPM to run the tpm::testing::lock_tests() to obtain the mutex and be
able to continue executing without the risk of other tests filling the
TPM memory.

The QuoteData::fixture implementation (used only during tests) was
modified to flush the created key contexts when dropped. It also was
modified to lock the global mutex by calling the
tpm::testing::lock_tests() and provide the respective guard, preventing
other tests that use the fixture (which necessarily create TPM keys) to
run in parallel.

Note that it is necessary to drop the QuoteData explicitly to guarantee
that the keys are flushed before releasing the global mutex.

Finally, the following changes were made to the tests/run.sh:

* Do not use tpm2-abrmd anymore, and use only the swtpm socket instead
* Stop the started processes at exit

With all these changes, the tests/run.sh can now be executed locally
without any special setting.

Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
Add the tests/setup_swtpm.sh script which setup a Software TPM in a
temporary directory, starts the swtpm socket, and sets the environment
TCTI accordingly.

This allows the tests to be executed locally, even with the "testing"
feature.

Unfortunately, it is not possible to cleanup some of the transient
objects created during tests, being necessary to cleanup manually
between runs by running:

$ tpm2_flushcontext -t -l -s

Another caveat is that the tests need to run on a single thread to avoid
test cases that create objects to run in parallel, which can fill up the
TPM memory with transient object contexts. For this, please run the
tests on a single thread:

$ cargo test --features=testing -- --test-threads=1

The swtpm socket process is stopped when exiting from the started shell.

Fixes: keylime#259

Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
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.

Include a straightforward way to use the swtpm
5 participants