mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
parser - add support for variable expansion in dbus rules
Bug: https://bugs.launchpad.net/bugs/1218099 This patch adds support for expanding variables with dbus rules. Specifically, they can expanded within the bus, name, path, member, interface, and peer label fields. Parser test cases and regression test cases are added as well. Patch history: v1: initial version of patch v2: add equality.sh tests to verify that the results of using variable expansion is the same as what should be equivalent rules Signed-off-by: Steve Beattie <sbeattie@ubuntu.com> Acked-by: Tyler Hicks <tyhicks@canonical.com> Acked-by: Seth Arnold <seth.arnold@canonical.com>
This commit is contained in:
parent
2420c573d0
commit
05029cb9b7
13 changed files with 226 additions and 0 deletions
|
@ -141,6 +141,30 @@ out:
|
|||
return ent;
|
||||
}
|
||||
|
||||
#define DUP_STRING(orig, new, field) \
|
||||
(new)->field = (orig)->field ? strdup((orig)->field) : NULL
|
||||
|
||||
struct dbus_entry *dup_dbus_entry(struct dbus_entry *orig)
|
||||
{
|
||||
struct dbus_entry *ent = NULL;
|
||||
ent = (struct dbus_entry *) calloc(1, sizeof(struct dbus_entry));
|
||||
if (!ent)
|
||||
return NULL;
|
||||
|
||||
DUP_STRING(orig, ent, bus);
|
||||
DUP_STRING(orig, ent, name);
|
||||
DUP_STRING(orig, ent, peer_label);
|
||||
DUP_STRING(orig, ent, path);
|
||||
DUP_STRING(orig, ent, interface);
|
||||
DUP_STRING(orig, ent, member);
|
||||
ent->mode = orig->mode;
|
||||
ent->audit = orig->audit;
|
||||
ent->deny = orig->deny;
|
||||
|
||||
ent->next = orig->next;
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
void print_dbus_entry(struct dbus_entry *ent)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,7 @@ struct dbus_entry {
|
|||
void free_dbus_entry(struct dbus_entry *ent);
|
||||
struct dbus_entry *new_dbus_entry(int mode, struct cond_entry *conds,
|
||||
struct cond_entry *peer_conds);
|
||||
struct dbus_entry *dup_dbus_entry(struct dbus_entry *ent);
|
||||
void print_dbus_entry(struct dbus_entry *ent);
|
||||
|
||||
#endif /* __AA_DBUS_H */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "parser.h"
|
||||
#include "mount.h"
|
||||
#include "dbus.h"
|
||||
|
||||
static inline char *get_var_end(char *var)
|
||||
{
|
||||
|
@ -213,6 +214,19 @@ int clone_and_chain_mnt(void *v)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int clone_and_chain_dbus(void *v)
|
||||
{
|
||||
struct dbus_entry *entry = v;
|
||||
|
||||
struct dbus_entry *dup = dup_dbus_entry(entry);
|
||||
if (!dup)
|
||||
return 0;
|
||||
|
||||
entry->next = dup;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int process_variables_in_entries(struct cod_entry *entry_list)
|
||||
{
|
||||
int ret = TRUE, rc;
|
||||
|
@ -253,6 +267,42 @@ static int process_variables_in_mnt_entries(struct mnt_entry *entry_list)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int process_dbus_variables(struct dbus_entry *entry_list)
|
||||
{
|
||||
int ret = TRUE, rc;
|
||||
struct dbus_entry *entry;
|
||||
|
||||
list_for_each(entry_list, entry) {
|
||||
rc = expand_entry_variables(&entry->bus, entry,
|
||||
clone_and_chain_dbus);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
rc = expand_entry_variables(&entry->name, entry,
|
||||
clone_and_chain_dbus);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
rc = expand_entry_variables(&entry->peer_label, entry,
|
||||
clone_and_chain_dbus);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
rc = expand_entry_variables(&entry->path, entry,
|
||||
clone_and_chain_dbus);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
rc = expand_entry_variables(&entry->interface, entry,
|
||||
clone_and_chain_dbus);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
rc = expand_entry_variables(&entry->member, entry,
|
||||
clone_and_chain_dbus);
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int process_variables(struct codomain *cod)
|
||||
{
|
||||
int error = 0;
|
||||
|
@ -265,6 +315,10 @@ int process_variables(struct codomain *cod)
|
|||
error = -1;
|
||||
}
|
||||
|
||||
if (!process_dbus_variables(cod->dbus_ents)) {
|
||||
error = -1;
|
||||
}
|
||||
|
||||
if (process_hat_variables(cod) != 0) {
|
||||
error = -1;
|
||||
}
|
||||
|
|
|
@ -148,6 +148,35 @@ verify_binary_equality "dbus access parsing" \
|
|||
"/t { dbus (send,receive,,,,,,,,,,,,,,,,bind), }" \
|
||||
"/t { dbus (send,send,send,send send receive,bind), }" \
|
||||
|
||||
verify_binary_equality "dbus variable expansion" \
|
||||
"/t { dbus (send, receive) path=/com/foo member=spork interface=org.foo peer=(name=com.foo label=/com/foo), }" \
|
||||
"@{FOO}=foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO} member=spork interface=org.@{FOO} peer=(name=com.@{FOO} label=/com/@{FOO}), }" \
|
||||
"@{FOO}=foo
|
||||
@{SPORK}=spork
|
||||
/t { dbus (send, receive) path=/com/@{FOO} member=@{SPORK} interface=org.@{FOO} peer=(name=com.@{FOO} label=/com/@{FOO}), }" \
|
||||
"@{FOO}=/com/foo
|
||||
/t { dbus (send, receive) path=@{FOO} member=spork interface=org.foo peer=(name=com.foo label=@{FOO}), }" \
|
||||
"@{FOO}=com
|
||||
/t { dbus (send, receive) path=/@{FOO}/foo member=spork interface=org.foo peer=(name=@{FOO}.foo label=/@{FOO}/foo), }"
|
||||
|
||||
verify_binary_equality "dbus variable expansion, multiple values/rules" \
|
||||
"/t { dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, }" \
|
||||
"@{FOO}=foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com/bar, }" \
|
||||
"@{FOO}=foo bar
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=bar foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }"
|
||||
|
||||
verify_binary_equality "dbus variable expansion, ensure rule de-duping occurs" \
|
||||
"/t { dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, }" \
|
||||
"/t { dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, dbus (send, receive) path=/com/bar, }" \
|
||||
"@{FOO}=bar foo bar foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=bar foo bar foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com/@{FOO}, }"
|
||||
|
||||
if [ $fails -ne 0 -o $errors -ne 0 ]
|
||||
then
|
||||
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
|
||||
|
|
11
parser/tst/simple_tests/vars/vars_dbus_1.sd
Normal file
11
parser/tst/simple_tests/vars/vars_dbus_1.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#=DESCRIPTION reference variables in dbus rules
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{FOO}=bar baz
|
||||
@{BAR}=@{FOO} blort
|
||||
|
||||
/does/not/exist {
|
||||
dbus (send)
|
||||
bus=session
|
||||
path="/com/canonical/hud/applications/@{BAR}",
|
||||
}
|
11
parser/tst/simple_tests/vars/vars_dbus_2.sd
Normal file
11
parser/tst/simple_tests/vars/vars_dbus_2.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#=DESCRIPTION reference variables in dbus rules, interfaces
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{ORGS}=freedesktop ubuntu gnome kde
|
||||
|
||||
/does/not/exist {
|
||||
dbus (receive)
|
||||
bus=accessibility
|
||||
interface=org.@{ORGS}.DBus.Properties
|
||||
path="/com/canonical/hud/applications/bar",
|
||||
}
|
10
parser/tst/simple_tests/vars/vars_dbus_3.sd
Normal file
10
parser/tst/simple_tests/vars/vars_dbus_3.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#=DESCRIPTION reference variables in dbus rules, bus fields
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{BUSES}=session system accessability choochoo
|
||||
|
||||
/does/not/exist {
|
||||
dbus (send)
|
||||
bus=@{BUSES}
|
||||
path="/com/canonical/hud/applications/baz",
|
||||
}
|
13
parser/tst/simple_tests/vars/vars_dbus_4.sd
Normal file
13
parser/tst/simple_tests/vars/vars_dbus_4.sd
Normal file
|
@ -0,0 +1,13 @@
|
|||
#=DESCRIPTION reference variables in dbus rules, members
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{MEMBERS}=blurt blirt @{BAR}
|
||||
@{BAR}=@{FOO} blort
|
||||
@{FOO}=bink bank bonk blurry*
|
||||
|
||||
/does/not/exist {
|
||||
dbus (send)
|
||||
bus=session
|
||||
member=@{MEMBERS}
|
||||
path="/com/canonical/hud/applications/biff",
|
||||
}
|
12
parser/tst/simple_tests/vars/vars_dbus_5.sd
Normal file
12
parser/tst/simple_tests/vars/vars_dbus_5.sd
Normal file
|
@ -0,0 +1,12 @@
|
|||
#=DESCRIPTION reference variables in dbus rules, with peers
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{FOO}=bar baz
|
||||
@{BAR}=@{FOO} blort
|
||||
|
||||
/does/not/exist {
|
||||
dbus (send, receive)
|
||||
bus=session
|
||||
path="/foo/bar" member="bar"
|
||||
peer=(name="com.@{FOO}" label="/usr/bin/app.@{FOO}"),
|
||||
}
|
11
parser/tst/simple_tests/vars/vars_dbus_6.sd
Normal file
11
parser/tst/simple_tests/vars/vars_dbus_6.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#=DESCRIPTION reference variables in dbus rules, with name
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{FOO}=bar baz
|
||||
@{BAR}=@{FOO} blort
|
||||
|
||||
/does/not/exist {
|
||||
dbus (bind)
|
||||
bus=session
|
||||
name="com.@{BAR}.@{FOO}",
|
||||
}
|
11
parser/tst/simple_tests/vars/vars_dbus_7.sd
Normal file
11
parser/tst/simple_tests/vars/vars_dbus_7.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#=DESCRIPTION reference variables in dbus rules, with duplicates
|
||||
#=EXRESULT PASS
|
||||
|
||||
@{FOO}=bar baz bar
|
||||
@{BAR}=@{FOO} blort
|
||||
|
||||
/does/not/exist {
|
||||
dbus (bind)
|
||||
bus=session
|
||||
name="com.@{BAR}.@{FOO}",
|
||||
}
|
|
@ -10,11 +10,22 @@
|
|||
gendbusprofile()
|
||||
{
|
||||
genprofile --stdin <<EOF
|
||||
${__dbus_var_decl}
|
||||
$test {
|
||||
@{gen $test}
|
||||
$@
|
||||
}
|
||||
EOF
|
||||
unset __dbus_var_decl
|
||||
}
|
||||
|
||||
# the arguments passed are emitted in the profile's prologue, for
|
||||
# setting profile variables, e.g.
|
||||
# set_dbus_var "@{MY_DBUS_VAR}=stuff"
|
||||
# the saved variable declaration gets unset after each test run
|
||||
set_dbus_var()
|
||||
{
|
||||
__dbus_var_decl=$@
|
||||
}
|
||||
|
||||
start_bus()
|
||||
|
|
|
@ -102,6 +102,34 @@ message_gendbusprofile "dbus send bus=session path=/org/freedesktop/DBus interfa
|
|||
runtestfg "message (send allowed w/ bus, dest, path, interface, method)" pass $confined_args
|
||||
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
||||
|
||||
# Make sure send is allowed when confined with appropriate permissions along
|
||||
# with conditionals and variables (same tests as above, with vars)
|
||||
|
||||
set_dbus_var "@{BUSES}=session system"
|
||||
message_gendbusprofile "dbus send bus=@{BUSES},"
|
||||
runtestfg "message (send allowed w/ bus)" pass $confined_args
|
||||
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
||||
|
||||
set_dbus_var "@{PEERNAMES}=com.ubuntu.what net.apparmor.wiki org.freedesktop.DBus"
|
||||
message_gendbusprofile "dbus send bus=session peer=(name=@{PEERNAMES}),"
|
||||
runtestfg "message (send allowed w/ bus, dest)" pass $confined_args
|
||||
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
||||
|
||||
set_dbus_var "@{PATHNAMES}=DBus spork spoon spork"
|
||||
message_gendbusprofile "dbus send bus=session path=/org/freedesktop/@{PATHNAMES} peer=(name=org.freedesktop.DBus),"
|
||||
runchecktest "message (send allowed w/ bus, dest, path)" pass $confined_args
|
||||
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
||||
|
||||
set_dbus_var "@{INTERFACE_NAMES}=DBus spork spoon spork"
|
||||
message_gendbusprofile "dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.@{INTERFACE_NAMES} peer=(name=org.freedesktop.DBus),"
|
||||
runtestfg "message (send allowed w/ bus, dest, path, interface)" pass $confined_args
|
||||
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
||||
|
||||
set_dbus_var "@{MEMBERS}=Hello ListNames Spork Spoon"
|
||||
message_gendbusprofile "dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=@{MEMBERS} peer=(name=org.freedesktop.DBus),"
|
||||
runtestfg "message (send allowed w/ bus, dest, path, interface, method)" pass $confined_args
|
||||
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
||||
|
||||
# Make sure send is denied when confined with appropriate permissions along
|
||||
# with incorrect conditionals
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue