2023-09-25 01:22:41 +02:00
|
|
|
// apparmor.d - Full set of apparmor profiles
|
2024-02-07 00:16:21 +01:00
|
|
|
// Copyright (C) 2021-2024 Alexandre Pujol <alexandre@pujol.io>
|
2023-09-25 01:22:41 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
|
|
|
|
package aa
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2024-05-05 00:45:36 +02:00
|
|
|
func TestRules_FromLog(t *testing.T) {
|
2024-05-29 22:17:21 +02:00
|
|
|
for _, tt := range testRule {
|
|
|
|
if tt.fromLog == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
if got := tt.fromLog(tt.log); !reflect.DeepEqual(got, tt.rule) {
|
|
|
|
t.Errorf("RuleFromLog() = %v, want %v", got, tt.rule)
|
|
|
|
}
|
|
|
|
})
|
2023-09-25 01:22:41 +02:00
|
|
|
}
|
2024-05-29 22:17:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestRules_Validate(t *testing.T) {
|
|
|
|
for _, tt := range testRule {
|
2023-09-25 01:22:41 +02:00
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2024-05-29 22:17:21 +02:00
|
|
|
if err := tt.rule.Validate(); (err != nil) != tt.wValidErr {
|
|
|
|
t.Errorf("Rules.Validate() error = %v, wantErr %v", err, tt.wValidErr)
|
2023-09-25 01:22:41 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-05 00:45:36 +02:00
|
|
|
func TestRules_Less(t *testing.T) {
|
2024-05-29 22:17:21 +02:00
|
|
|
for _, tt := range testRule {
|
|
|
|
if tt.oLess == nil {
|
|
|
|
continue
|
|
|
|
}
|
2023-09-25 01:22:41 +02:00
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2024-05-29 22:17:21 +02:00
|
|
|
if got := tt.rule.Less(tt.oLess); got != tt.wLessErr {
|
|
|
|
t.Errorf("Rule.Less() = %v, want %v", got, tt.wLessErr)
|
2023-09-25 01:22:41 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-05 00:45:36 +02:00
|
|
|
func TestRules_Equals(t *testing.T) {
|
2024-05-29 22:17:21 +02:00
|
|
|
for _, tt := range testRule {
|
|
|
|
if tt.oEqual == nil {
|
|
|
|
continue
|
|
|
|
}
|
2023-09-25 01:22:41 +02:00
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
r := tt.rule
|
2024-05-29 22:17:21 +02:00
|
|
|
if got := r.Equals(tt.oEqual); got != tt.wEqualErr {
|
|
|
|
t.Errorf("Rule.Equals() = %v, want %v", got, tt.wEqualErr)
|
2023-09-25 01:22:41 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2024-04-23 22:26:09 +02:00
|
|
|
|
2024-05-05 00:45:36 +02:00
|
|
|
func TestRules_String(t *testing.T) {
|
2024-05-29 22:17:21 +02:00
|
|
|
for _, tt := range testRule {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
if got := tt.rule.String(); got != tt.wString {
|
|
|
|
t.Errorf("Rule.String() = %v, want %v", got, tt.wString)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
// Test cases for the Rule interface
|
|
|
|
testRule = []struct {
|
|
|
|
name string
|
|
|
|
fromLog func(map[string]string) Rule
|
|
|
|
log map[string]string
|
|
|
|
rule Rule
|
|
|
|
wValidErr bool
|
|
|
|
oLess Rule
|
|
|
|
wLessErr bool
|
|
|
|
oEqual Rule
|
|
|
|
wEqualErr bool
|
|
|
|
wString string
|
2024-04-23 22:26:09 +02:00
|
|
|
}{
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "comment",
|
|
|
|
rule: comment1,
|
|
|
|
oLess: comment2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: comment2,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "#comment",
|
2024-05-28 19:23:37 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "abi",
|
|
|
|
rule: abi1,
|
|
|
|
oLess: abi2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: abi1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "abi <abi/4.0>,",
|
2024-05-28 19:23:37 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "alias",
|
|
|
|
rule: alias1,
|
|
|
|
oLess: alias2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: alias2,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "alias /mnt/usr -> /usr,",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "include1",
|
|
|
|
rule: include1,
|
|
|
|
oLess: includeLocal1,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: includeLocal1,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "include <abstraction/base>",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "include2",
|
|
|
|
rule: include1,
|
|
|
|
oLess: include2,
|
|
|
|
wLessErr: false,
|
|
|
|
wString: "include <abstraction/base>",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
2024-05-28 19:23:37 +02:00
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "include-local",
|
|
|
|
rule: includeLocal1,
|
|
|
|
oLess: include1,
|
|
|
|
wLessErr: true,
|
|
|
|
wString: "include if exists <local/foo>",
|
2024-05-28 19:23:37 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "include/abs",
|
|
|
|
rule: &Include{Path: "/usr/share/apparmor.d/", IsMagic: false},
|
|
|
|
wString: `include "/usr/share/apparmor.d/"`,
|
2024-05-28 19:23:37 +02:00
|
|
|
},
|
2024-04-23 22:26:09 +02:00
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "variable",
|
|
|
|
rule: variable1,
|
|
|
|
oLess: variable2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: variable1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "@{bin} = /{,usr/}{,s}bin",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
2024-05-28 19:23:37 +02:00
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "all",
|
|
|
|
rule: all1,
|
|
|
|
oLess: all2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: all2,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "all,",
|
2024-05-28 19:23:37 +02:00
|
|
|
},
|
2024-04-23 22:26:09 +02:00
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "rlimit",
|
|
|
|
rule: rlimit1,
|
|
|
|
oLess: rlimit2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: rlimit1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "set rlimit nproc <= 200,",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "rlimit2",
|
|
|
|
rule: rlimit2,
|
|
|
|
oLess: rlimit2,
|
|
|
|
wLessErr: false,
|
|
|
|
wString: "set rlimit cpu <= 2,",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "rlimit3",
|
|
|
|
rule: rlimit3,
|
|
|
|
oLess: rlimit1,
|
|
|
|
wLessErr: true,
|
|
|
|
|
|
|
|
wString: "set rlimit nproc < 2,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "userns",
|
|
|
|
rule: userns1,
|
|
|
|
oLess: userns2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: userns1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "userns,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "capbability",
|
|
|
|
fromLog: newCapabilityFromLog,
|
|
|
|
log: capability1Log,
|
|
|
|
rule: capability1,
|
|
|
|
oLess: capability2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: capability1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "capability net_admin,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "capability/multi",
|
|
|
|
rule: &Capability{Names: []string{"dac_override", "dac_read_search"}},
|
|
|
|
wString: "capability dac_override dac_read_search,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "capability/all",
|
|
|
|
rule: &Capability{},
|
|
|
|
wString: "capability,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "network",
|
|
|
|
fromLog: newNetworkFromLog,
|
|
|
|
log: network1Log,
|
|
|
|
rule: network1,
|
|
|
|
wValidErr: true,
|
|
|
|
oLess: network2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: network1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "network netlink raw,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "mount",
|
|
|
|
fromLog: newMountFromLog,
|
|
|
|
log: mount1Log,
|
|
|
|
rule: mount1,
|
|
|
|
oEqual: mount2,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "mount fstype=overlay overlay -> /var/lib/docker/overlay2/opaque-bug-check1209538631/merged/, # failed perms check",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "remount",
|
|
|
|
rule: remount1,
|
|
|
|
oLess: remount2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: remount1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "remount /,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "umount",
|
|
|
|
fromLog: newUmountFromLog,
|
|
|
|
log: umount1Log,
|
|
|
|
rule: umount1,
|
|
|
|
oLess: umount2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: umount1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "umount /,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "pivot_root1",
|
|
|
|
fromLog: newPivotRootFromLog,
|
|
|
|
log: pivotroot1Log,
|
|
|
|
rule: pivotroot1,
|
|
|
|
oLess: pivotroot2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: pivotroot2,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "pivot_root oldroot=@{run}/systemd/mount-rootfs/ @{run}/systemd/mount-rootfs/,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "pivot_root2",
|
|
|
|
rule: pivotroot1,
|
|
|
|
oLess: pivotroot3,
|
|
|
|
wLessErr: false,
|
|
|
|
wString: "pivot_root oldroot=@{run}/systemd/mount-rootfs/ @{run}/systemd/mount-rootfs/,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change_profile1",
|
|
|
|
fromLog: newChangeProfileFromLog,
|
|
|
|
log: changeprofile1Log,
|
|
|
|
rule: changeprofile1,
|
|
|
|
oLess: changeprofile2,
|
|
|
|
wLessErr: false,
|
|
|
|
wString: "change_profile -> systemd-user,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "change_profile2",
|
|
|
|
rule: changeprofile2,
|
|
|
|
oLess: changeprofile3,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: changeprofile1,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "change_profile -> brwap,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "mqueue",
|
|
|
|
rule: mqueue1,
|
|
|
|
oLess: mqueue2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: mqueue1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "mqueue r type=posix /,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "iouring",
|
|
|
|
rule: iouring1,
|
|
|
|
oLess: iouring2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: iouring2,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "io_uring sqpoll label=foo,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "signal",
|
|
|
|
fromLog: newSignalFromLog,
|
|
|
|
log: signal1Log,
|
|
|
|
rule: signal1,
|
|
|
|
oLess: signal2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: signal1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "signal receive set=kill peer=firefox//&firejail-default,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ptrace/xdg-document-portal",
|
|
|
|
fromLog: newPtraceFromLog,
|
|
|
|
log: ptrace1Log,
|
|
|
|
rule: ptrace1,
|
|
|
|
oLess: ptrace2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: ptrace1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "ptrace read peer=nautilus,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "ptrace/snap-update-ns.firefox",
|
|
|
|
fromLog: newPtraceFromLog,
|
|
|
|
log: ptrace2Log,
|
|
|
|
rule: ptrace2,
|
|
|
|
oLess: ptrace1,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: ptrace1,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "ptrace readby peer=systemd-journald,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "unix",
|
|
|
|
fromLog: newUnixFromLog,
|
|
|
|
log: unix1Log,
|
|
|
|
rule: unix1,
|
|
|
|
oLess: unix1,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: unix1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "unix (send receive) type=stream protocol=0 addr=none peer=(label=dbus-daemon, addr=@/tmp/dbus-AaKMpxzC4k),",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "dbus",
|
|
|
|
fromLog: newDbusFromLog,
|
|
|
|
log: dbus1Log,
|
|
|
|
rule: dbus1,
|
|
|
|
oLess: dbus1,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: dbus2,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "dbus receive bus=session path=/org/gtk/vfs/metadata\n interface=org.gtk.vfs.Metadata\n member=Remove\n peer=(name=:1.15, label=tracker-extract),",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "dbus2",
|
|
|
|
rule: dbus2,
|
|
|
|
oLess: dbus3,
|
|
|
|
wLessErr: false,
|
|
|
|
wString: "dbus bind bus=session name=org.gnome.evolution.dataserver.Sources5,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "dbus/bind",
|
|
|
|
rule: &Dbus{Access: []string{"bind"}, Bus: "session", Name: "org.gnome.*"},
|
|
|
|
wString: `dbus bind bus=session name=org.gnome.*,`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "dbus/full",
|
|
|
|
rule: &Dbus{Bus: "accessibility"},
|
|
|
|
wString: `dbus bus=accessibility,`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "file",
|
|
|
|
fromLog: newFileFromLog,
|
|
|
|
log: file1Log,
|
|
|
|
rule: file1,
|
|
|
|
oLess: file2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: file2,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "/usr/share/poppler/cMap/Identity-H r,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "file/empty",
|
|
|
|
rule: &File{},
|
|
|
|
oLess: &File{},
|
|
|
|
wLessErr: false,
|
|
|
|
wString: " ,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "file/equal",
|
|
|
|
rule: &File{Path: "/usr/share/poppler/cMap/Identity-H"},
|
|
|
|
oLess: &File{Path: "/usr/share/poppler/cMap/Identity-H"},
|
|
|
|
wLessErr: false,
|
|
|
|
wString: "/usr/share/poppler/cMap/Identity-H ,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "file/owner",
|
|
|
|
rule: &File{Path: "/usr/share/poppler/cMap/Identity-H", Owner: true},
|
|
|
|
oLess: &File{Path: "/usr/share/poppler/cMap/Identity-H"},
|
|
|
|
wLessErr: true,
|
|
|
|
wString: "owner /usr/share/poppler/cMap/Identity-H ,",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "file/access",
|
|
|
|
rule: &File{Path: "/usr/share/poppler/cMap/Identity-H", Access: []string{"r"}},
|
|
|
|
oLess: &File{Path: "/usr/share/poppler/cMap/Identity-H", Access: []string{"w"}},
|
|
|
|
wLessErr: false,
|
|
|
|
wString: "/usr/share/poppler/cMap/Identity-H r,",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "file/close",
|
|
|
|
rule: &File{Path: "/usr/share/poppler/cMap/"},
|
|
|
|
oLess: &File{Path: "/usr/share/poppler/cMap/Identity-H"},
|
|
|
|
wLessErr: true,
|
|
|
|
wString: "/usr/share/poppler/cMap/ ,",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "link",
|
|
|
|
fromLog: newLinkFromLog,
|
|
|
|
log: link1Log,
|
|
|
|
rule: link1,
|
|
|
|
oLess: link2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: link3,
|
|
|
|
wEqualErr: false,
|
|
|
|
wString: "link /tmp/mkinitcpio.QDWtza/early@{lib}/firmware/i915/dg1_dmc_ver2_02.bin.zst -> /tmp/mkinitcpio.QDWtza/root@{lib}/firmware/i915/dg1_dmc_ver2_02.bin.zst,",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "link",
|
|
|
|
fromLog: newFileFromLog,
|
|
|
|
log: link3Log,
|
|
|
|
rule: link3,
|
|
|
|
wString: "owner link @{user_config_dirs}/kiorc -> @{user_config_dirs}/#3954,",
|
2024-04-23 22:26:09 +02:00
|
|
|
},
|
2024-05-25 23:22:57 +02:00
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "profile",
|
|
|
|
rule: profile1,
|
|
|
|
oLess: profile2,
|
|
|
|
wLessErr: true,
|
|
|
|
oEqual: profile1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "profile sudo {\n}",
|
2024-05-25 23:22:57 +02:00
|
|
|
},
|
2024-05-28 19:23:37 +02:00
|
|
|
{
|
2024-05-29 22:17:21 +02:00
|
|
|
name: "hat",
|
|
|
|
rule: hat1,
|
|
|
|
oLess: hat2,
|
|
|
|
wLessErr: false,
|
|
|
|
oEqual: hat1,
|
|
|
|
wEqualErr: true,
|
|
|
|
wString: "hat user {\n}",
|
2024-05-28 19:23:37 +02:00
|
|
|
},
|
2024-04-23 22:26:09 +02:00
|
|
|
}
|
2024-05-29 22:17:21 +02:00
|
|
|
)
|