Skip to content

Feature: implement swtpm in runc #4855

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

Draft
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

everzakov
Copy link

This patch series adds a vTPM support for Linux to libcontainer.

The functionality is based on swtpm_cuse binary to create cuse device on which a TPM emulator listen for TPM commands. If we for example want to create vtpmName device then we make this device available as /dev/tpm + vtpmName inside the container. We also add its major and minor numbers to the device cgroup.

We implement a VTPM class that allows us to create the device and starts a TPM emulator 'swtpm_cuse'. Besides that, the user can choose to have the vTPM create certificates in a step that simulates TPM manufacturing. We do this by calling the external swtpm_setup program, which is a part of the swtpm project.

vTPM support is added inside the JSON configuration as follows:

[...]
    "linux": {
        "resources": {
            "devices": [
                {
                    "allow": false,
                    "access": "rwm"
                }
            ] ,
           "vtpms": [
                {
                   "statePath": "/var/lib/runc/myvtpm1",
                   "statePathIsManaged": false,
                   "vtpmVersion": "2",
                   "createCerts": false,
                    "runAs": "tss",
                    "pcrBanks": "sha1,sha512",
                    "encryptionPassword": "mysecret",
                    "vtpmName": "tpm0",
                    "vtpmMajor": 100,
                    "vtpmMinor": 1
                }
            ]
        },

This JSON markup makes a single TPM available inside the created container:

  • The statePath parameter indicates the directory where the TPM emulator 'swtpm_cuse' writes the state of the TPM device to.
  • The createCerts parameter indicates that certificates for the TPM are to be created.
  • The vtpmName parameter indicates that /dev/tpm + vtpmName device will be created under container rootfs.

Users can have a requirement to create 2 containers with separated vTPM devices with the same vtpmName in the container rootfs. In the host the created vTPM will have the devpath like that: /dev/tpm + hash of runc root + "-" + containerName + "-" + vtpmName. vTPM devices require runc to be run by root. If runc is running in non-default user namespace or have user namespace in config, then /dev/tpm + hash of runc root + "-" + containerName + "-" + vtpmName will be passed to the container instead of /dev/tpm + vtpmName.

There are several checks to be sure that vTPM devices are unique and won't miss the state between themselves:

  1. vtpmName should be unique
  2. statePath should be unique
  3. no swtpm_cuse / runc runned with the same statePath

The third check is done by starting 'swtpm_cuse' by checking two file locks on '.runc-lock' and '.lock' in the state dir.

In order to run unit / integration tests in the docker container you should also add vtpmMajor and vtpmMinor parameters to the vTPM spec, add them to the cgroup allow rule and pass /dev/cuse device. This is done because tmpfs is usually mounted on the container's /dev/path that's why the new devices won't be propagated to the test container. Also, swtpm.sh script is added to download swtpm and libtpms source code to the test container and build it. google/go-tpm is added to the dependency list because it is used in tpm-helper binary to check vTPM devices in the integration tests.

This PR is based on the previous PR.

The swtpm project is available here

The libtpms project is available here

stefanberger and others added 29 commits August 16, 2025 19:39
This patch adds vTPM support for Linux to libcontainer.

The functionality is based on a recently added vtpm_proxy driver, which
is becoming available in Linux 4.8. The driver provides /dev/vtpmx, on
which an ioctl is called that spawns a TPM device in the host's /dev
directory and returns an anonymous file-descriptor on which a TPM emulator
can listen for TPM commands. If we for example created /dev/tpm12 on the
host we make this device available as /dev/tpm0 inside the container. We
also add its major and minor numbers to the device cgroup.

We implement a VTPM class that allows us to create the device and starts
a TPM emulator 'swtpm', to which it passes the anonymous file descriptor.
Besides that, the user can choose to have the vTPM create certificates in
a step that simulates TPM manufacturing. We do this by calling the external
swtpm_setup program, which is part of the swtpm project.

VTPM support is added inside the JSON configuration as follows:

[...]
	"linux": {
		"resources": {
			"devices": [
				{
					"allow": false,
					"access": "rwm"
				}
			] ,
			"vtpms": [
				{
					"statePath": "/tmp/tpm-1",
					"createCerts": true
				},
			]
		},
[...]

This JSON markup makes a single TPM available inside the created container.

o The statPath parameter indicates the directory where the TPM emulator
  'swtpm' writes the state of the TPM device to.
o The createCerts parameter indicates that certificates for the
  TPM are to be created.

The current implementation does not support checkpointing, so checkpointing
of a container with an attached vTPM is prevented.

The swtpm project is available here  : https://github.com/stefanberger/swtpm
The libtpms project is available here: https://github.com/stefanberger/libtpms

Signed-off-by: Stefan Berger <[email protected]>
Create an AppArmor profile and apply it so that swtpm runs with an AppArmor
profile.

Signed-off-by: Stefan Berger <[email protected]>
On systems supporting SELinux run swtpm with an SELinux label
applied. Also label the required files in the state directory.

Signed-off-by: Stefan Berger <[email protected]>
Add test cases for testing TPM 1.2 and TPM 2 by creating, stopping,
restarting, and destroying it.

Signed-off-by: Stefan Berger <[email protected]>
Call 'swtpm chardev --print-capabilities' to get the supported capabilites
from swtpm. An JSON object is printed by swtpm that we unmarshal and
we pick the 'features' part from it that is an array of strings indicating
what this version of swtpm supports. This option was added in v0.2.
For older versions of swtpm we return an empty array.

Signed-off-by: Stefan Berger <[email protected]>
We need to startup the TPM as part of starting swtpm so that the Linux
driver can successfully send its initial command to the vTPM and does
not log a failure and then do the startup itself.

Signed-off-by: Stefan Berger <[email protected]>
This patch adds support for encrypting the vTPM state by allowing
a user to pass a password to swtpm_setup and swtpm.

Signed-off-by: Stefan Berger <[email protected]>
Add /sys/devices/virtual/tpm to the mask paths to avoid isolation
issues via sysfs for TPM 1.2

Signed-off-by: Stefan Berger <[email protected]>
Put vTPMs into a container's cgroup to limit their CPU usage.

Signed-off-by: Stefan Berger <[email protected]>
Signed-off-by: Efim Verzakov <[email protected]>
Signed-off-by: Efim Verzakov <[email protected]>
Signed-off-by: Efim Verzakov <[email protected]>
Signed-off-by: Efim Verzakov <[email protected]>
Signed-off-by: Efim Verzakov <[email protected]>
Signed-off-by: Efim Verzakov <[email protected]>
Signed-off-by: Efim Verzakov <[email protected]>
@everzakov everzakov marked this pull request as draft August 16, 2025 21:12
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.

2 participants