feat(aa): add implementation of the new rule methods.

This commit is contained in:
Alexandre Pujol 2024-06-29 22:27:39 +01:00
parent 8b24f3521d
commit 0e0f87611a
No known key found for this signature in database
GPG Key ID: C5469996F0DF68EC
19 changed files with 380 additions and 2 deletions

View File

@ -39,5 +39,11 @@ func (r *All) Compare(other Rule) int {
func (r *All) Merge(other Rule) bool {
o, _ := other.(*All)
b := &r.Base
return b.merge(o.Base)
return b.merge(o.Base) // Always merge all rules
}
func (r *All) Lengths() []int {
return []int{} // No len for all
}
func (r *All) setPaddings(max []int) {} // No paddings for all

View File

@ -39,3 +39,9 @@ func (r *Hat) Compare(other Rule) int {
func (r *Hat) Merge(other Rule) bool {
return false // Never merge hat blocks
}
func (r *Hat) Lengths() []int {
return []int{} // No len for hat
}
func (r *Hat) setPaddings(max []int) {} // No paddings for hat

View File

@ -81,3 +81,17 @@ func (r *Capability) Compare(other Rule) int {
func (r *Capability) Merge(other Rule) bool {
return false // Never merge capabilities
}
func (r *Capability) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("", r.Names),
}
}
func (r *Capability) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{""}, []any{r.Names})...,
)
}

View File

@ -103,3 +103,20 @@ func (r *ChangeProfile) Compare(other Rule) int {
func (r *ChangeProfile) Merge(other Rule) bool {
return false // Never merge change_profile
}
func (r *ChangeProfile) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("", r.ExecMode),
length("", r.Exec),
length("", r.ProfileName),
}
}
func (r *ChangeProfile) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"", "", ""},
[]any{r.ExecMode, r.Exec, r.ProfileName})...,
)
}

View File

@ -137,3 +137,9 @@ func (r *Dbus) Merge(other Rule) bool {
}
return false
}
func (r *Dbus) Lengths() []int {
return []int{} // No len for dbus
}
func (r *Dbus) setPaddings(max []int) {} // No paddings for dbus

View File

@ -8,6 +8,8 @@ import (
"fmt"
"slices"
"strings"
"github.com/roddhjav/apparmor.d/pkg/util"
)
const (
@ -156,6 +158,42 @@ func (r *File) Merge(other Rule) bool {
return false
}
func (r *File) Lengths() []int {
// Add padding to align with other transition rule
lenPath := 0
isTransition := util.Intersect(
append(requirements[FILE]["transition"], "m"), r.Access,
)
if len(isTransition) > 0 {
lenPath = length("", r.Path)
}
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("owner", r.Owner),
lenPath,
}
}
func (r *File) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"owner", ""},
[]any{r.Owner, r.Path})...,
)
}
func (r *File) addLine(other Rule) bool {
if other.Kind() != r.Kind() {
return false
}
letterI := getLetterIn(fileAlphabet, r.Path)
letterJ := getLetterIn(fileAlphabet, other.(*File).Path)
groupI, ok1 := fileAlphabetGroups[letterI]
groupJ, ok2 := fileAlphabetGroups[letterJ]
return letterI != letterJ && !(ok1 && ok2 && groupI == groupJ)
}
type Link struct {
Base
Qualifier

View File

@ -88,3 +88,19 @@ func (r *IOUring) Merge(other Rule) bool {
}
return false
}
func (r *IOUring) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("", r.Access),
length("label=", r.Label),
}
}
func (r *IOUring) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"", "label="},
[]any{r.Access, r.Label})...,
)
}

View File

@ -73,6 +73,21 @@ func (m *MountConditions) Merge(other MountConditions) bool {
return false
}
func (m MountConditions) getLenFsType() int {
return length("fstype=", m.FsType)
}
func (m MountConditions) getLenOptions() int {
return length("options=", m.Options)
}
func (m MountConditions) setPaddings(max []int) []string {
return setPaddings(max,
[]string{"fstype=", "options="},
[]any{m.FsType, m.Options},
)
}
type Mount struct {
Base
Qualifier
@ -168,6 +183,24 @@ func (r *Mount) Merge(other Rule) bool {
return false
}
func (r *Mount) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
r.MountConditions.getLenFsType(),
r.MountConditions.getLenOptions(),
length("", r.Source),
length("", r.MountPoint),
}
}
func (r *Mount) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), r.MountConditions.setPaddings(max[2:4])...)
r.Paddings = append(r.Paddings,
setPaddings(max[4:], []string{"", ""}, []any{r.Source, r.MountPoint})...,
)
}
type Umount struct {
Base
Qualifier
@ -246,6 +279,23 @@ func (r *Umount) Merge(other Rule) bool {
return false
}
func (r *Umount) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
r.MountConditions.getLenFsType(),
r.MountConditions.getLenOptions(),
length("", r.MountPoint),
}
}
func (r *Umount) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), r.MountConditions.setPaddings(max[2:4])...)
r.Paddings = append(r.Paddings,
setPaddings(max[4:], []string{""}, []any{r.MountPoint})...,
)
}
type Remount struct {
Base
Qualifier
@ -324,3 +374,20 @@ func (r *Remount) Merge(other Rule) bool {
}
return false
}
func (r *Remount) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
r.MountConditions.getLenFsType(),
r.MountConditions.getLenOptions(),
length("", r.MountPoint),
}
}
func (r *Remount) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), r.MountConditions.setPaddings(max[2:4])...)
r.Paddings = append(r.Paddings,
setPaddings(max[4:], []string{""}, []any{r.MountPoint})...,
)
}

View File

@ -122,3 +122,21 @@ func (r *Mqueue) Merge(other Rule) bool {
}
return false
}
func (r *Mqueue) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("", r.Access),
length("type=", r.Type),
length("label=", r.Label),
length("", r.Name),
}
}
func (r *Mqueue) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"", "type=", "label=", ""},
[]any{r.Access, r.Type, r.Label, r.Name})...,
)
}

View File

@ -144,3 +144,20 @@ func (r *Network) Compare(other Rule) int {
func (r *Network) Merge(other Rule) bool {
return false // Never merge network
}
func (r *Network) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("", r.Domain),
length("", r.Type),
length("", r.Protocol),
}
}
func (r *Network) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"", "", ""},
[]any{r.Domain, r.Type, r.Protocol})...,
)
}

View File

@ -83,3 +83,20 @@ func (r *PivotRoot) Compare(other Rule) int {
func (r *PivotRoot) Merge(other Rule) bool {
return false // Never merge pivot root
}
func (r *PivotRoot) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("oldroot=", r.OldRoot),
length("", r.NewRoot),
length("", r.TargetProfile),
}
}
func (r *PivotRoot) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"oldroot=", "", ""},
[]any{r.OldRoot, r.NewRoot, r.TargetProfile})...,
)
}

View File

@ -53,6 +53,12 @@ func (r *Comment) Merge(other Rule) bool {
return false // Never merge comments
}
func (r *Comment) Lengths() []int {
return []int{} // No len for comments
}
func (r *Comment) setPaddings(max []int) {} // No paddings for comments
type Abi struct {
Base
Path string
@ -109,6 +115,12 @@ func (r *Abi) Merge(other Rule) bool {
return false // Never merge abi
}
func (r *Abi) Lengths() []int {
return []int{} // No len for abi
}
func (r *Abi) setPaddings(max []int) {} // No paddings for abi
type Alias struct {
Base
Path string
@ -157,6 +169,12 @@ func (r *Alias) Merge(other Rule) bool {
return false // Never merge alias
}
func (r *Alias) Lengths() []int {
return []int{} // No len for alias
}
func (r *Alias) setPaddings(max []int) {} // No paddings for alias
type Include struct {
Base
IfExists bool
@ -234,6 +252,12 @@ func (r *Include) Merge(other Rule) bool {
return false // Never merge include
}
func (r *Include) Lengths() []int {
return []int{} // No len for include
}
func (r *Include) setPaddings(max []int) {} // No paddings for include
type Variable struct {
Base
Name string
@ -305,3 +329,9 @@ func (r *Variable) Merge(other Rule) bool {
}
return false
}
func (r *Variable) Lengths() []int {
return []int{} // No len for variable
}
func (r *Variable) setPaddings(max []int) {} // No paddings for variable

View File

@ -103,6 +103,12 @@ func (p *Profile) Merge(other Rule) bool {
return false
}
func (r *Profile) Lengths() []int {
return []int{} // No len for profile
}
func (r *Profile) setPaddings(max []int) {} // No paddings for profile
func (p *Profile) Sort() {
p.Rules = p.Rules.Sort()
}

View File

@ -90,3 +90,19 @@ func (r *Ptrace) Merge(other Rule) bool {
}
return false
}
func (r *Ptrace) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("", r.Access),
length("peer=", r.Peer),
}
}
func (r *Ptrace) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"", "peer="},
[]any{r.Access, r.Peer})...,
)
}

View File

@ -84,3 +84,18 @@ func (r *Rlimit) Compare(other Rule) int {
func (r *Rlimit) Merge(other Rule) bool {
return false // Never merge rlimit
}
func (r *Rlimit) Lengths() []int {
return []int{
length("", r.Key),
length("", r.Op),
length("", r.Value),
}
}
func (r *Rlimit) setPaddings(max []int) {
r.Paddings = setPaddings(
max, []string{"", "", ""},
[]any{r.Key, r.Op, r.Value},
)
}

View File

@ -121,3 +121,20 @@ func (r *Signal) Merge(other Rule) bool {
}
return false
}
func (r *Signal) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("", r.Access),
length("set=", r.Set),
length("peer=", r.Peer),
}
}
func (r *Signal) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"", "set=", "peer="},
[]any{r.Access, r.Set, r.Peer})...,
)
}

View File

@ -136,3 +136,22 @@ func (r *Unix) Merge(other Rule) bool {
}
return false
}
func (r *Unix) Lengths() []int {
return []int{
r.Qualifier.getLenAudit(),
r.Qualifier.getLenAccess(),
length("", r.Access),
length("type=", r.Type),
length("protocol=", r.Protocol),
length("addr=", r.Address),
length("label=", r.Label),
}
}
func (r *Unix) setPaddings(max []int) {
r.Paddings = append(r.Qualifier.setPaddings(max[:2]), setPaddings(
max[2:], []string{"", "type=", "protocol=", "addr=", "label="},
[]any{r.Access, r.Type, r.Protocol, r.Address, r.Label})...,
)
}

View File

@ -69,5 +69,11 @@ func (r *Userns) Compare(other Rule) int {
func (r *Userns) Merge(other Rule) bool {
o, _ := other.(*Userns)
b := &r.Base
return b.merge(o.Base)
return b.merge(o.Base) // Always merge userns rules
}
func (r *Userns) Lengths() []int {
return []int{} // No len for userns
}
func (r *Userns) setPaddings(max []int) {} // No paddings for userns

View File

@ -43,6 +43,53 @@ func merge(kind Kind, key string, a, b []string) []string {
return slices.Compact(a)
}
func length(prefix string, value any) int {
var res int
switch value := value.(type) {
case bool:
if value {
return len(prefix) + 1
}
return 0
case string:
if value != "" {
res = len(value) + len(prefix) + 1
}
return res
case []string:
for _, v := range value {
lenV := len(v)
if lenV > 0 {
res += lenV + 1 // Space between values
}
}
if len(value) > 1 {
res += 2 // Brackets on slices
}
return res
default:
panic("length: unsupported type")
}
}
func setPaddings(max []int, prefixes []string, values []any) []string {
if len(max) != len(values) || len(max) != len(prefixes) {
panic("setPaddings: max, prefix, and values must have the same length")
}
res := make([]string, len(max))
for i, v := range values {
if max[i] == 0 {
res[i] = ""
continue
}
count := max[i] - length(prefixes[i], v)
if count > 0 {
res[i] = strings.Repeat(" ", count)
}
}
return res
}
func compare(a, b any) int {
switch a := a.(type) {
case int: