Skip to content

Commit

Permalink
vtpm: Run swtpm with an AppArmor profile
Browse files Browse the repository at this point in the history
Create an AppArmor profile and apply it so that swtpm runs with an AppArmor
profile.

Signed-off-by: Stefan Berger <[email protected]>
  • Loading branch information
stefanberger committed Jan 6, 2020
1 parent 506d9ac commit 6eefa33
Showing 1 changed file with 95 additions and 0 deletions.
95 changes: 95 additions & 0 deletions libcontainer/vtpm/vtpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"time"
"unsafe"

"github.com/opencontainers/runc/libcontainer/apparmor"

"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -53,6 +55,9 @@ type VTPM struct {

// The minor number of the created device
minor uint32

// The AppArmor profile's full path
aaprofile string
}

// ioctl
Expand Down Expand Up @@ -435,6 +440,11 @@ again:
return false, err
}

err = vtpm.setupAppArmor()
if err != nil {
return false, err
}

tpmname := vtpm.GetTPMDevname()
fdstr := fmt.Sprintf("%d", vtpm.fd)
tpmstate := fmt.Sprintf("dir=%s", vtpm.StatePath)
Expand Down Expand Up @@ -465,6 +475,8 @@ again:
return false, err
}

vtpm.resetAppArmor()

cmd = exec.Command("swtpm_bios", "-n", "-cs", "-u", "--tpm-device", tpmname)
if vtpm.Vtpmversion == VTPM_VERSION_2 {
cmd.Args = append(cmd.Args, "--tpm2")
Expand Down Expand Up @@ -506,6 +518,8 @@ func (vtpm *VTPM) Stop(deleteStatePath bool) error {

vtpm.CloseServer()

vtpm.teardownAppArmor()

vtpm.Tpm_dev_num = VTPM_DEV_NUM_INVALID

if deleteStatePath {
Expand Down Expand Up @@ -554,5 +568,86 @@ func (vtpm *VTPM) CloseServer() error {
os.NewFile(uintptr(vtpm.fd), "[vtpm]").Close()
vtpm.fd = ILLEGAL_FD
}

return nil
}

// setupAppArmor creates an apparmor profile for swtpm if AppArmor is enabled and
// compiles it using apparmor_parser -r <filename> and activates it for the next
// exec.
func (vtpm *VTPM) setupAppArmor() error {
var statefilepattern string

if !apparmor.IsEnabled() {
return nil
}

profilename := fmt.Sprintf("runc_%d_swtpm_tpm%d", os.Getpid(), vtpm.GetTPMDevNum())
if vtpm.Vtpmversion == VTPM_VERSION_1_2 {
statefilepattern = "tpm-00.*"
} else {
statefilepattern = "tpm2-00.*"
}

profile := fmt.Sprintf("\n#include <tunables/global>\n"+
"profile %s {\n"+
" #include <abstractions/base>\n"+
" capability setgid,\n"+
" capability setuid,\n"+
" /dev/tpm[0-9]* rw,\n"+
" owner /etc/group r,\n"+
" owner /etc/nsswitch.conf r,\n"+
" owner /etc/passwd r,\n"+
" %s/.lock wk,\n"+
" %s/swtpm.log w,\n"+
" %s/swtpm.pid rw,\n"+
" %s/%s rw,\n"+
"}\n",
profilename,
vtpm.StatePath,
vtpm.StatePath,
vtpm.StatePath,
vtpm.StatePath,
statefilepattern)

vtpm.aaprofile = path.Join(vtpm.StatePath, "swtpm.apparmor")

err := ioutil.WriteFile(vtpm.aaprofile, []byte(profile), 0600)
if err != nil {
return err
}
defer func() {
if err != nil {
vtpm.teardownAppArmor()
}
}()

cmd := exec.Command("/sbin/apparmor_parser", "-r", vtpm.aaprofile)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("apparmor_parser -r failed: %s", string(output))
}

err = apparmor.ApplyProfileThread(profilename)
if err != nil {
return err
}

return nil
}

func (vtpm *VTPM) resetAppArmor() {
apparmor.ApplyProfileThread("unconfined")
}

// teardownAppArmor removes the AppArmor profile from the system and ensures
// that the next time the process exec's no swtpm related profile is applied
func (vtpm *VTPM) teardownAppArmor() {
vtpm.resetAppArmor()
if len(vtpm.aaprofile) > 0 {
cmd := exec.Command("/sbin/apparmor_parser", "-R", vtpm.aaprofile)
cmd.Run()
os.Remove(vtpm.aaprofile)
vtpm.aaprofile = ""
}
}

0 comments on commit 6eefa33

Please sign in to comment.