build: improve the dbus directive.

- Support for additional interfaces: +=
- Restrict the generated dbus rules
- Add the required unix bind rule.
This commit is contained in:
Alexandre Pujol 2025-02-23 20:53:49 +01:00
parent 81ecce1ef7
commit 972ae950e4
Failed to generate hash of commit
3 changed files with 199 additions and 131 deletions

View file

@ -20,7 +20,7 @@ func TestNewOption(t *testing.T) {
}{ }{
{ {
name: "dbus", name: "dbus",
file: nil, file: paths.New("dbus"),
match: []string{ match: []string{
" #aa:dbus own bus=system name=org.gnome.DisplayManager", " #aa:dbus own bus=system name=org.gnome.DisplayManager",
"dbus", "dbus",
@ -34,13 +34,13 @@ func TestNewOption(t *testing.T) {
"own": "", "own": "",
}, },
ArgList: []string{"own", "bus=system", "name=org.gnome.DisplayManager"}, ArgList: []string{"own", "bus=system", "name=org.gnome.DisplayManager"},
File: nil, File: paths.New("dbus"),
Raw: " #aa:dbus own bus=system name=org.gnome.DisplayManager", Raw: " #aa:dbus own bus=system name=org.gnome.DisplayManager",
}, },
}, },
{ {
name: "only", name: "only",
file: nil, file: paths.New("only"),
match: []string{ match: []string{
" #aa:only opensuse", " #aa:only opensuse",
"only", "only",
@ -50,7 +50,7 @@ func TestNewOption(t *testing.T) {
Name: "only", Name: "only",
ArgMap: map[string]string{"opensuse": ""}, ArgMap: map[string]string{"opensuse": ""},
ArgList: []string{"opensuse"}, ArgList: []string{"opensuse"},
File: nil, File: paths.New("only"),
Raw: " #aa:only opensuse", Raw: " #aa:only opensuse",
}, },
}, },
@ -74,13 +74,13 @@ func TestRun(t *testing.T) {
}{ }{
{ {
name: "none", name: "none",
file: nil, file: paths.New("dummy"),
profile: ` `, profile: ` `,
want: ` `, want: ` `,
}, },
{ {
name: "present", name: "present",
file: nil, file: paths.New("fake-own"),
profile: ` #aa:dbus own bus=system name=org.freedesktop.systemd1`, profile: ` #aa:dbus own bus=system name=org.freedesktop.systemd1`,
want: dbusOwnSystemd1, want: dbusOwnSystemd1,
}, },

View file

@ -21,11 +21,6 @@ import (
"github.com/roddhjav/apparmor.d/pkg/prebuild" "github.com/roddhjav/apparmor.d/pkg/prebuild"
) )
var defaultInterfaces = []string{
"org.freedesktop.DBus.Properties",
"org.freedesktop.DBus.ObjectManager",
}
type Dbus struct { type Dbus struct {
prebuild.Base prebuild.Base
} }
@ -43,15 +38,6 @@ func init() {
) )
} }
func setInterfaces(rules map[string]string) []string {
interfaces := []string{rules["name"]}
if _, present := rules["interface"]; present {
interfaces = append(interfaces, rules["interface"])
}
interfaces = append(interfaces, defaultInterfaces...)
return interfaces
}
func (d Dbus) Apply(opt *Option, profile string) (string, error) { func (d Dbus) Apply(opt *Option, profile string) (string, error) {
var r aa.Rules var r aa.Rules
@ -59,11 +45,15 @@ func (d Dbus) Apply(opt *Option, profile string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
name := opt.File.Base()
if len(name) > 15 {
name = name[:15]
}
switch action { switch action {
case "own": case "own":
r = d.own(opt.ArgMap) r = d.own(opt.ArgMap, name)
case "talk": case "talk":
r = d.talk(opt.ArgMap) r = d.talk(opt.ArgMap, name)
} }
aa.IndentationLevel = strings.Count( aa.IndentationLevel = strings.Count(
@ -103,63 +93,132 @@ func (d Dbus) sanityCheck(opt *Option) (string, error) {
return action, nil return action, nil
} }
func (d Dbus) own(rules map[string]string) aa.Rules { func getInterfaces(rules map[string]string) []string {
interfaces := setInterfaces(rules) var interfaces []string
res := aa.Rules{} if _, present := rules["interface"]; present {
res = append(res, &aa.Dbus{ interfaces = []string{rules["interface"]}
} else {
interfaces = []string{rules["name"]}
}
if _, present := rules["interface+"]; present {
interfaces = append(interfaces, rules["interface+"])
}
return interfaces
}
func (d Dbus) own(rules map[string]string, name string) aa.Rules {
interfaces := getInterfaces(rules)
res := aa.Rules{
&aa.Unix{
Access: []string{"bind"}, Type: "stream",
Address: `@@{udbus}/bus/` + name + `/` + rules["bus"],
},
&aa.Dbus{
Access: []string{"bind"}, Bus: rules["bus"], Name: rules["name"], Access: []string{"bind"}, Bus: rules["bus"], Name: rules["name"],
}) },
for _, iface := range interfaces {
res = append(res, &aa.Dbus{
Access: []string{"receive"},
Bus: rules["bus"],
Path: rules["path"],
Interface: iface,
PeerName: `":1.@{int}"`,
})
} }
// Interfaces
for _, iface := range interfaces { for _, iface := range interfaces {
res = append(res, &aa.Dbus{ res = append(res,
Access: []string{"send"}, &aa.Dbus{
Bus: rules["bus"], Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"],
Path: rules["path"],
Interface: iface, Interface: iface,
PeerName: `"{:1.@{int},org.freedesktop.DBus}"`, PeerName: `"@{busname}"`,
}) },
&aa.Dbus{
Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"],
Interface: iface,
PeerName: `"{@{busname},org.freedesktop.DBus}"`,
},
)
} }
res = append(res, &aa.Dbus{
Access: []string{"receive"}, res = append(res,
Bus: rules["bus"], // DBus.Properties
Path: rules["path"], &aa.Dbus{
Access: []string{"send", "receive"}, Bus: rules["bus"], Path: rules["path"],
Interface: "org.freedesktop.DBus.Properties",
Member: "{Get,GetAll,Set,PropertiesChanged}",
PeerName: `"{@{busname},org.freedesktop.DBus}"`,
},
// DBus.Introspectable
&aa.Dbus{
Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"],
Interface: "org.freedesktop.DBus.Introspectable", Interface: "org.freedesktop.DBus.Introspectable",
Member: "Introspect", Member: "Introspect",
PeerName: `":1.@{int}"`, PeerName: `"@{busname}"`,
}) },
// DBus.ObjectManager
&aa.Dbus{
Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"],
Interface: "org.freedesktop.DBus.ObjectManager",
Member: "GetManagedObjects",
PeerName: `"{@{busname},` + rules["name"] + `}"`,
},
&aa.Dbus{
Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"],
Interface: "org.freedesktop.DBus.ObjectManager",
Member: "{InterfacesAdded,InterfacesRemoved}",
PeerName: `"{@{busname},org.freedesktop.DBus}"`,
},
)
return res return res
} }
func (d Dbus) talk(rules map[string]string) aa.Rules { func (d Dbus) talk(rules map[string]string, name string) aa.Rules {
interfaces := setInterfaces(rules) interfaces := getInterfaces(rules)
res := aa.Rules{}
res := aa.Rules{
&aa.Unix{
Access: []string{"bind"}, Type: "stream",
Address: `@@{udbus}/bus/` + name + `/` + rules["bus"],
},
}
// Interfaces
for _, iface := range interfaces { for _, iface := range interfaces {
res = append(res, &aa.Dbus{ res = append(res, &aa.Dbus{
Access: []string{"send"}, Access: []string{"send", "receive"}, Bus: rules["bus"], Path: rules["path"],
Bus: rules["bus"],
Path: rules["path"],
Interface: iface, Interface: iface,
PeerName: `"{:1.@{int},` + rules["name"] + `}"`, PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"],
PeerLabel: rules["label"],
})
}
for _, iface := range interfaces {
res = append(res, &aa.Dbus{
Access: []string{"receive"},
Bus: rules["bus"],
Path: rules["path"],
Interface: iface,
PeerName: `"{:1.@{int},` + rules["name"] + `}"`,
PeerLabel: rules["label"],
}) })
} }
res = append(res,
// DBus.Properties
&aa.Dbus{
Access: []string{"send", "receive"}, Bus: rules["bus"], Path: rules["path"],
Interface: "org.freedesktop.DBus.Properties",
Member: "{Get,GetAll,Set,PropertiesChanged}",
PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"],
},
// DBus.Introspectable
&aa.Dbus{
Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"],
Interface: "org.freedesktop.DBus.Introspectable",
Member: "Introspect",
PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"],
},
// DBus.ObjectManager
&aa.Dbus{
Access: []string{"send"}, Bus: rules["bus"], Path: rules["path"],
Interface: "org.freedesktop.DBus.ObjectManager",
Member: "GetManagedObjects",
PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"],
},
&aa.Dbus{
Access: []string{"receive"}, Bus: rules["bus"], Path: rules["path"],
Interface: "org.freedesktop.DBus.ObjectManager",
Member: "{InterfacesAdded,InterfacesRemoved}",
PeerName: `"{@{busname},` + rules["name"] + `}"`, PeerLabel: rules["label"],
},
)
return res return res
} }

View file

@ -6,31 +6,35 @@ package directive
import ( import (
"testing" "testing"
"github.com/roddhjav/apparmor.d/pkg/paths"
) )
const dbusOwnSystemd1 = ` dbus bind bus=system name=org.freedesktop.systemd1{,.*}, const dbusOwnSystemd1 = ` unix bind type=stream addr=@@{udbus}/bus/fake-own/system,
dbus bind bus=system name=org.freedesktop.systemd1{,.*},
dbus receive bus=system path=/org/freedesktop/systemd1{,/**} dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
interface=org.freedesktop.systemd1{,.*} interface=org.freedesktop.systemd1{,.*}
peer=(name=":1.@{int}"), peer=(name="@{busname}"),
dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
interface=org.freedesktop.DBus.Properties
peer=(name=":1.@{int}"),
dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
interface=org.freedesktop.DBus.ObjectManager
peer=(name=":1.@{int}"),
dbus send bus=system path=/org/freedesktop/systemd1{,/**} dbus send bus=system path=/org/freedesktop/systemd1{,/**}
interface=org.freedesktop.systemd1{,.*} interface=org.freedesktop.systemd1{,.*}
peer=(name="{:1.@{int},org.freedesktop.DBus}"), peer=(name="{@{busname},org.freedesktop.DBus}"),
dbus send bus=system path=/org/freedesktop/systemd1{,/**} dbus (send receive) bus=system path=/org/freedesktop/systemd1{,/**}
interface=org.freedesktop.DBus.Properties interface=org.freedesktop.DBus.Properties
peer=(name="{:1.@{int},org.freedesktop.DBus}"), member={Get,GetAll,Set,PropertiesChanged}
dbus send bus=system path=/org/freedesktop/systemd1{,/**} peer=(name="{@{busname},org.freedesktop.DBus}"),
interface=org.freedesktop.DBus.ObjectManager
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
dbus receive bus=system path=/org/freedesktop/systemd1{,/**} dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
interface=org.freedesktop.DBus.Introspectable interface=org.freedesktop.DBus.Introspectable
member=Introspect member=Introspect
peer=(name=":1.@{int}"),` peer=(name="@{busname}"),
dbus receive bus=system path=/org/freedesktop/systemd1{,/**}
interface=org.freedesktop.DBus.ObjectManager
member=GetManagedObjects
peer=(name="{@{busname},org.freedesktop.systemd1{,.*}}"),
dbus send bus=system path=/org/freedesktop/systemd1{,/**}
interface=org.freedesktop.DBus.ObjectManager
member={InterfacesAdded,InterfacesRemoved}
peer=(name="{@{busname},org.freedesktop.DBus}"),`
func TestDbus_Apply(t *testing.T) { func TestDbus_Apply(t *testing.T) {
tests := []struct { tests := []struct {
@ -50,7 +54,7 @@ func TestDbus_Apply(t *testing.T) {
"own": "", "own": "",
}, },
ArgList: []string{"own", "bus=system", "name=org.freedesktop.systemd1"}, ArgList: []string{"own", "bus=system", "name=org.freedesktop.systemd1"},
File: nil, File: paths.New("fake-own"),
Raw: " #aa:dbus own bus=system name=org.freedesktop.systemd1", Raw: " #aa:dbus own bus=system name=org.freedesktop.systemd1",
}, },
profile: " #aa:dbus own bus=system name=org.freedesktop.systemd1", profile: " #aa:dbus own bus=system name=org.freedesktop.systemd1",
@ -62,44 +66,46 @@ func TestDbus_Apply(t *testing.T) {
Name: "dbus", Name: "dbus",
ArgMap: map[string]string{ ArgMap: map[string]string{
"bus": "session", "bus": "session",
"name": "com.rastersoft.dingextension", "name": "com.rastersoft.ding",
"interface": "org.gtk.Actions", "interface+": "org.gtk.Actions",
"own": "", "own": "",
}, },
ArgList: []string{"own", "bus=session", "name=com.rastersoft.dingextension", "interface=org.gtk.Actions"}, ArgList: []string{"own", "bus=session", "name=com.rastersoft.ding", "interface+=org.gtk.Actions"},
File: nil, File: paths.New("fake-interface"),
Raw: " #aa:dbus own bus=session name=com.rastersoft.dingextension interface=org.gtk.Actions", Raw: " #aa:dbus own bus=session name=com.rastersoft.ding interface+=org.gtk.Actions",
}, },
profile: " #aa:dbus own bus=session name=com.rastersoft.dingextension interface=org.gtk.Actions", profile: " #aa:dbus own bus=session name=com.rastersoft.ding interface+=org.gtk.Actions",
want: ` dbus bind bus=session name=com.rastersoft.dingextension{,.*}, want: ` unix bind type=stream addr=@@{udbus}/bus/fake-interface/session,
dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
interface=com.rastersoft.dingextension{,.*} dbus bind bus=session name=com.rastersoft.ding{,.*},
peer=(name=":1.@{int}"), dbus receive bus=session path=/com/rastersoft/ding{,/**}
dbus receive bus=session path=/com/rastersoft/dingextension{,/**} interface=com.rastersoft.ding{,.*}
peer=(name="@{busname}"),
dbus send bus=session path=/com/rastersoft/ding{,/**}
interface=com.rastersoft.ding{,.*}
peer=(name="{@{busname},org.freedesktop.DBus}"),
dbus receive bus=session path=/com/rastersoft/ding{,/**}
interface=org.gtk.Actions interface=org.gtk.Actions
peer=(name=":1.@{int}"), peer=(name="@{busname}"),
dbus receive bus=session path=/com/rastersoft/dingextension{,/**} dbus send bus=session path=/com/rastersoft/ding{,/**}
interface=org.freedesktop.DBus.Properties
peer=(name=":1.@{int}"),
dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
interface=org.freedesktop.DBus.ObjectManager
peer=(name=":1.@{int}"),
dbus send bus=session path=/com/rastersoft/dingextension{,/**}
interface=com.rastersoft.dingextension{,.*}
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
dbus send bus=session path=/com/rastersoft/dingextension{,/**}
interface=org.gtk.Actions interface=org.gtk.Actions
peer=(name="{:1.@{int},org.freedesktop.DBus}"), peer=(name="{@{busname},org.freedesktop.DBus}"),
dbus send bus=session path=/com/rastersoft/dingextension{,/**} dbus (send receive) bus=session path=/com/rastersoft/ding{,/**}
interface=org.freedesktop.DBus.Properties interface=org.freedesktop.DBus.Properties
peer=(name="{:1.@{int},org.freedesktop.DBus}"), member={Get,GetAll,Set,PropertiesChanged}
dbus send bus=session path=/com/rastersoft/dingextension{,/**} peer=(name="{@{busname},org.freedesktop.DBus}"),
interface=org.freedesktop.DBus.ObjectManager dbus receive bus=session path=/com/rastersoft/ding{,/**}
peer=(name="{:1.@{int},org.freedesktop.DBus}"),
dbus receive bus=session path=/com/rastersoft/dingextension{,/**}
interface=org.freedesktop.DBus.Introspectable interface=org.freedesktop.DBus.Introspectable
member=Introspect member=Introspect
peer=(name=":1.@{int}"),`, peer=(name="@{busname}"),
dbus receive bus=session path=/com/rastersoft/ding{,/**}
interface=org.freedesktop.DBus.ObjectManager
member=GetManagedObjects
peer=(name="{@{busname},com.rastersoft.ding{,.*}}"),
dbus send bus=session path=/com/rastersoft/ding{,/**}
interface=org.freedesktop.DBus.ObjectManager
member={InterfacesAdded,InterfacesRemoved}
peer=(name="{@{busname},org.freedesktop.DBus}"),`,
}, },
{ {
name: "talk", name: "talk",
@ -112,28 +118,31 @@ func TestDbus_Apply(t *testing.T) {
"talk": "", "talk": "",
}, },
ArgList: []string{"talk", "bus=system", "name=org.freedesktop.Accounts", "label=accounts-daemon"}, ArgList: []string{"talk", "bus=system", "name=org.freedesktop.Accounts", "label=accounts-daemon"},
File: nil, File: paths.New("gdm-session-worker"),
Raw: " #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon", Raw: " #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon",
}, },
profile: " #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon", profile: " #aa:dbus talk bus=system name=org.freedesktop.Accounts label=accounts-daemon",
want: ` dbus send bus=system path=/org/freedesktop/Accounts{,/**} want: ` unix bind type=stream addr=@@{udbus}/bus/gdm-session-wor/system,
dbus (send receive) bus=system path=/org/freedesktop/Accounts{,/**}
interface=org.freedesktop.Accounts{,.*} interface=org.freedesktop.Accounts{,.*}
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon), peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
dbus send bus=system path=/org/freedesktop/Accounts{,/**} dbus (send receive) bus=system path=/org/freedesktop/Accounts{,/**}
interface=org.freedesktop.DBus.Properties interface=org.freedesktop.DBus.Properties
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon), member={Get,GetAll,Set,PropertiesChanged}
peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
dbus send bus=system path=/org/freedesktop/Accounts{,/**}
interface=org.freedesktop.DBus.Introspectable
member=Introspect
peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
dbus send bus=system path=/org/freedesktop/Accounts{,/**} dbus send bus=system path=/org/freedesktop/Accounts{,/**}
interface=org.freedesktop.DBus.ObjectManager interface=org.freedesktop.DBus.ObjectManager
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon), member=GetManagedObjects
dbus receive bus=system path=/org/freedesktop/Accounts{,/**} peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
interface=org.freedesktop.Accounts{,.*}
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
dbus receive bus=system path=/org/freedesktop/Accounts{,/**}
interface=org.freedesktop.DBus.Properties
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),
dbus receive bus=system path=/org/freedesktop/Accounts{,/**} dbus receive bus=system path=/org/freedesktop/Accounts{,/**}
interface=org.freedesktop.DBus.ObjectManager interface=org.freedesktop.DBus.ObjectManager
peer=(name="{:1.@{int},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),`, member={InterfacesAdded,InterfacesRemoved}
peer=(name="{@{busname},org.freedesktop.Accounts{,.*}}", label=accounts-daemon),`,
}, },
} }
for _, tt := range tests { for _, tt := range tests {