-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]> Signed-off-by: Stefan Berger <[email protected]> Signed-off-by: Stefan Berger <[email protected]>
- Loading branch information
1 parent
8633da8
commit 64e9c4c
Showing
9 changed files
with
736 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// + build linux | ||
|
||
package vtpmhelper | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"syscall" | ||
|
||
"github.com/opencontainers/runc/libcontainer/configs" | ||
"github.com/opencontainers/runc/libcontainer/vtpm" | ||
|
||
"github.com/opencontainers/runtime-spec/specs-go" | ||
"golang.org/x/sys/unix" | ||
) | ||
|
||
func addVTPMDevice(spec *specs.Spec, hostpath, devpath string, major, minor uint32) { | ||
var filemode os.FileMode = 0600 | ||
|
||
device := specs.LinuxDevice{ | ||
Path: hostpath, | ||
Devpath: devpath, | ||
Type: "c", | ||
Major: int64(major), | ||
Minor: int64(minor), | ||
FileMode: &filemode, | ||
} | ||
spec.Linux.Devices = append(spec.Linux.Devices, device) | ||
|
||
major_p := new(int64) | ||
*major_p = int64(major) | ||
minor_p := new(int64) | ||
*minor_p = int64(minor) | ||
|
||
ld := &specs.LinuxDeviceCgroup{ | ||
Allow: true, | ||
Type: "c", | ||
Major: major_p, | ||
Minor: minor_p, | ||
Access: "rwm", | ||
} | ||
spec.Linux.Resources.Devices = append(spec.Linux.Resources.Devices, *ld) | ||
} | ||
|
||
// Create a VTPM | ||
func CreateVTPM(spec *specs.Spec, vtpmdev *specs.VTPM, devnum int) (*vtpm.VTPM, error) { | ||
|
||
vtpm, err := vtpm.NewVTPM(vtpmdev.Statepath, vtpmdev.StatepathIsManaged, vtpmdev.TPMVersion, vtpmdev.CreateCertificates, vtpmdev.Runas, vtpmdev.PcrBanks) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Start the vTPM process; once stopped, the device pair will | ||
// also disappear | ||
err, vtpm.CreatedStatepath = vtpm.Start() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
hostdev := vtpm.GetTPMDevname() | ||
major, minor := vtpm.GetMajorMinor() | ||
|
||
devpath := fmt.Sprintf("/dev/tpm%d", devnum) | ||
addVTPMDevice(spec, hostdev, devpath, major, minor) | ||
|
||
// check if /dev/vtpmrm%d is available | ||
host_tpmrm := fmt.Sprintf("/dev/tpmrm%d", vtpm.GetTPMDevNum()) | ||
if fileInfo, err := os.Lstat(host_tpmrm); err == nil { | ||
if stat_t, ok := fileInfo.Sys().(*syscall.Stat_t); ok { | ||
devNumber := stat_t.Rdev | ||
devpath = fmt.Sprintf("/dev/tpmrm%d", devnum) | ||
addVTPMDevice(spec, host_tpmrm, devpath, unix.Major(devNumber), unix.Minor(devNumber)) | ||
} | ||
} | ||
|
||
return vtpm, nil | ||
} | ||
|
||
func setVTPMHostDevOwner(vtpm *vtpm.VTPM, uid, gid int) error { | ||
hostdev := vtpm.GetTPMDevname() | ||
// adapt ownership of the device since only root can access it | ||
if err := os.Chown(hostdev, uid, gid); err != nil { | ||
return err | ||
} | ||
|
||
host_tpmrm := fmt.Sprintf("/dev/tpmrm%d", vtpm.GetTPMDevNum()) | ||
if _, err := os.Lstat(host_tpmrm); err == nil { | ||
// adapt ownership of the device since only root can access it | ||
if err := os.Chown(host_tpmrm, uid, gid); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// SetVTPMHostDevsOwner sets the owner of the host devices to the | ||
// container root's mapped user id; if root inside the container is | ||
// uid 1000 on the host, the devices will be owned by uid 1000. | ||
func SetVTPMHostDevsOwner(config *configs.Config, uid, gid int) error { | ||
if uid != 0 { | ||
for _, vtpm := range config.VTPMs { | ||
if err := setVTPMHostDevOwner(vtpm, uid, gid); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func DestroyVTPMs(vtpms []*vtpm.VTPM) { | ||
for _, vtpm := range vtpms { | ||
vtpm.Stop(vtpm.CreatedStatepath) | ||
} | ||
} |
Oops, something went wrong.