// apparmor.d - Full set of apparmor profiles // Copyright (C) 2021-2023 Alexandre Pujol // SPDX-License-Identifier: GPL-2.0-only package aa import ( "strings" ) type Rule struct { Comment string NoNewPrivs bool FileInherit bool } func (r *Rule) Less(other any) bool { return false } func (r *Rule) Equals(other any) bool { return false } // Qualifier to apply extra settings to a rule type Qualifier struct { Audit bool AccessType string Owner bool NoNewPrivs bool FileInherit bool Optional bool Comment string Prefix string Padding string } func NewQualifierFromLog(log map[string]string) Qualifier { owner := false fsuid, hasFsUID := log["fsuid"] ouid, hasOuUID := log["ouid"] OUID, hasOUID := log["OUID"] isDbus := strings.Contains(log["operation"], "dbus") if hasFsUID && hasOuUID && hasOUID && fsuid == ouid && OUID != "root" && !isDbus { owner = true } audit := false if log["apparmor"] == "AUDIT" { audit = true } fileInherit := false if log["operation"] == "file_inherit" { fileInherit = true } noNewPrivs := false optional := false msg := "" switch log["error"] { case "-1": if strings.Contains(log["info"], "optional:") { optional = true msg = strings.Replace(log["info"], "optional: ", "", 1) } else { noNewPrivs = true } case "-13": ignoreProfileInfo := []string{"namespace", "disconnected path"} for _, info := range ignoreProfileInfo { if strings.Contains(log["info"], info) { break } } msg = log["info"] default: } return Qualifier{ Audit: audit, Owner: owner, NoNewPrivs: noNewPrivs, FileInherit: fileInherit, Optional: optional, Comment: msg, } } func (r Qualifier) Less(other Qualifier) bool { if r.Owner == other.Owner { if r.Audit == other.Audit { return r.AccessType < other.AccessType } return r.Audit } return other.Owner } func (r Qualifier) Equals(other Qualifier) bool { return r.Audit == other.Audit && r.AccessType == other.AccessType && r.Owner == other.Owner && r.NoNewPrivs == other.NoNewPrivs && r.FileInherit == other.FileInherit } // Preamble specific rules type Abi struct { Path string IsMagic bool } func (r Abi) Less(other Abi) bool { if r.Path == other.Path { return r.IsMagic == other.IsMagic } return r.Path < other.Path } func (r Abi) Equals(other Abi) bool { return r.Path == other.Path && r.IsMagic == other.IsMagic } type Alias struct { Path string RewrittenPath string } func (r Alias) Less(other Alias) bool { if r.Path == other.Path { return r.RewrittenPath < other.RewrittenPath } return r.Path < other.Path } func (r Alias) Equals(other Alias) bool { return r.Path == other.Path && r.RewrittenPath == other.RewrittenPath }