apparmor.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. // +build apparmor,linux
  2. package apparmor
  3. import (
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. )
  8. // IsEnabled returns true if apparmor is enabled for the host.
  9. func IsEnabled() bool {
  10. if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil && os.Getenv("container") == "" {
  11. if _, err = os.Stat("/sbin/apparmor_parser"); err == nil {
  12. buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
  13. return err == nil && len(buf) > 1 && buf[0] == 'Y'
  14. }
  15. }
  16. return false
  17. }
  18. func setprocattr(attr, value string) error {
  19. // Under AppArmor you can only change your own attr, so use /proc/self/
  20. // instead of /proc/<tid>/ like libapparmor does
  21. path := fmt.Sprintf("/proc/self/attr/%s", attr)
  22. f, err := os.OpenFile(path, os.O_WRONLY, 0)
  23. if err != nil {
  24. return err
  25. }
  26. defer f.Close()
  27. _, err = fmt.Fprintf(f, "%s", value)
  28. return err
  29. }
  30. // changeOnExec reimplements aa_change_onexec from libapparmor in Go
  31. func changeOnExec(name string) error {
  32. value := "exec " + name
  33. if err := setprocattr("exec", value); err != nil {
  34. return fmt.Errorf("apparmor failed to apply profile: %s", err)
  35. }
  36. return nil
  37. }
  38. // ApplyProfile will apply the profile with the specified name to the process after
  39. // the next exec.
  40. func ApplyProfile(name string) error {
  41. if name == "" {
  42. return nil
  43. }
  44. return changeOnExec(name)
  45. }