Files
Kir Kolyshkin 2ae07a45d6 libct/apparmor: simplify isEnabled
1. Use sync.OnceValue.

2. Fix the len(buf) check -- we only need 1 byte. Real kernel output
   is "Y\n" so practically this change is a no-op.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-05-15 17:14:15 -07:00

62 lines
1.5 KiB
Go

package apparmor
import (
"errors"
"fmt"
"os"
"sync"
"golang.org/x/sys/unix"
"github.com/opencontainers/runc/internal/pathrs"
)
// isEnabled returns true if apparmor is enabled for the host.
var isEnabled = sync.OnceValue(func() bool {
if _, err := os.Stat("/sys/kernel/security/apparmor"); err != nil {
return false
}
buf, err := os.ReadFile("/sys/module/apparmor/parameters/enabled")
return err == nil && len(buf) > 0 && buf[0] == 'Y'
})
func setProcAttr(attr, value string) error {
attr = pathrs.LexicallyCleanPath(attr)
attrSubPath := "attr/apparmor/" + attr
if _, err := os.Stat("/proc/self/" + attrSubPath); errors.Is(err, os.ErrNotExist) {
// fall back to the old convention
attrSubPath = "attr/" + attr
}
// Under AppArmor you can only change your own attr, so there's no reason
// to not use /proc/thread-self/ (instead of /proc/<tid>/, like libapparmor
// does).
f, closer, err := pathrs.ProcThreadSelfOpen(attrSubPath, unix.O_WRONLY|unix.O_CLOEXEC)
if err != nil {
return err
}
defer closer()
defer f.Close()
_, err = f.WriteString(value)
return err
}
// changeOnExec reimplements aa_change_onexec from libapparmor in Go.
func changeOnExec(name string) error {
if err := setProcAttr("exec", "exec "+name); err != nil {
return fmt.Errorf("apparmor failed to apply profile: %w", err)
}
return nil
}
// applyProfile will apply the profile with the specified name to the process
// after the next exec.
func applyProfile(name string) error {
if name == "" {
return nil
}
return changeOnExec(name)
}