Skip to content

Commit a548859

Browse files
committed
vtpm: Run swtpm with an AppArmor profile
Create an AppArmor profile and apply it so that swtpm runs with an AppArmor profile. Signed-off-by: Stefan Berger <[email protected]>
1 parent 550b0b6 commit a548859

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

libcontainer/vtpm/vtpm.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515
"time"
1616
"unsafe"
1717

18+
"github.com/opencontainers/runc/libcontainer/apparmor"
19+
1820
"github.com/sirupsen/logrus"
1921
)
2022

@@ -53,6 +55,9 @@ type VTPM struct {
5355

5456
// The minor number of the created device
5557
minor uint32
58+
59+
// The AppArmor profile's full path
60+
aaprofile string
5661
}
5762

5863
// ioctl
@@ -432,6 +437,11 @@ again:
432437
return false, err
433438
}
434439

440+
err = vtpm.SetupAppArmor()
441+
if err != nil {
442+
return false, err
443+
}
444+
435445
tpmname := vtpm.GetTPMDevname()
436446
fdstr := fmt.Sprintf("%d", vtpm.fd)
437447
tpmstate := fmt.Sprintf("dir=%s", vtpm.StatePath)
@@ -462,6 +472,8 @@ again:
462472
return false, err
463473
}
464474

475+
apparmor.ApplyProfileTid("unconfined")
476+
465477
cmd = exec.Command("swtpm_bios", "-n", "-cs", "-u", "--tpm-device", tpmname)
466478
if vtpm.Vtpmversion == VTPM_VERSION_2 {
467479
cmd.Args = append(cmd.Args, "--tpm2")
@@ -503,6 +515,8 @@ func (vtpm *VTPM) Stop(deleteStatePath bool) error {
503515

504516
vtpm.CloseServer()
505517

518+
vtpm.TeardownAppArmor()
519+
506520
vtpm.Tpm_dev_num = VTPM_DEV_NUM_INVALID
507521

508522
if deleteStatePath {
@@ -551,5 +565,82 @@ func (vtpm *VTPM) CloseServer() error {
551565
os.NewFile(uintptr(vtpm.fd), "[vtpm]").Close()
552566
vtpm.fd = ILLEGAL_FD
553567
}
568+
569+
return nil
570+
}
571+
572+
// SetupAppArmor creates an apparmor profile for swtpm if AppArmor is enabled and
573+
// compiles it using apparmor_parser -r <filename> and activates it for the next
574+
// exec.
575+
func (vtpm *VTPM) SetupAppArmor() error {
576+
var statefilepattern string
577+
578+
if !apparmor.IsEnabled() {
579+
return nil
580+
}
581+
582+
profilename := fmt.Sprintf("runc_%d_swtpm_tpm%d",os.Getpid(), vtpm.GetTPMDevNum())
583+
if vtpm.Vtpmversion == VTPM_VERSION_1_2 {
584+
statefilepattern = "tpm-00.*"
585+
} else {
586+
statefilepattern = "tpm2-00.*"
587+
}
588+
589+
profile := fmt.Sprintf("\n#include <tunables/global>\n"+
590+
"profile %s {\n"+
591+
" #include <abstractions/base>\n"+
592+
" capability setgid,\n"+
593+
" capability setuid,\n"+
594+
" /dev/tpm[0-9]* rw,\n"+
595+
" owner /etc/group r,\n"+
596+
" owner /etc/nsswitch.conf r,\n"+
597+
" owner /etc/passwd r,\n"+
598+
" %s/.lock wk,\n"+
599+
" %s/swtpm.log w,\n"+
600+
" %s/swtpm.pid rw,\n"+
601+
" %s/%s rw,\n"+
602+
"}\n",
603+
profilename,
604+
vtpm.StatePath,
605+
vtpm.StatePath,
606+
vtpm.StatePath,
607+
vtpm.StatePath,
608+
statefilepattern)
609+
610+
vtpm.aaprofile = path.Join(vtpm.StatePath, "swtpm.apparmor")
611+
612+
err := ioutil.WriteFile(vtpm.aaprofile, []byte(profile), 0600)
613+
if err != nil {
614+
return err
615+
}
616+
defer func() {
617+
if err != nil {
618+
vtpm.TeardownAppArmor()
619+
}
620+
}()
621+
622+
cmd := exec.Command("/sbin/apparmor_parser", "-r", vtpm.aaprofile)
623+
output, err := cmd.CombinedOutput()
624+
if err != nil {
625+
return fmt.Errorf("apparmor_parser -r failed: %s", string(output))
626+
}
627+
628+
err = apparmor.ApplyProfileTid(profilename)
629+
if err != nil {
630+
return err
631+
}
632+
554633
return nil
555634
}
635+
636+
// TeardownAppArmor removes the AppArmor profile from the system and ensures
637+
// that the next time the process exec's no swtpm related profile is applied
638+
func (vtpm *VTPM) TeardownAppArmor() {
639+
apparmor.ApplyProfileTid("unconfined")
640+
if len(vtpm.aaprofile) > 0 {
641+
cmd := exec.Command("/sbin/apparmor_parser", "-R", vtpm.aaprofile)
642+
cmd.Run()
643+
os.Remove(vtpm.aaprofile)
644+
vtpm.aaprofile = ""
645+
}
646+
}

0 commit comments

Comments
 (0)