feat(aa): improve rule creation from log.

This commit is contained in:
Alexandre Pujol 2023-09-29 20:07:29 +01:00
parent 13de4182c8
commit c7485326e8
No known key found for this signature in database
GPG key ID: C5469996F0DF68EC
15 changed files with 62 additions and 57 deletions

View file

@ -9,9 +9,9 @@ type Capability struct {
Name string Name string
} }
func CapabilityFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func CapabilityFromLog(log map[string]string) ApparmorRule {
return &Capability{ return &Capability{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
Name: log["capname"], Name: log["capname"],
} }
} }

View file

@ -10,7 +10,7 @@ type ChangeProfile struct {
ProfileName string ProfileName string
} }
func ChangeProfileFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func ChangeProfileFromLog(log map[string]string) ApparmorRule {
return &ChangeProfile{ return &ChangeProfile{
ExecMode: log["mode"], ExecMode: log["mode"],
Exec: log["exec"], Exec: log["exec"],

View file

@ -15,9 +15,9 @@ type Dbus struct {
Label string Label string
} }
func DbusFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func DbusFromLog(log map[string]string) ApparmorRule {
return &Dbus{ return &Dbus{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
Access: log["mask"], Access: log["mask"],
Bus: log["bus"], Bus: log["bus"],
Name: log["name"], Name: log["name"],

View file

@ -11,13 +11,9 @@ type File struct {
Target string Target string
} }
func FileFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func FileFromLog(log map[string]string) ApparmorRule {
owner := false
if log["fsuid"] == log["ouid"] && log["OUID"] != "root" {
owner = true
}
return &File{ return &File{
Qualifier: NewQualifier(owner, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
Path: log["name"], Path: log["name"],
Access: maskToAccess[log["requested_mask"]], Access: maskToAccess[log["requested_mask"]],
Target: log["target"], Target: log["target"],

View file

@ -38,9 +38,9 @@ type Mount struct {
MountPoint string MountPoint string
} }
func MountFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func MountFromLog(log map[string]string) ApparmorRule {
return &Mount{ return &Mount{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
MountConditions: MountConditions{ MountConditions: MountConditions{
Fs: "", Fs: "",
Op: "", Op: "",
@ -79,9 +79,9 @@ type Umount struct {
MountPoint string MountPoint string
} }
func UmountFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func UmountFromLog(log map[string]string) ApparmorRule {
return &Umount{ return &Umount{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
MountConditions: MountConditions{ MountConditions: MountConditions{
Fs: "", Fs: "",
Op: "", Op: "",
@ -116,9 +116,9 @@ type Remount struct {
MountPoint string MountPoint string
} }
func RemountFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func RemountFromLog(log map[string]string) ApparmorRule {
return &Remount{ return &Remount{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
MountConditions: MountConditions{ MountConditions: MountConditions{
Fs: "", Fs: "",
Op: "", Op: "",

View file

@ -11,9 +11,9 @@ type Mqueue struct {
Label string Label string
} }
func MqueueFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func MqueueFromLog(log map[string]string) ApparmorRule {
return &Mqueue{ return &Mqueue{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
Access: maskToAccess[log["requested_mask"]], Access: maskToAccess[log["requested_mask"]],
Type: log["type"], Type: log["type"],
Label: log["label"], Label: log["label"],

View file

@ -33,9 +33,9 @@ type Network struct {
AddressExpr AddressExpr
} }
func NetworkFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func NetworkFromLog(log map[string]string) ApparmorRule {
return &Network{ return &Network{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
AddressExpr: AddressExpr{ AddressExpr: AddressExpr{
Source: log["laddr"], Source: log["laddr"],
Destination: log["faddr"], Destination: log["faddr"],

View file

@ -11,9 +11,9 @@ type PivotRoot struct {
TargetProfile string TargetProfile string
} }
func PivotRootFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func PivotRootFromLog(log map[string]string) ApparmorRule {
return &PivotRoot{ return &PivotRoot{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
OldRoot: log["oldroot"], OldRoot: log["oldroot"],
NewRoot: log["root"], NewRoot: log["root"],
TargetProfile: log["name"], TargetProfile: log["name"],

View file

@ -66,15 +66,7 @@ func (p *AppArmorProfile) String() string {
// AddRule adds a new rule to the profile from a log map // AddRule adds a new rule to the profile from a log map
func (p *AppArmorProfile) AddRule(log map[string]string) { func (p *AppArmorProfile) AddRule(log map[string]string) {
noNewPrivs := false
fileInherit := false
if log["operation"] == "file_inherit" {
fileInherit = true
}
switch log["error"] { switch log["error"] {
case "-1":
noNewPrivs = true
case "-2": case "-2":
if !slices.Contains(p.Flags, "mediate_deleted") { if !slices.Contains(p.Flags, "mediate_deleted") {
p.Flags = append(p.Flags, "mediate_deleted") p.Flags = append(p.Flags, "mediate_deleted")
@ -90,36 +82,36 @@ func (p *AppArmorProfile) AddRule(log map[string]string) {
switch log["class"] { switch log["class"] {
case "cap": case "cap":
p.Rules = append(p.Rules, CapabilityFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, CapabilityFromLog(log))
case "net": case "net":
p.Rules = append(p.Rules, NetworkFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, NetworkFromLog(log))
case "mount": case "mount":
p.Rules = append(p.Rules, MountFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, MountFromLog(log))
case "remount": case "remount":
p.Rules = append(p.Rules, RemountFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, RemountFromLog(log))
case "umount": case "umount":
p.Rules = append(p.Rules, UmountFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, UmountFromLog(log))
case "pivot_root": case "pivot_root":
p.Rules = append(p.Rules, PivotRootFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, PivotRootFromLog(log))
case "change_profile": case "change_profile":
p.Rules = append(p.Rules, RemountFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, RemountFromLog(log))
case "mqueue": case "mqueue":
p.Rules = append(p.Rules, MqueueFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, MqueueFromLog(log))
case "signal": case "signal":
p.Rules = append(p.Rules, SignalFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, SignalFromLog(log))
case "ptrace": case "ptrace":
p.Rules = append(p.Rules, PtraceFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, PtraceFromLog(log))
case "namespace": case "namespace":
p.Rules = append(p.Rules, UsernsFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, UsernsFromLog(log))
case "unix": case "unix":
p.Rules = append(p.Rules, UnixFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, UnixFromLog(log))
case "file": case "file":
p.Rules = append(p.Rules, FileFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, FileFromLog(log))
default: default:
if strings.Contains(log["operation"], "dbus") { if strings.Contains(log["operation"], "dbus") {
p.Rules = append(p.Rules, DbusFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, DbusFromLog(log))
} else if log["family"] == "unix" { } else if log["family"] == "unix" {
p.Rules = append(p.Rules, UnixFromLog(log, noNewPrivs, fileInherit)) p.Rules = append(p.Rules, UnixFromLog(log))
} }
} }
} }

View file

@ -10,9 +10,9 @@ type Ptrace struct {
Peer string Peer string
} }
func PtraceFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func PtraceFromLog(log map[string]string) ApparmorRule {
return &Ptrace{ return &Ptrace{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
Access: maskToAccess[log["requested_mask"]], Access: maskToAccess[log["requested_mask"]],
Peer: log["peer"], Peer: log["peer"],
} }

View file

@ -13,7 +13,24 @@ type Qualifier struct {
FileInherit bool FileInherit bool
} }
func NewQualifier(owner, noNewPrivs, fileInherit bool) Qualifier { 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
}
fileInherit := false
if log["operation"] == "file_inherit" {
fileInherit = true
}
noNewPrivs := false
if log["error"] == "-1" {
noNewPrivs = true
}
return Qualifier{ return Qualifier{
Audit: false, Audit: false,
AccessType: "", AccessType: "",

View file

@ -12,7 +12,7 @@ import (
func TestRule_FromLog(t *testing.T) { func TestRule_FromLog(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
fromLog func(map[string]string, bool, bool) ApparmorRule fromLog func(map[string]string) ApparmorRule
log map[string]string log map[string]string
want ApparmorRule want ApparmorRule
}{ }{
@ -73,7 +73,7 @@ func TestRule_FromLog(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := tt.fromLog(tt.log, false, false); !reflect.DeepEqual(got, tt.want) { if got := tt.fromLog(tt.log); !reflect.DeepEqual(got, tt.want) {
t.Errorf("RuleFromLog() = %v, want %v", got, tt.want) t.Errorf("RuleFromLog() = %v, want %v", got, tt.want)
} }
}) })

View file

@ -11,9 +11,9 @@ type Signal struct {
Peer string Peer string
} }
func SignalFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func SignalFromLog(log map[string]string) ApparmorRule {
return &Signal{ return &Signal{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
Access: maskToAccess[log["requested_mask"]], Access: maskToAccess[log["requested_mask"]],
Set: log["signal"], Set: log["signal"],
Peer: log["peer"], Peer: log["peer"],

View file

@ -17,9 +17,9 @@ type Unix struct {
PeerAddr string PeerAddr string
} }
func UnixFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func UnixFromLog(log map[string]string) ApparmorRule {
return &Unix{ return &Unix{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
Access: maskToAccess[log["requested_mask"]], Access: maskToAccess[log["requested_mask"]],
Type: log["sock_type"], Type: log["sock_type"],
Protocol: log["protocol"], Protocol: log["protocol"],

View file

@ -9,9 +9,9 @@ type Userns struct {
Create bool Create bool
} }
func UsernsFromLog(log map[string]string, noNewPrivs, fileInherit bool) ApparmorRule { func UsernsFromLog(log map[string]string) ApparmorRule {
return &Userns{ return &Userns{
Qualifier: NewQualifier(false, noNewPrivs, fileInherit), Qualifier: NewQualifierFromLog(log),
Create: true, Create: true,
} }
} }