@@ -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
@@ -56,6 +58,9 @@ type VTPM struct {
5658
5759 // process id of this vtpm
5860 Pid int
61+
62+ // The AppArmor profile's full path
63+ aaprofile string
5964}
6065
6166// ioctl
@@ -452,6 +457,11 @@ func (vtpm *VTPM) startSwtpm() error {
452457 return err
453458 }
454459
460+ err = vtpm .setupAppArmor ()
461+ if err != nil {
462+ return err
463+ }
464+
455465 tpmstate := fmt .Sprintf ("dir=%s" , vtpm .StatePath )
456466 pidfile := fmt .Sprintf ("file=%s" , vtpm .getPidFile ())
457467 logfile := fmt .Sprintf ("file=%s" , vtpm .getLogFile ())
@@ -481,6 +491,9 @@ func (vtpm *VTPM) startSwtpm() error {
481491 if err != nil {
482492 return err
483493 }
494+
495+ vtpm .resetAppArmor ()
496+
484497 return nil
485498}
486499
@@ -561,6 +574,8 @@ func (vtpm *VTPM) Stop(deleteStatePath bool) error {
561574
562575 vtpm .CloseServer ()
563576
577+ vtpm .teardownAppArmor ()
578+
564579 vtpm .Tpm_dev_num = VTPM_DEV_NUM_INVALID
565580
566581 if deleteStatePath {
@@ -609,5 +624,85 @@ func (vtpm *VTPM) CloseServer() error {
609624 os .NewFile (uintptr (vtpm .fd ), "[vtpm]" ).Close ()
610625 vtpm .fd = ILLEGAL_FD
611626 }
627+
628+ return nil
629+ }
630+
631+ // setupAppArmor creates an apparmor profile for swtpm if AppArmor is enabled and
632+ // compiles it using apparmor_parser -r <filename> and activates it for the next
633+ // exec.
634+ func (vtpm * VTPM ) setupAppArmor () error {
635+ var statefilepattern string
636+
637+ if ! apparmor .IsEnabled () {
638+ return nil
639+ }
640+
641+ profilename := fmt .Sprintf ("runc_%d_swtpm_tpm%d" , os .Getpid (), vtpm .GetTPMDevNum ())
642+ if vtpm .Vtpmversion == VTPM_VERSION_1_2 {
643+ statefilepattern = path .Join (vtpm .StatePath , "tpm-00.*" )
644+ } else {
645+ statefilepattern = path .Join (vtpm .StatePath , "tpm2-00.*" )
646+ }
647+
648+ profile := fmt .Sprintf ("\n #include <tunables/global>\n " +
649+ "profile %s {\n " +
650+ " #include <abstractions/base>\n " +
651+ " capability setgid,\n " +
652+ " capability setuid,\n " +
653+ " /dev/tpm[0-9]* rw,\n " +
654+ " owner /etc/group r,\n " +
655+ " owner /etc/nsswitch.conf r,\n " +
656+ " owner /etc/passwd r,\n " +
657+ " %s/.lock wk,\n " +
658+ " %s w,\n " +
659+ " %s rw,\n " +
660+ " %s rw,\n " +
661+ "}\n " ,
662+ profilename ,
663+ vtpm .StatePath ,
664+ vtpm .getLogFile (),
665+ vtpm .getPidFile (),
666+ statefilepattern )
667+
668+ vtpm .aaprofile = path .Join (vtpm .StatePath , "swtpm.apparmor" )
669+
670+ err := ioutil .WriteFile (vtpm .aaprofile , []byte (profile ), 0600 )
671+ if err != nil {
672+ return err
673+ }
674+ defer func () {
675+ if err != nil {
676+ vtpm .teardownAppArmor ()
677+ }
678+ }()
679+
680+ cmd := exec .Command ("/sbin/apparmor_parser" , "-r" , vtpm .aaprofile )
681+ output , err := cmd .CombinedOutput ()
682+ if err != nil {
683+ return fmt .Errorf ("apparmor_parser -r failed: %s" , string (output ))
684+ }
685+
686+ err = apparmor .ApplyProfileThread (profilename )
687+ if err != nil {
688+ return err
689+ }
690+
612691 return nil
613692}
693+
694+ func (vtpm * VTPM ) resetAppArmor () {
695+ apparmor .ApplyProfileThread ("unconfined" )
696+ }
697+
698+ // teardownAppArmor removes the AppArmor profile from the system and ensures
699+ // that the next time the process exec's no swtpm related profile is applied
700+ func (vtpm * VTPM ) teardownAppArmor () {
701+ vtpm .resetAppArmor ()
702+ if len (vtpm .aaprofile ) > 0 {
703+ cmd := exec .Command ("/sbin/apparmor_parser" , "-R" , vtpm .aaprofile )
704+ cmd .Run ()
705+ os .Remove (vtpm .aaprofile )
706+ vtpm .aaprofile = ""
707+ }
708+ }
0 commit comments