stefanberger / swtpm

Libtpms-based TPM emulator with socket, character device, and Linux CUSE interface.
Other
576 stars 143 forks source link

Virtual Machine startup hangs when attaching a new TPM 2.0 #68

Closed 0xabe-io closed 6 years ago

0xabe-io commented 6 years ago

Hi,

First of all, thank you for the great work you've put into this project, I am able to have a fully working TPM 2.0 in a Windows 10 VM!

I am using:

To attach a new TPM, I edit the VM configuration with virsh and add the following:

<tpm model='tpm-crb'>
  <backend type='emulator' version='2.0'/>
</tpm>

When I start the VM, libvirt just hangs (i.e. it does not respond to any actions), there is no qemu process started even though swtpm_setup.sh and swtpm are running, the tpmstate directory has been created, it contains both tpm2-00.permall and .lock, and swtpm has the write lock on .lock.

To circumvent the issue, I keep note of the tpmstate directory, I kill both swtpm_setup.sh and swtpm processes. At that point, libvirt complains about the exit status of swtpm_setup and responds again, and the tpmstate directory is no longer present. So I manually create the directory and set the correct permissions and ownership. After that, I am able to start the VM with the TPM normally.

I am not sure whether it is a libvirt issue or a swtpm one, I'll try here first.

stefanberger commented 6 years ago

Are you running the latest version of libtpms from the tpm2-preview.rev146.v2 branch and swtpm from the tpm2-preview branch? Does make check -j8 on the swtpm project pass ? What host are you running this on (Fedora/Ubuntu)? If it has SELinux , can you disable SELinux using sudo setenforce 0 -- just in case. Can you check the contents of /var/log/swtpm/libvirt/qemu/<vmname>-swtpm.log ? Is there a file and anything in the file?

0xabe-io commented 6 years ago

I use the tpm2-preview.rev146.v2 branch of libtpms, I just don't have your last commit (stefanberger/libtpms@bb5d837cf8409c05ae2840728713982de67e02b6 build-sys: fix make distcheck) and for swtpm I am using the tpm2-preview.v2 branch at the latest commit.

here is the output of sudo make check:

PASS: test_vtpm_proxy
PASS: test_tpm2_vtpm_proxy
PASS: test_ctrlchannel2
PASS: test_ctrlchannel4
PASS: test_ctrlchannel
PASS: test_ctrlchannel3
PASS: test_encrypted_state
PASS: test_getcap
PASS: test_hashing
PASS: test_hashing2
PASS: test_init
PASS: test_locality
PASS: test_migration_key
PASS: test_resume_volatile
PASS: test_save_load_encrypted_state
PASS: test_save_load_state
PASS: test_setbuffersize
PASS: test_volatilestate
PASS: test_swtpm_bios
PASS: test_tpm_probe
PASS: test_wrongorder
PASS: test_tpm2_encrypted_state
PASS: test_tpm2_init
PASS: test_tpm2_getcap
PASS: test_tpm2_locality
PASS: test_tpm2_hashing
PASS: test_tpm2_hashing2
PASS: test_tpm2_hashing3
PASS: test_tpm2_migration_key
PASS: test_tpm2_resume_volatile
PASS: test_tpm2_savestate
PASS: test_tpm2_save_load_encrypted_state
FAIL: test_tpm2_save_load_state_3
PASS: test_tpm2_save_load_state_da_timeout
PASS: test_tpm2_setbuffersize
PASS: test_tpm2_volatilestate
PASS: test_tpm2_wrongorder
PASS: test_tpm2_probe
PASS: test_tpm2_swtpm_bios
PASS: test_commandline
^Cmake[3]: *** Deleting file 'test_parameters.log'
make[3]: *** [Makefile:1068: test_parameters.log] Error 130
make[2]: *** [Makefile:770: check-TESTS] Interrupt
make[1]: *** [Makefile:1163: check-am] Interrupt
make: *** [Makefile:442: check-recursive] Interrupt

CTRL+C after 2 hours and 30 minutes being stucked on test_parameters

As a normal user:

SKIP: test_vtpm_proxy
SKIP: test_tpm2_vtpm_proxy
PASS: test_ctrlchannel2
PASS: test_ctrlchannel4
PASS: test_ctrlchannel
PASS: test_ctrlchannel3
PASS: test_encrypted_state
PASS: test_getcap
PASS: test_hashing
PASS: test_hashing2
PASS: test_init
PASS: test_locality
PASS: test_migration_key
PASS: test_resume_volatile
PASS: test_save_load_encrypted_state
PASS: test_save_load_state
PASS: test_setbuffersize
PASS: test_volatilestate
PASS: test_swtpm_bios
PASS: test_tpm_probe
PASS: test_wrongorder
PASS: test_tpm2_encrypted_state
PASS: test_tpm2_init
PASS: test_tpm2_getcap
PASS: test_tpm2_locality
PASS: test_tpm2_hashing
PASS: test_tpm2_hashing2
PASS: test_tpm2_hashing3
PASS: test_tpm2_migration_key
PASS: test_tpm2_resume_volatile
PASS: test_tpm2_savestate
PASS: test_tpm2_save_load_encrypted_state
FAIL: test_tpm2_save_load_state_3
PASS: test_tpm2_save_load_state_da_timeout
PASS: test_tpm2_setbuffersize
PASS: test_tpm2_volatilestate
PASS: test_tpm2_wrongorder
PASS: test_tpm2_probe
PASS: test_tpm2_swtpm_bios
PASS: test_commandline
SKIP: test_parameters
SKIP: test_tpm2_parameters
PASS: test_swtpm_cert
PASS: test_tpm2_swtpm_cert
PASS: test_tpm2_swtpm_cert_ecc
SKIP: test_swtpm_setup_create_cert
SKIP: test_tpm2_swtpm_setup_create_cert
============================================================================
Testsuite summary for swtpm 0.1.0
============================================================================
# TOTAL: 47
# PASS:  40
# SKIP:  6
# XFAIL: 0
# FAIL:  1
# XPASS: 0
# ERROR: 0
============================================================================
See tests/test-suite.log
============================================================================

Content of test-suite.log:

=======================================
   swtpm 0.1.0: tests/test-suite.log
=======================================

# TOTAL: 47
# PASS:  40
# SKIP:  6
# XFAIL: 0
# FAIL:  1
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

SKIP: test_vtpm_proxy
=====================

Need to be root to run this test.
SKIP test_vtpm_proxy (exit status: 77)

SKIP: test_tpm2_vtpm_proxy
==========================

Need to be root to run this test.
SKIP test_tpm2_vtpm_proxy (exit status: 77)

FAIL: test_tpm2_save_load_state_3
=================================

Creating NVRAM location 01000000
Creating NVRAM location 01000001
Creating NVRAM location 01000002
Creating NVRAM location 01000003
Creating NVRAM location 01000004
Creating NVRAM location 01000005
Creating NVRAM location 01000006
Creating NVRAM location 01000007
Creating NVRAM location 01000008
Creating NVRAM location 01000009
Creating NVRAM location 01000010 for counter
Incrementing the counter at location 01000010
Checking NVRAM location 01000000
Checking NVRAM location 01000001
Checking NVRAM location 01000002
Checking NVRAM location 01000003
Checking NVRAM location 01000004
Checking NVRAM location 01000005
Checking NVRAM location 01000006
Checking NVRAM location 01000007
Checking NVRAM location 01000008
Checking NVRAM location 01000009
Checking counter value at location 01000010
Checking availability of key with perm. handle 0x81000000
Verifying signature with this key
Allocating SHA256 PCR bank

-sha512 is not a valid option

pcrallocate

Runs TPM2_PCR_Allocate

Allocates SHA-1 and/or SHA-256 banks for a full set of PCR 0-23.  Not all
TPMs support two banks

    [-pwdp platform hierarchy password (default empty)]
    -sha1 allocate a SHA-1 bank
    -sha256 allocate a SHA-256 bank
Error: PCR 0 in SHA512 bank should be available for read before reboot
Bad parameter sha512 for -halg

pcrread

Runs TPM2_PCR_Read

    -ha pcr handle
    -halg (sha1, sha256, sha384) (default sha256)
        -halg may be specified more than once
    [-of data file for first algorithm specified, in binary]
        (default do not save)
    [-ns no space, no text, no newlines, first algorithm]
        Used for scripting policy construction
    -se0 session handle / attributes (default NULL)
        01 continue
        80 audit
FAIL test_tpm2_save_load_state_3 (exit status: 1)

SKIP: test_parameters
=====================

Need to be root to run this test.
SKIP test_parameters (exit status: 77)

SKIP: test_tpm2_parameters
==========================

Need to be root to run this test.
SKIP test_tpm2_parameters (exit status: 77)

SKIP: test_swtpm_setup_create_cert
==================================

Need to be root to run this test.
SKIP test_swtpm_setup_create_cert (exit status: 77)

SKIP: test_tpm2_swtpm_setup_create_cert
=======================================

Need to be root to run this test.
SKIP test_tpm2_swtpm_setup_create_cert (exit status: 77)

I am on Arch Linux without selinux or apparmor.

Yes the log file is created and nothing wrong is reported in it:

Starting vTPM manufacturing as tss:tss @ Wed 01 Aug 2018 05:19:34 PM PDT
0xabe-io commented 6 years ago

Here is the command that hangs during the tests: swtpm/.libs/lt-swtpm socket --flags not-need-init -p 47448 --tpmstate dir=/tmp/tmp.wY68hL2FQi --ctrl type=tcp,port=47449

stefanberger commented 6 years ago

@0xabe-io What you are showing there is swtpm started by swtpm_setup. Can you find the command line of swtpm_setup during the test that is hanging?

I fixed the above error related to SHA512. You have an older version of tsspcrallocated package installed on the system than what the tests assume. To get the fix and and due to dependencies you would have to pull and compile libtpms first and then pull on swtpm to get around this error.

0xabe-io commented 6 years ago

I pulled and recompiled both libtpms and swtpm, and, as expected, test_tpm2_save_load_state_3 does not fail anymore.

Here is the process hierarchy ([...]/ is used to shorten the paths to the git repo):

/bin/bash ./test_parameters
└─ /bin/bash [...]/swtpm/src/swtpm_setup/swtpm_setup.sh --config [...]/swtpm/etc/swtpm_setup.conf --runas root --tpm-state /tmp/tmp.vrYeMkXzog --tpm [...]/swtpm/src/swtpm/swtpm socket --swtpm_ioctl [...]/swtpm/src/swtpm_ioctl/swtpm_ioctl
   └─ [...]/swtpm/src/swtpm/.libs/lt-swtpm socket --flags not-need-init -p 59623 --tpmstate dir=/tmp/tmp.vrYeMkXzog --ctrl type=tcp,port=59624
stefanberger commented 6 years ago

Can you add set -x to the first few lines of src/swtpm_setup/swtpm_setup.sh:

#!/bin/bash
set -x
#
# swtpm_setup.sh

You can also add it to swtpm_setup.sh.in, which then survives a configure but you would need to run ./configure ... for this line to get into swtpm_setup.sh.

Assuming /tmp doesn't have any valuable TPM state, can you please run the following command and post the output:

sudo ./src/swtpm_setup/swtpm_setup --config ./etc/swtpm_setup.conf --runas root --tpm-state /tmp --tpm "./src/swtpm/swtpm socket" --swtpm_ioctl ./src/swtpm_ioctl/swtpm_ioctl --overwrite

I hope this leads us to a solution.

stefanberger commented 6 years ago

Which version of ArchLinux are you running? I could try to spin up a VM somewhere running the same version.

0xabe-io commented 6 years ago

OK, I don't have netstat because it is part of the net-tools package that is not installed by default on Arch. They set the package as deprecated and encourage to use ss (iproute2 package) instead (https://wiki.archlinux.org/index.php/Core_utilities#ss). I am using the x86_64 version. They don't have release versions because it is a rolling release kind of distro.

Now that I have netstat:

[...]
============================================================================
Testsuite summary for swtpm 0.1.0
============================================================================
# TOTAL: 47
# PASS:  47
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0
============================================================================
[...]

Now everything is fine, thanks for your support!

stefanberger commented 6 years ago

I now pushed a patch that checks for availability of the netstat tool: https://github.com/stefanberger/swtpm/commit/47df05a6a5d0c0d4d691a24b1113708f37cdeab2

Moving away from netsat may be nice to have some time in the future. Though likely it will stay around even if the package is unmaintained.

0xabe-io commented 6 years ago

The check works when I run the following command:

$ sudo ./src/swtpm_setup/swtpm_setup --config ./etc/swtpm_setup.conf --runas root --tpm-state /tmp --tpm "./src/swtpm/swtpm socket" --swtpm_ioctl ./src/swtpm_ioctl/swtpm_ioctl --overwrite
Starting vTPM manufacturing as root:root @ Fri 03 Aug 2018 04:00:11 PM PDT
Error: netstat is not installed.
Error: An error occurred. Authoring the TPM state failed.
Ending vTPM manufacturing @ Fri 03 Aug 2018 04:00:11 PM PDT

However sudo make check still hangs without netstats. It is not hanging on test_parameters as it was before. That test fails because it correctly detects that netstat is not available:

Error: netstat is not installed.

It hangs on both test_tpm2_swtpm_setup_create_cert and test_tpm2_parameters tests which don't seem to invoke the new check_tool function.

/bin/bash ./test_tpm2_swtpm_setup_create_cert
└─ /bin/bash [...]/swtpm/src/swtpm_setup/swtpm_setup.sh --tpm2 --allow-signing --runas root --tpm-state /tmp/tmp.HirviUHk74 --create-ek-cert --create-platform-cert --config /tmp/tmp.HirviUHk74/swtpm_setup.conf --logfile /tmp/tmp.HirviUHk74/logfile --tpm [...]/swtpm/src/swtpm/swtpm socket --swtpm_ioctl [...]/swtpm/src/swtpm_ioctl/swtpm_ioctl
   └─ [...]/swtpm/src/swtpm/.libs/lt-swtpm socket --tpm2 --flags not-need-init -p 52206 --tpmstate dir=/tmp/tmp.HirviUHk74 --ctrl type=tcp,port=52207

/bin/bash ./test_tpm2_parameters
└─ /bin/bash [...]/swtpm/src/swtpm_setup/swtpm_setup.sh --tpm2 --config [...]/swtpm/etc/swtpm_setup.conf --runas root --tpm-state /tmp/tmp.m01ReKlvqd --tpm [...]/swtpm/src/swtpm/swtpm socket --swtpm_ioctl [...]/swtpm/src/swtpm_ioctl/swtpm_ioctl
   └─ [...]/swtpm/src/swtpm/.libs/lt-swtpm socket --tpm2 --flags not-need-init -p 49946 --tpmstate dir=/tmp/tmp.m01ReKlvqd --ctrl type=tcp,port=49947
stefanberger commented 6 years ago

My bad. The TPM 2 case uses start_tpm() as well and needs to have a check done before it as. I pushed a patch.

I hope all tests are passing now.

stefanberger commented 6 years ago

I removed swtpm_setup's dependency on netstat now.

0xabe-io commented 6 years ago

Yes everything seems to be OK now, make fails if netstat is not present