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

Preview: Add vTPM support for Linux #1082

Closed
wants to merge 1,247 commits into from

Conversation

stefanberger
Copy link
Contributor

@stefanberger stefanberger commented Sep 27, 2016

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 CreateCertificates parameter indicates that certificates for the TPM are
to be created.

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 stefanb@linux.vnet.ibm.com

@cyphar
Copy link
Member

cyphar commented Sep 27, 2016

Can you add a link to the corresponding PR in the runtime-spec?

@stefanberger
Copy link
Contributor Author

@cyphar I haven't sent a PR to the run-time spec, yet. Since this is a 'preview' I thought I'd just keep the all the changes, also the ones for the run-time spec, in this PR here ...

@stefanberger stefanberger force-pushed the vtpm branch 5 times, most recently from a50c766 to 9b4e911 Compare September 29, 2016 13:14
@stefanberger
Copy link
Contributor Author

stefanberger commented Sep 29, 2016

So here's the status of the code:

One can add several (v)TPMs to a container. For each vTPM a 'swtpm' process and vtpm_proxy device pair is spawned via an ioctl on /dev/vtpmx.

One can then start the TPM Software Stack (TSS, TrouSerS) inside a container. For this I am using a Fedora container in which I previously installed trousers and tpm-tools packages. To be able to start the TSS stack inside the container (as root) I found it necessary to add CAP_DAC_OVERRIDE to the capabilities in the config.json of my container:

 [...]
            "cwd": "/",
            "capabilities": [
                    "CAP_AUDIT_WRITE",
                    "CAP_KILL",
                    "CAP_NET_BIND_SERVICE",
                    "CAP_DAC_OVERRIDE"
            ],
 [...]

Besides that I enabled two vTPMs in config.json:

 [...]
            "resources": {
                    "devices": [
                            {
                                    "allow": false,
                                    "access": "rwm"
                            }
                    ] ,
                    "vtpms": [
                            {
                                    "statePath": "/tmp/foobar",
                                    "createCerts" : true
                            },
                            {
                                    "statePath": "/tmp/foobar2",
                                    "createCerts" : true
                            }
                    ]
            },
 [...]

Then it is possible to do the following:

[root@host mycontainer]# runc create test
[root@host mycontainer]# runc exec -t test bash
[root@runc /]# ls -l /dev/tpm*
crw-------. 1 root root  10, 224 Sep 29 13:51 /dev/tpm0
crw-------. 1 root root 254,   1 Sep 29 13:51 /dev/tpm1
[root@runc /]# tcsd -f &
[1] 24
[root@runc /]# TCSD TDDL ioctl: (25) Inappropriate ioctl for device
TCSD TDDL Falling back to Read/Write device support.
TCSD trousers 0.3.13: TCSD up and running.

[root@runc /]# tpm_takeownership
Enter owner password:
Confirm password:
Enter SRK password:
Confirm password:
[root@runc /]# tpm_clear
Enter owner password:
TPM Successfuly Cleared.  You need to reboot to complete this operation.  After reboot the TPM will be in the default state: unowned, disabled and inactive.
[root@runc /]# exit
exit
[root@host mycontainer]# ps aux | grep swtpm
tss       6296  1.6  0.0  31664  3620 ?        Ss   09:46   0:00 swtpm chardev --tpmstate dir=/tmp/foobar --daemon --fd 5 --pid file=/tmp/foobar/swtpm.pid --log file=/tmp/foobar/swtpm.log --runas tss
tss       6336  0.4  0.0  31664  3676 ?        Ss   09:47   0:00 swtpm chardev --tpmstate dir=/tmp/foobar2 --daemon --fd 6 --pid file=/tmp/foobar2/swtpm.pid --log file=/tmp/foobar2/swtpm.log --runas tss
root      6379  0.0  0.0 114328  2300 pts/0    S+   09:47   0:00 grep --color=auto swtpm
[root@host mycontainer]# runc delete test
[root@host mycontainer]# ps aux | grep swtpm
root      6389  0.0  0.0 114328  2096 pts/0    S+   09:47   0:00 grep --color=auto swtpm

Once ownership of the vTPM has been given up, the container would have to be delete and created again, since the vTPM needs to be reset.

@mrunalp
Copy link
Contributor

mrunalp commented Sep 29, 2016

@stefanberger Thanks for the PR. I would suggest that you open a PR to runtime-spec as well if you want to try to get this included in the 1.0 version of the spec which is getting closer. We can't really merge anything here without the spec changes being upstreamed first. We can of course review your changes meanwhile.

@stefanberger
Copy link
Contributor Author

@mrunalp If you want to review the changes in the meantime, that would be helpful.

// After successful creation of the object the Start() method can be called
func NewVTPM(statepath, vtpmversion string, createcerts, debug bool) (*VTPM, error) {
if len(statepath) == 0 {
return nil, fmt.Errorf("Missing required statpath for vTPM.")
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: error string that aren't logged start with lower case.

return nil, fmt.Errorf("VTPM device driver not available.")
}

if debug {
Copy link
Contributor

Choose a reason for hiding this comment

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

We could probably take out the debugs from the library.

@mrunalp
Copy link
Contributor

mrunalp commented Sep 30, 2016

@stefanberger I am trying to test this on Fedora Rawhide on (4.8 rc4 kernel). What do I have to do to install/enable VTPM driver?

@mrunalp mrunalp added this to the 1.0.0 milestone Oct 5, 2016
@stefanberger
Copy link
Contributor Author

stefanberger commented Oct 20, 2016

@mrunalp

  1. The Linux kernel has to be compiled with CONFIG_TCG_VTPM_PROXY either as module or built-in.
  2. Libtpms from Fedora can unfortunately currently not be used due to this bug here: https://bugzilla.redhat.com/show_bug.cgi?id=1385290

Instead one would have to git clone it from my git repo: https://github.com/stefanberger/libtpms/

git clone https://github.com/stefanberger/libtpms.git
cd libtpms
./bootstrap.sh
dnf builddep dist/libtpms.spec
./configure --prefix=/usr --with-openssl
make
make install
  1. swtpm is not packaged for Fedora, yet, so do the following
git clone https://github.com/stefanberger/swtpm.git
cd swtpm
./bootstrap.sh
dnf builddep dist/swtpm.spec
./configure --prefix=/usr --with-openssl
make
make install

@stefanberger stefanberger force-pushed the vtpm branch 2 times, most recently from 579b370 to 510c3c7 Compare October 27, 2016 14:37
@stefanberger
Copy link
Contributor Author

Regarding the need for CAP_DAC_OVERRIDE: This requirement is needed in the above 'demo' because 'tcsd' requires that /etc/tcsd.conf is owned by tss:tss. Therefore, it's not possible to just change the owner of this file to root:root because then tcsd will not run.

TCSD ERROR: TCSD config file (/etc/tcsd.conf) must be user/group tss/tss.

PS: Docker also sets CAP_DAC_OVERRIDE by default as one of the capabilities in the containers, so it would run there: https://github.com/docker/docker/blob/v1.12.3/oci/defaults_linux.go#L63

vbatts and others added 11 commits April 10, 2017 08:04
The current "For example, valid values for Linux..." wording in
config.md does not seem strong enough to support this condition,
especially since the spec makes no claims about what valid
capabilities are for non-Linux OSes.  And process.capabilities has
been nominally legal for non-Linux OSes since 718f9f3 (minor
narrative cleanup regarding config compatibility, 2017-01-30, opencontainers#673).

Signed-off-by: W. Trevor King <wking@tremily.us>
Catching up with erratum 499 [1].

[1]: https://www.rfc-editor.org/errata_search.php?rfc=2119&eid=499

Signed-off-by: W. Trevor King <wking@tremily.us>
specs-go/config: Add omitempty to LinuxSyscall.Args
spec: Add "NOT RECOMMENDED" to RFC 2119 keywords
config: Specify height/width units (characters) for consoleSize
…ames

I expect the (undocumented) intention here is to iterate through
'names' and call seccomp_rule_add(3) or similar for each name.  In
that case, an empty 'names' makes the whole syscall entry a no-op, and
with this commit we can warn users who are validating such configs.

If, on the other hand, we were comfortable with no-op syscall entries,
we'd want to make 'names' OPTIONAL.

Warning folks who accidentally empty (or don't set) 'names' seems more
useful to me, and doesn't restrict the useful config space, so that's
what I've gone with in this commit.

minItems is documented in [1], and there is an example of its use in
[2]:

  "options": {
    "type": "array",
    "minItems": 1,
    "items": { "type": "string" },
    "uniqueItems": true
  },

[1]: https://tools.ietf.org/html/draft-wright-json-schema-validation-00#section-5.11
[2]: http://json-schema.org/example2.html

Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: zhouhao <zhouhao@cn.fujitsu.com>
If the timeout value was zero, the hook would always error, and there
doesn't seem to be much point to that.  And I'm not sure what negative
timeouts would mean.  By adding this restriction, we do not limit
useful hook entries, and we give the validation code grounds to warn
users attempting to validate configs which are poorly defined or have
useless hook entries.

I'd like to remove the pointer from the Go type to comply with our
anti-pointer zero-value style (style.md) now that Go's zero-value is
clearly invalid.  However, there has been maintainer resistance to
removing the pointer [1] (although I don't think this is consistent
with previous maintainer statements that we don't need pointers when
the zero value is invalid [2]).  In order to land the normative spec
change, this commit keeps the current *int for Hook.Timeout and punts
a consistent policy to future work.

[1]: opencontainers/runtime-spec#764 (comment)
[2]: opencontainers/runtime-spec#653 (comment)

Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: zhouhao <zhouhao@cn.fujitsu.com>
Signed-off-by: zhouhao <zhouhao@cn.fujitsu.com>
crosbymichael and others added 4 commits August 22, 2017 11:05
.pullapprove.yml: Switch to v2 and other project-template updates
README: Make meetings monthly (were weekly)
Fixing a typo I'd made in 5292e9c (config: Make rlimits
POSIX-specific, 2017-05-23, opencontainers#880).

Signed-off-by: W. Trevor King <wking@tremily.us>
config: Add a trailing period to the "cannot be mapped" rlimits line
@mrunalp
Copy link
Contributor

mrunalp commented Sep 6, 2017

Needs rebase.

@deitch
Copy link
Contributor

deitch commented Sep 6, 2017

@mrunalp it does... but will @stefanberger do it? He is a great guy, putting in all this work, but if I had been the one who opened the PR, I would be loathe to rebase unless someone on the runc team told me they would merge it in once it is rebased.

@crosbymichael crosbymichael modified the milestones: 1.1.0, 1.0.0 Sep 6, 2017
@stefanberger
Copy link
Contributor Author

@deitch I will do the rebase. Give me some time. I have to catch up with other things after vacation. I also want to see it working in QEMU as well.
I sent this pull request a while ago but so far not having it integrated has worked to the benefit of being able to extend swtpm etc.

@stefanberger stefanberger force-pushed the vtpm branch 7 times, most recently from 3be4922 to ea857d9 Compare September 7, 2017 14:16
@Mashimiao
Copy link

Thanks for your catch. fixing in #1587

@stefanberger stefanberger force-pushed the vtpm branch 3 times, most recently from 2e1fe02 to 3d13c75 Compare September 8, 2017 15:17
Add the vTPM specification to the documentation and schema
description. The following is an example of a vTPM specification
that is found under the path /linux/resources/vtpms:

    "vtpms": [
        {
            "Statepath": "/tmp/tpm12_1_ubuntu",
            "VTPMVersion": "1.2",
            "CreateCertificates" : false
        }
    ]

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
@deitch
Copy link
Contributor

deitch commented Sep 8, 2017

Why did we close?

@stefanberger
Copy link
Contributor Author

I did not close this by going to this page. Maybe because I pushed the runtime-spec's vtpm branch over this branch here...

@crosbymichael
Copy link
Member

@stefanberger i cannot reopen, its not allowing me to.

@stefanberger
Copy link
Contributor Author

Opened this again as PR #1591.

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.