mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
Merge parser: add the ability to specify a priority prefix to policy rules
This enables adding a priority to a rules in policy. Rules have a default priority of 0. The priority prefix can be added before the other currently support rule prefixes, ie. [priority prefix][audit qualifier][rule mode][owner] If present a numerical priority can be assigned to the rule, where the greater the number the higher the priority. Eg. priority=1 audit file r /etc/passwd, priority=-1 deny file w /etc/**, Rule priority allows the rule with the highest priority to completely override lower priority rules where they overlap. Within a given priority level rules will accumulate in standard apparmor fashion. Eg. given priority=1 w /*c, priority=0 r /a*, priority=-1 k /*b*, /abc, /bc, /ac .. will have permissions of w /ab, /abb, /aaa, .. will have permissions of r /b, /bcb, /bab, .. will have permissions of k User specified rule priorities are currently capped at the arbitrary values of 1000, and -1000. Notes: * not all rule types support the priority prefix. Rukes like - network - capability - rlimits need to be reworked to properly preserve the policy rule structure. * this patch does not support priority on rule blocks * this patch does not support using a variable in the priority value. MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1261 Approved-by: John Johansen <john@jjmx.net> Merged-by: John Johansen <john@jjmx.net>
This commit is contained in:
commit
5edcb6f45c
108 changed files with 1807 additions and 473 deletions
|
@ -203,7 +203,7 @@ void unix_rule::downgrade_rule(Profile &prof) {
|
|||
prof.net.audit[AF_UNIX] |= mask;
|
||||
const char *error;
|
||||
network_rule *netv8 = new network_rule(perms, AF_UNIX, sock_type_n);
|
||||
if(!netv8->add_prefix({audit, rule_mode, owner}, error))
|
||||
if(!netv8->add_prefix({0, audit, rule_mode, owner}, error))
|
||||
yyerror(error);
|
||||
prof.rule_ents.push_back(netv8);
|
||||
} else {
|
||||
|
@ -344,7 +344,8 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||
write_to_prot(buffer);
|
||||
if ((mask & AA_NET_CREATE) && !has_peer_conds()) {
|
||||
buf = buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode,
|
||||
map_perms(AA_NET_CREATE),
|
||||
map_perms(audit == AUDIT_FORCE ? AA_NET_CREATE : 0),
|
||||
parseopts))
|
||||
|
@ -369,7 +370,8 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||
tmp << "\\x00";
|
||||
|
||||
buf = tmp.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode,
|
||||
map_perms(AA_NET_BIND),
|
||||
map_perms(audit == AUDIT_FORCE ? AA_NET_BIND : 0),
|
||||
parseopts))
|
||||
|
@ -394,7 +396,8 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||
AA_LOCAL_NET_PERMS & ~AA_LOCAL_NET_CMD;
|
||||
if (mask & local_mask) {
|
||||
buf = buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode,
|
||||
map_perms(mask & local_mask),
|
||||
map_perms(audit == AUDIT_FORCE ? mask & local_mask : 0),
|
||||
parseopts))
|
||||
|
@ -408,7 +411,9 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||
/* TODO: backlog conditional: for now match anything*/
|
||||
tmp << "..";
|
||||
buf = tmp.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(),
|
||||
priority,
|
||||
rule_mode,
|
||||
map_perms(AA_NET_LISTEN),
|
||||
map_perms(audit == AUDIT_FORCE ? AA_NET_LISTEN : 0),
|
||||
parseopts))
|
||||
|
@ -422,6 +427,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||
tmp << "..";
|
||||
buf = tmp.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(),
|
||||
priority,
|
||||
rule_mode,
|
||||
map_perms(mask & AA_NET_OPT),
|
||||
map_perms(audit == AUDIT_FORCE ?
|
||||
|
@ -444,7 +450,10 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||
goto fail;
|
||||
|
||||
buf = buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms & AA_PEER_NET_PERMS), map_perms(audit == AUDIT_FORCE ? perms & AA_PEER_NET_PERMS : 0), parseopts))
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms & AA_PEER_NET_PERMS),
|
||||
map_perms(audit == AUDIT_FORCE ? perms & AA_PEER_NET_PERMS : 0),
|
||||
parseopts))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,9 @@ public:
|
|||
};
|
||||
|
||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
||||
// priority is partially supported for unix rules
|
||||
// rules that get downgraded to just network socket
|
||||
// won't support them but the fine grained do.
|
||||
if (p.owner) {
|
||||
error = "owner prefix not allowed on unix rules";
|
||||
return false;
|
||||
|
|
|
@ -89,15 +89,13 @@ void all_rule::add_implied_rules(Profile &prof)
|
|||
|
||||
/* rules that have not been converted to use rule.h */
|
||||
|
||||
//file
|
||||
//file no x
|
||||
{
|
||||
const char *error;
|
||||
struct cod_entry *entry;
|
||||
char *path = strdup("/{**,}");
|
||||
int perms = ((AA_BASE_PERMS & ~AA_EXEC_TYPE) |
|
||||
(AA_MAY_EXEC));
|
||||
int perms = (AA_BASE_PERMS & ~(AA_EXEC_TYPE | AA_MAY_EXEC));
|
||||
if (rule_mode != RULE_DENY)
|
||||
perms |= AA_EXEC_INHERIT;
|
||||
/* duplicate to other permission set */
|
||||
perms |= perms << AA_OTHER_SHIFT;
|
||||
if (!path)
|
||||
|
@ -108,7 +106,35 @@ void all_rule::add_implied_rules(Profile &prof)
|
|||
}
|
||||
add_entry_to_policy(&prof, entry);
|
||||
}
|
||||
// lower priority ix
|
||||
{
|
||||
const char *error;
|
||||
struct cod_entry *entry;
|
||||
char *path = strdup("/{**,}");
|
||||
int perms = AA_MAY_EXEC;
|
||||
prefixes ix_prefix;
|
||||
|
||||
// TODO:
|
||||
// need a better way to make sure the prefix is intialized
|
||||
// without a constructor or copy constructor
|
||||
ix_prefix.priority = prefix->priority -1;
|
||||
ix_prefix.audit = prefix->audit;
|
||||
ix_prefix.rule_mode = prefix->rule_mode;
|
||||
ix_prefix.owner = prefix->owner;
|
||||
|
||||
ix_prefix.priority -= 1;
|
||||
if (rule_mode != RULE_DENY)
|
||||
perms |= AA_EXEC_INHERIT;
|
||||
/* duplicate to other permission set */
|
||||
perms |= perms << AA_OTHER_SHIFT;
|
||||
if (!path)
|
||||
yyerror(_("Memory allocation error."));
|
||||
entry = new_entry(path, perms, NULL);
|
||||
if (!entry_add_prefix(entry, ix_prefix, error)) {
|
||||
yyerror(_("%s"), error);
|
||||
}
|
||||
add_entry_to_policy(&prof, entry);
|
||||
}
|
||||
// caps
|
||||
{
|
||||
if (prefix->owner)
|
||||
|
|
|
@ -32,6 +32,10 @@ public:
|
|||
all_rule(void): prefix_rule_t(RULE_TYPE_ALL) { }
|
||||
|
||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
||||
if (p.priority != 0) {
|
||||
error = _("priority prefix not allowed on all rules");
|
||||
return false;
|
||||
}
|
||||
if (p.owner) {
|
||||
error = _("owner prefix not allowed on all rules");
|
||||
return false;
|
||||
|
|
|
@ -139,9 +139,11 @@ B<HATNAME> = (must start with alphanumeric character. See aa_change_hat(2) for a
|
|||
|
||||
B<QUALIFIER BLOCK> = I<QUALIFIERS> I<BLOCK>
|
||||
|
||||
B<INTEGER> = (+ | -)? [[:digit:]]+
|
||||
|
||||
B<ACCESS TYPE> = ( 'allow' | 'deny' )
|
||||
|
||||
B<QUALIFIERS> = [ 'audit' ] [ I<ACCESS TYPE> ]
|
||||
B<QUALIFIERS> = [ 'priority' '=' <INTEGER> ] [ 'audit' ] [ I<ACCESS TYPE> ]
|
||||
|
||||
B<CAPABILITY RULE> = [ I<QUALIFIERS> ] 'capability' [ I<CAPABILITY LIST> ]
|
||||
|
||||
|
@ -1878,6 +1880,17 @@ Rule qualifiers can modify the rule and/or permissions within the rule.
|
|||
|
||||
=over 4
|
||||
|
||||
=item B<priority>
|
||||
|
||||
Specifies the priority of the rule. Currently the allowed range is
|
||||
-1000 to 1000 with the default priority of rule is 0. Rules with
|
||||
higher priority are given preferences and will completely override
|
||||
permissions of lower priority rules where they overlap. When rules
|
||||
partially overlap the permissions of the higher priority rule will
|
||||
completely override lower priority rules within in overlap. Within a
|
||||
given priority level rules that overlap will accumulate permissions in
|
||||
the standard apparmor fashion.
|
||||
|
||||
=item B<allow>
|
||||
|
||||
Specifies that permissions requests that match the rule are allowed. This
|
||||
|
|
|
@ -274,23 +274,24 @@ int dbus_rule::gen_policy_re(Profile &prof)
|
|||
}
|
||||
|
||||
if (perms & AA_DBUS_BIND) {
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms & AA_DBUS_BIND,
|
||||
audit == AUDIT_FORCE ? perms & AA_DBUS_BIND : 0,
|
||||
2, vec, parseopts, false))
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode,
|
||||
perms & AA_DBUS_BIND,
|
||||
audit == AUDIT_FORCE ? perms & AA_DBUS_BIND : 0,
|
||||
2, vec, parseopts, false))
|
||||
goto fail;
|
||||
}
|
||||
if (perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode,
|
||||
perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
|
||||
audit == AUDIT_FORCE ? perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE) : 0,
|
||||
6, vec, parseopts, false))
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode,
|
||||
perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
|
||||
audit == AUDIT_FORCE ? perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE) : 0,
|
||||
6, vec, parseopts, false))
|
||||
goto fail;
|
||||
}
|
||||
if (perms & AA_DBUS_EAVESDROP) {
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode,
|
||||
perms & AA_DBUS_EAVESDROP,
|
||||
audit == AUDIT_FORCE ? perms & AA_DBUS_EAVESDROP : 0,
|
||||
1, vec, parseopts, false))
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode,
|
||||
perms & AA_DBUS_EAVESDROP,
|
||||
audit == AUDIT_FORCE ? perms & AA_DBUS_EAVESDROP : 0,
|
||||
1, vec, parseopts, false))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,16 +122,18 @@ int io_uring_rule::gen_policy_re(Profile &prof)
|
|||
}
|
||||
|
||||
if (perms & AA_VALID_IO_URING_PERMS) {
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
goto fail;
|
||||
|
||||
if (perms & AA_IO_URING_OVERRIDE_CREDS) {
|
||||
buf = buffer.str(); /* update buf to have label */
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
|
||||
perms, audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(),
|
||||
priority, rule_mode,
|
||||
perms, audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,10 +44,11 @@ aare_rules::~aare_rules(void)
|
|||
expr_map.clear();
|
||||
}
|
||||
|
||||
bool aare_rules::add_rule(const char *rule, rule_mode_t mode, perm32_t perms,
|
||||
perm32_t audit, optflags const &opts)
|
||||
bool aare_rules::add_rule(const char *rule, int priority, rule_mode_t mode,
|
||||
perm32_t perms, perm32_t audit, optflags const &opts)
|
||||
{
|
||||
return add_rule_vec(mode, perms, audit, 1, &rule, opts, false);
|
||||
return add_rule_vec(priority, mode, perms, audit, 1, &rule, opts,
|
||||
false);
|
||||
}
|
||||
|
||||
void aare_rules::add_to_rules(Node *tree, Node *perms)
|
||||
|
@ -71,9 +72,9 @@ static Node *cat_with_oob_separator(Node *l, Node *r)
|
|||
return new CatNode(new CatNode(l, new CharNode(transchar(-1, true))), r);
|
||||
}
|
||||
|
||||
bool aare_rules::add_rule_vec(rule_mode_t mode, perm32_t perms, perm32_t audit,
|
||||
int count, const char **rulev, optflags const &opts,
|
||||
bool oob)
|
||||
bool aare_rules::add_rule_vec(int priority, rule_mode_t mode, perm32_t perms,
|
||||
perm32_t audit, int count, const char **rulev,
|
||||
optflags const &opts, bool oob)
|
||||
{
|
||||
Node *tree = NULL, *accept;
|
||||
int exact_match;
|
||||
|
@ -107,7 +108,7 @@ bool aare_rules::add_rule_vec(rule_mode_t mode, perm32_t perms, perm32_t audit,
|
|||
if (reverse)
|
||||
flip_tree(tree);
|
||||
|
||||
accept = unique_perms.insert(mode, perms, audit, exact_match);
|
||||
accept = unique_perms.insert(priority, mode, perms, audit, exact_match);
|
||||
|
||||
if (opts.dump & DUMP_DFA_RULE_EXPR) {
|
||||
const char *separator;
|
||||
|
@ -124,6 +125,7 @@ bool aare_rules::add_rule_vec(rule_mode_t mode, perm32_t perms, perm32_t audit,
|
|||
cerr << " -> ";
|
||||
tree->dump(cerr);
|
||||
// TODO: split out from prefixes class
|
||||
cerr << " priority=" << priority;
|
||||
if (mode == RULE_DENY)
|
||||
cerr << " deny";
|
||||
else if (mode == RULE_PROMPT)
|
||||
|
@ -256,6 +258,20 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
|||
if (opts.dump & DUMP_DFA_UNIQ_PERMS)
|
||||
dfa.dump_uniq_perms("dfa");
|
||||
|
||||
/* since we are building a chfa, use the info about
|
||||
* whether the chfa supports extended perms to help
|
||||
* determine whether we clear the deny info.
|
||||
* This will let us build the minimal dfa for the
|
||||
* information supported by the backed
|
||||
*/
|
||||
if (!extended_perms ||
|
||||
// TODO: we should drop DFA_MINIMIZE check here but doing
|
||||
// so changes behavior. Do as a separate patch and fixup
|
||||
// tests, etc.
|
||||
((opts.control & CONTROL_DFA_FILTER_DENY) &&
|
||||
(opts.control & CONTROL_DFA_MINIMIZE)))
|
||||
dfa.apply_and_clear_deny();
|
||||
|
||||
if (opts.control & CONTROL_DFA_MINIMIZE) {
|
||||
dfa.minimize(opts);
|
||||
|
||||
|
@ -263,22 +279,6 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
|||
dfa.dump_uniq_perms("minimized dfa");
|
||||
}
|
||||
|
||||
if (opts.control & CONTROL_DFA_FILTER_DENY &&
|
||||
opts.control & CONTROL_DFA_MINIMIZE &&
|
||||
dfa.apply_and_clear_deny()) {
|
||||
/* Do a second minimization pass as removal of deny
|
||||
* information has moved some states from accepting
|
||||
* to none accepting partitions
|
||||
*
|
||||
* TODO: add this as a tail pass to minimization
|
||||
* so we don't need to do a full second pass
|
||||
*/
|
||||
dfa.minimize(opts);
|
||||
|
||||
if (opts.dump & DUMP_DFA_MIN_UNIQ_PERMS)
|
||||
dfa.dump_uniq_perms("minimized dfa");
|
||||
}
|
||||
|
||||
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE)
|
||||
dfa.remove_unreachable(opts);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
class UniquePerm {
|
||||
public:
|
||||
int priority;
|
||||
rule_mode_t mode;
|
||||
bool exact_match;
|
||||
uint32_t perms;
|
||||
|
@ -42,6 +43,8 @@ public:
|
|||
|
||||
bool operator<(UniquePerm const &rhs)const
|
||||
{
|
||||
if (priority < rhs.priority)
|
||||
return priority < rhs.priority;
|
||||
if (mode >= rhs.mode) {
|
||||
if (exact_match == rhs.exact_match) {
|
||||
if (perms == rhs.perms)
|
||||
|
@ -71,21 +74,21 @@ public:
|
|||
nodes.clear();
|
||||
}
|
||||
|
||||
Node *insert(rule_mode_t mode, uint32_t perms, uint32_t audit,
|
||||
bool exact_match)
|
||||
Node *insert(int priority, rule_mode_t mode, uint32_t perms,
|
||||
uint32_t audit, bool exact_match)
|
||||
{
|
||||
UniquePerm tmp = { mode, exact_match, perms, audit };
|
||||
UniquePerm tmp = { priority, mode, exact_match, perms, audit };
|
||||
iterator res = nodes.find(tmp);
|
||||
if (res == nodes.end()) {
|
||||
Node *node;
|
||||
if (mode == RULE_DENY)
|
||||
node = new DenyMatchFlag(perms, audit);
|
||||
node = new DenyMatchFlag(priority, perms, audit);
|
||||
else if (mode == RULE_PROMPT)
|
||||
node = new PromptMatchFlag(perms, audit);
|
||||
node = new PromptMatchFlag(priority, perms, audit);
|
||||
else if (exact_match)
|
||||
node = new ExactMatchFlag(perms, audit);
|
||||
node = new ExactMatchFlag(priority, perms, audit);
|
||||
else
|
||||
node = new MatchFlag(perms, audit);
|
||||
node = new MatchFlag(priority, perms, audit);
|
||||
pair<iterator, bool> val = nodes.insert(make_pair(tmp, node));
|
||||
if (val.second == false)
|
||||
return val.first->second;
|
||||
|
@ -109,11 +112,11 @@ class aare_rules {
|
|||
aare_rules(int reverse): root(NULL), unique_perms(), expr_map(), reverse(reverse), rule_count(0) { };
|
||||
~aare_rules();
|
||||
|
||||
bool add_rule(const char *rule, rule_mode_t mode, perm32_t perms,
|
||||
perm32_t audit, optflags const &opts);
|
||||
bool add_rule_vec(rule_mode_t mode, perm32_t perms, perm32_t audit,
|
||||
int count, const char **rulev, optflags const &opts,
|
||||
bool oob);
|
||||
bool add_rule(const char *rule, int priority, rule_mode_t mode,
|
||||
perm32_t perms, perm32_t audit, optflags const &opts);
|
||||
bool add_rule_vec(int priority, rule_mode_t mode, perm32_t perms,
|
||||
perm32_t audit, int count, const char **rulev,
|
||||
optflags const &opts, bool oob);
|
||||
bool append_rule(const char *rule, bool oob, bool with_perm, optflags const &opts);
|
||||
CHFA *create_chfa(int *min_match_len,
|
||||
vector <aa_perms> &perms_table,
|
||||
|
|
|
@ -886,19 +886,20 @@ public:
|
|||
|
||||
class MatchFlag: public AcceptNode {
|
||||
public:
|
||||
MatchFlag(perm32_t perms, perm32_t audit): perms(perms), audit(audit)
|
||||
MatchFlag(int priority, perm32_t perms, perm32_t audit): priority(priority), perms(perms), audit(audit)
|
||||
{
|
||||
type_flags |= NODE_TYPE_MATCHFLAG;
|
||||
}
|
||||
ostream &dump(ostream &os) { return os << "< 0x" << hex << perms << '>'; }
|
||||
|
||||
int priority;
|
||||
perm32_t perms;
|
||||
perm32_t audit;
|
||||
};
|
||||
|
||||
class ExactMatchFlag: public MatchFlag {
|
||||
public:
|
||||
ExactMatchFlag(perm32_t perms, perm32_t audit): MatchFlag(perms, audit)
|
||||
ExactMatchFlag(int priority, perm32_t perms, perm32_t audit): MatchFlag(priority, perms, audit)
|
||||
{
|
||||
type_flags |= NODE_TYPE_EXACTMATCHFLAG;
|
||||
}
|
||||
|
@ -906,7 +907,7 @@ public:
|
|||
|
||||
class DenyMatchFlag: public MatchFlag {
|
||||
public:
|
||||
DenyMatchFlag(perm32_t perms, perm32_t quiet): MatchFlag(perms, quiet)
|
||||
DenyMatchFlag(int priority, perm32_t perms, perm32_t quiet): MatchFlag(priority, perms, quiet)
|
||||
{
|
||||
type_flags |= NODE_TYPE_DENYMATCHFLAG;
|
||||
}
|
||||
|
@ -914,7 +915,7 @@ public:
|
|||
|
||||
class PromptMatchFlag: public MatchFlag {
|
||||
public:
|
||||
PromptMatchFlag(perm32_t prompt, perm32_t audit): MatchFlag(prompt, audit) {}
|
||||
PromptMatchFlag(int priority, perm32_t prompt, perm32_t audit): MatchFlag(priority, prompt, audit) {}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -493,6 +493,11 @@ DFA::DFA(Node *root, optflags const &opts, bool buildfiledfa): root(root), filed
|
|||
*/
|
||||
nnodes_cache.clear();
|
||||
node_map.clear();
|
||||
/* once created the priority information is no longer needed and
|
||||
* can prevent sets with the same perms and different priorities
|
||||
* from being merged during minimization
|
||||
*/
|
||||
clear_priorities();
|
||||
}
|
||||
|
||||
DFA::~DFA()
|
||||
|
@ -646,41 +651,34 @@ int DFA::apply_and_clear_deny(void)
|
|||
return c;
|
||||
}
|
||||
|
||||
void DFA::clear_priorities(void)
|
||||
{
|
||||
for (Partition::iterator i = states.begin(); i != states.end(); i++)
|
||||
(*i)->perms.priority = 0;
|
||||
}
|
||||
|
||||
|
||||
typedef pair<uint64_t,uint64_t> uint128_t;
|
||||
|
||||
/* minimize the number of dfa states */
|
||||
void DFA::minimize(optflags const &opts)
|
||||
{
|
||||
map<pair<uint128_t, size_t>, Partition *> perm_map;
|
||||
map<perms_t, Partition *> perm_map;
|
||||
list<Partition *> partitions;
|
||||
|
||||
/* Set up the initial partitions
|
||||
* minimum of - 1 non accepting, and 1 accepting
|
||||
* if trans hashing is used the accepting and non-accepting partitions
|
||||
* can be further split based on the number and type of transitions
|
||||
* a state makes.
|
||||
* If permission hashing is enabled the accepting partitions can
|
||||
* be further divided by permissions. This can result in not
|
||||
* obtaining a truly minimized dfa but comes close, and can speedup
|
||||
* minimization.
|
||||
*/
|
||||
int accept_count = 0;
|
||||
int final_accept = 0;
|
||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||
size_t hash = 0;
|
||||
uint128_t permtype;
|
||||
permtype.first = ((uint64_t) (PACK_AUDIT_CTL((*i)->perms.audit, (*i)->perms.quiet & (*i)->perms.deny)) << 32);
|
||||
permtype.second = (uint64_t) (*i)->perms.allow | ((uint64_t) (*i)->perms.prompt << 32);
|
||||
pair<uint128_t, size_t> group = make_pair(permtype, hash);
|
||||
map<pair<uint128_t, size_t>, Partition *>::iterator p = perm_map.find(group);
|
||||
map<perms_t, Partition *>::iterator p = perm_map.find((*i)->perms);
|
||||
if (p == perm_map.end()) {
|
||||
Partition *part = new Partition();
|
||||
part->push_back(*i);
|
||||
perm_map.insert(make_pair(group, part));
|
||||
perm_map.insert(make_pair((*i)->perms, part));
|
||||
partitions.push_back(part);
|
||||
(*i)->partition = part;
|
||||
if (permtype.first || permtype.second)
|
||||
if ((*i)->perms.is_accept())
|
||||
accept_count++;
|
||||
} else {
|
||||
(*i)->partition = p->second;
|
||||
|
@ -1392,9 +1390,7 @@ static inline int diff_qualifiers(perm32_t perm1, perm32_t perm2)
|
|||
int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
||||
{
|
||||
int error = 0;
|
||||
perm32_t exact_match_allow = 0;
|
||||
perm32_t exact_match_prompt = 0;
|
||||
perm32_t exact_audit = 0;
|
||||
perms_t exact;
|
||||
|
||||
perms.clear();
|
||||
|
||||
|
@ -1406,13 +1402,20 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
|||
continue;
|
||||
|
||||
MatchFlag *match = static_cast<MatchFlag *>(*i);
|
||||
if (perms.priority > match->priority)
|
||||
continue;
|
||||
|
||||
if (perms.priority < match->priority) {
|
||||
perms.clear(match->priority);
|
||||
exact.clear(match->priority);
|
||||
}
|
||||
if (match->is_type(NODE_TYPE_EXACTMATCHFLAG)) {
|
||||
/* exact match only ever happens with x */
|
||||
if (filedfa && !is_merged_x_consistent(exact_match_allow,
|
||||
match->perms))
|
||||
error = 1;;
|
||||
exact_match_allow |= match->perms;
|
||||
exact_audit |= match->audit;
|
||||
if (filedfa &&
|
||||
!is_merged_x_consistent(exact.allow, match->perms))
|
||||
error = 1;
|
||||
exact.allow |= match->perms;
|
||||
exact.audit |= match->audit;
|
||||
} else if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) {
|
||||
perms.deny |= match->perms;
|
||||
perms.quiet |= match->audit;
|
||||
|
@ -1420,7 +1423,8 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
|||
perms.prompt |= match->perms;
|
||||
perms.audit |= match->audit;
|
||||
} else {
|
||||
if (filedfa && !is_merged_x_consistent(perms.allow, match->perms))
|
||||
if (filedfa &&
|
||||
!is_merged_x_consistent(perms.allow, match->perms))
|
||||
error = 1;
|
||||
perms.allow |= match->perms;
|
||||
perms.audit |= match->audit;
|
||||
|
@ -1428,21 +1432,21 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
|||
}
|
||||
|
||||
if (filedfa) {
|
||||
perms.allow |= exact_match_allow & ~(ALL_AA_EXEC_TYPE);
|
||||
perms.prompt |= exact_match_prompt & ~(ALL_AA_EXEC_TYPE);
|
||||
perms.audit |= exact_audit & ~(ALL_AA_EXEC_TYPE);
|
||||
perms.allow |= exact.allow & ~(ALL_AA_EXEC_TYPE);
|
||||
perms.prompt |= exact.prompt & ~(ALL_AA_EXEC_TYPE);
|
||||
perms.audit |= exact.audit & ~(ALL_AA_EXEC_TYPE);
|
||||
} else {
|
||||
perms.allow |= exact_match_allow;
|
||||
perms.prompt |= exact_match_prompt;
|
||||
perms.audit |= exact_audit;
|
||||
perms.allow |= exact.allow;
|
||||
perms.prompt |= exact.prompt;
|
||||
perms.audit |= exact.audit;
|
||||
}
|
||||
if (exact_match_allow & AA_USER_EXEC) {
|
||||
perms.allow = (exact_match_allow & AA_USER_EXEC_TYPE) |
|
||||
if (exact.allow & AA_USER_EXEC) {
|
||||
perms.allow = (exact.allow & AA_USER_EXEC_TYPE) |
|
||||
(perms.allow & ~AA_USER_EXEC_TYPE);
|
||||
perms.exact = AA_USER_EXEC_TYPE;
|
||||
}
|
||||
if (exact_match_allow & AA_OTHER_EXEC) {
|
||||
perms.allow = (exact_match_allow & AA_OTHER_EXEC_TYPE) |
|
||||
if (exact.allow & AA_OTHER_EXEC) {
|
||||
perms.allow = (exact.allow & AA_OTHER_EXEC_TYPE) |
|
||||
(perms.allow & ~AA_OTHER_EXEC_TYPE);
|
||||
perms.exact |= AA_OTHER_EXEC_TYPE;
|
||||
}
|
||||
|
@ -1456,7 +1460,6 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
|||
perms.quiet &= perms.deny;
|
||||
perms.prompt &= ~perms.deny;
|
||||
perms.prompt &= ~perms.allow;
|
||||
|
||||
if (error)
|
||||
fprintf(stderr, "profile has merged rule with conflicting x modifiers\n");
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "expr-tree.h"
|
||||
|
@ -51,24 +52,37 @@ ostream &operator<<(ostream &os, State &state);
|
|||
|
||||
class perms_t {
|
||||
public:
|
||||
perms_t(void): allow(0), deny(0), audit(0), quiet(0), exact(0) { };
|
||||
perms_t(void): priority(INT_MIN), allow(0), deny(0), prompt(0), audit(0), quiet(0), exact(0) { };
|
||||
|
||||
bool is_accept(void) { return (allow | prompt | audit | quiet); }
|
||||
bool is_accept(void) { return (allow | deny | prompt | audit | quiet); }
|
||||
|
||||
void dump_header(ostream &os)
|
||||
{
|
||||
os << "(allow/deny/prompt/audit/quiet)";
|
||||
os << "priority (allow/deny/prompt/audit/quiet)";
|
||||
}
|
||||
void dump(ostream &os)
|
||||
{
|
||||
os << " (0x " << hex
|
||||
os << " " << priority << " (0x " << hex
|
||||
<< allow << "/" << deny << "/" << "/" << prompt << "/" << audit << "/" << quiet
|
||||
<< ')' << dec;
|
||||
}
|
||||
|
||||
void clear(void) { allow = deny = prompt = audit = quiet = 0; }
|
||||
void clear(void) {
|
||||
priority = INT_MIN;
|
||||
allow = deny = prompt = audit = quiet = exact = 0;
|
||||
}
|
||||
void clear(int p) {
|
||||
priority = p;
|
||||
allow = deny = prompt = audit = quiet = exact = 0;
|
||||
}
|
||||
void add(perms_t &rhs, bool filedfa)
|
||||
{
|
||||
if (priority > rhs.priority)
|
||||
return;
|
||||
if (priority < rhs.priority) {
|
||||
*this = rhs;
|
||||
return;
|
||||
} //else if (rhs.priority == priority) {
|
||||
deny |= rhs.deny;
|
||||
|
||||
if (filedfa && !is_merged_x_consistent(allow & ALL_USER_EXEC,
|
||||
|
@ -131,6 +145,8 @@ public:
|
|||
|
||||
bool operator<(perms_t const &rhs)const
|
||||
{
|
||||
if (priority < rhs.priority)
|
||||
return priority < rhs.priority;
|
||||
if (allow < rhs.allow)
|
||||
return allow < rhs.allow;
|
||||
if (deny < rhs.deny)
|
||||
|
@ -142,6 +158,7 @@ public:
|
|||
return quiet < rhs.quiet;
|
||||
}
|
||||
|
||||
int priority;
|
||||
perm32_t allow, deny, prompt, audit, quiet, exact;
|
||||
};
|
||||
|
||||
|
@ -351,6 +368,7 @@ public:
|
|||
bool same_mappings(State *s1, State *s2);
|
||||
void minimize(optflags const &flags);
|
||||
int apply_and_clear_deny(void);
|
||||
void clear_priorities(void);
|
||||
|
||||
void diff_encode(optflags const &flags);
|
||||
void undiff_encode(void);
|
||||
|
|
|
@ -797,8 +797,9 @@ int mnt_rule::gen_policy_remount(Profile &prof, int &count,
|
|||
* if a data match is required this only has AA_MATCH_CONT perms
|
||||
* else it has full perms
|
||||
*/
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, tmpperms, tmpaudit, 4,
|
||||
vec, parseopts, false))
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, tmpperms,
|
||||
tmpaudit, 4, vec, parseopts,
|
||||
false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
|
@ -808,7 +809,7 @@ int mnt_rule::gen_policy_remount(Profile &prof, int &count,
|
|||
if (!build_mnt_opts(optsbuf, opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms,
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, perms,
|
||||
(audit == AUDIT_FORCE ? perms : 0),
|
||||
5, vec, parseopts, false))
|
||||
goto fail;
|
||||
|
@ -850,7 +851,8 @@ int mnt_rule::gen_policy_bind_mount(Profile &prof, int &count,
|
|||
opt_flags & MS_BIND_FLAGS))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms, audit == AUDIT_FORCE ? perms : 0,
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
4, vec,
|
||||
parseopts, false))
|
||||
goto fail;
|
||||
|
@ -907,7 +909,8 @@ int mnt_rule::gen_policy_change_mount_type(Profile &prof, int &count,
|
|||
opt_flags & MS_MAKE_FLAGS))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms, audit == AUDIT_FORCE ? perms : 0,
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
4, vec,
|
||||
parseopts, false))
|
||||
goto fail;
|
||||
|
@ -950,7 +953,8 @@ int mnt_rule::gen_policy_move_mount(Profile &prof, int &count,
|
|||
opt_flags & MS_MOVE_FLAGS))
|
||||
goto fail;
|
||||
vec[3] = flagsbuf;
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms, audit == AUDIT_FORCE ? perms : 0,
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
4, vec,
|
||||
parseopts, false))
|
||||
goto fail;
|
||||
|
@ -1002,8 +1006,9 @@ int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
|
|||
tmpaudit = audit == AUDIT_FORCE ? perms : 0;
|
||||
}
|
||||
/* rule for match without required data || data MATCH_CONT */
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, tmpperms, tmpaudit, 4,
|
||||
vec, parseopts, false))
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, tmpperms,
|
||||
tmpaudit, 4, vec, parseopts,
|
||||
false))
|
||||
goto fail;
|
||||
count++;
|
||||
|
||||
|
@ -1013,7 +1018,7 @@ int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
|
|||
if (!build_mnt_opts(optsbuf, opts))
|
||||
goto fail;
|
||||
vec[4] = optsbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms,
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
5, vec, parseopts, false))
|
||||
goto fail;
|
||||
|
@ -1105,7 +1110,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
if (!convert_entry(mntbuf, mnt_point))
|
||||
goto fail;
|
||||
vec[0] = mntbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms,
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, perms,
|
||||
(audit == AUDIT_FORCE ? perms : 0), 1, vec,
|
||||
parseopts, false))
|
||||
goto fail;
|
||||
|
@ -1120,7 +1125,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
|||
if (!clear_and_convert_entry(devbuf, device))
|
||||
goto fail;
|
||||
vec[1] = devbuf.c_str();
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms,
|
||||
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, perms,
|
||||
(audit == AUDIT_FORCE ? perms : 0), 2, vec,
|
||||
parseopts, false))
|
||||
goto fail;
|
||||
|
|
|
@ -231,10 +231,19 @@ int mqueue_rule::gen_policy_re(Profile &prof)
|
|||
/* store perms at name match so label doesn't need
|
||||
* to be checked
|
||||
*/
|
||||
if (!label && !prof.policy.rules->add_rule_vec(rule_mode, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
|
||||
if (!label && !prof.policy.rules->add_rule_vec(
|
||||
priority,
|
||||
rule_mode,
|
||||
map_mqueue_perms(perms),
|
||||
audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1,
|
||||
vec, parseopts, false))
|
||||
goto fail;
|
||||
/* also provide label match with perm */
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
|
||||
if (!prof.policy.rules->add_rule_vec(priority,
|
||||
rule_mode,
|
||||
map_mqueue_perms(perms),
|
||||
audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0,
|
||||
size, vec, parseopts, false))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -266,10 +275,19 @@ int mqueue_rule::gen_policy_re(Profile &prof)
|
|||
}
|
||||
|
||||
if (perms & AA_VALID_SYSV_MQ_PERMS) {
|
||||
if (!label && !prof.policy.rules->add_rule_vec(rule_mode, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
|
||||
if (!label &&
|
||||
!prof.policy.rules->add_rule_vec(priority,
|
||||
rule_mode,
|
||||
map_mqueue_perms(perms),
|
||||
audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1,
|
||||
vec, parseopts, false))
|
||||
goto fail;
|
||||
/* also provide label match with perm */
|
||||
if (!prof.policy.rules->add_rule_vec(rule_mode, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
|
||||
if (!prof.policy.rules->add_rule_vec(priority,
|
||||
rule_mode,
|
||||
map_mqueue_perms(perms),
|
||||
audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0,
|
||||
size, vec, parseopts, false))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -697,7 +697,8 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
|
|||
|
||||
buf = oss.str();
|
||||
/* AA_CONT_MATCH mapping (cond_perms) only applies to perms, not audit */
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, cond_perms,
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, cond_perms,
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
|
@ -710,7 +711,8 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
|
|||
oss << "\\x00"; /* null transition */
|
||||
|
||||
buf = oss.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, cond_perms,
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, cond_perms,
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
|
@ -735,9 +737,10 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
|
|||
|
||||
if (!features_supports_inet || (family != AF_INET && family != AF_INET6)) {
|
||||
buf = buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -745,7 +748,8 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
|
|||
buf = buffer.str();
|
||||
/* create perms need to be generated excluding the rest of the perms */
|
||||
if (perms & AA_NET_CREATE) {
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms & AA_NET_CREATE) | (AA_CONT_MATCH << 1),
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms & AA_NET_CREATE) | (AA_CONT_MATCH << 1),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms & AA_NET_CREATE) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
|
@ -797,9 +801,10 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
|
|||
/* length of queue allowed - not used for now */
|
||||
listen_buffer << "..";
|
||||
buf = listen_buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -816,9 +821,10 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
|
|||
/* socket mapping - not used for now */
|
||||
opt_buffer << "..";
|
||||
buf = opt_buffer.str();
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, map_perms(perms),
|
||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -194,7 +194,12 @@ public:
|
|||
bool parse_address(ip_conds &entry);
|
||||
bool parse_port(ip_conds &entry);
|
||||
|
||||
// update TODO: in equality.sh when priority is a valid prefix
|
||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
||||
if (p.priority != 0) {
|
||||
error = _("priority prefix not allowed on network rules");
|
||||
return false;
|
||||
}
|
||||
if (p.owner) {
|
||||
error = _("owner prefix not allowed on network rules");
|
||||
return false;
|
||||
|
|
|
@ -53,6 +53,12 @@ using namespace std;
|
|||
*/
|
||||
extern int parser_token;
|
||||
|
||||
/* Arbitrary max and minimum priority that userspace can specify, internally
|
||||
* we handle up to INT_MAX and INT_MIN. Do not ever allow INT_MAX, see
|
||||
* note on mediates_priority
|
||||
*/
|
||||
#define MAX_PRIORITY 1000
|
||||
#define MIN_PRIORITY -1000
|
||||
|
||||
#define WARN_RULE_NOT_ENFORCED 0x1
|
||||
#define WARN_RULE_DOWNGRADED 0x2
|
||||
|
@ -114,6 +120,7 @@ struct cond_entry_list {
|
|||
};
|
||||
|
||||
struct cod_entry {
|
||||
int priority;
|
||||
char *name;
|
||||
union {
|
||||
char *link_name;
|
||||
|
|
|
@ -277,6 +277,7 @@ QUOTED_ID \"{ALLOWED_QUOTED_ID}*\"
|
|||
|
||||
IP {NUMBER}\.{NUMBER}\.{NUMBER}\.{NUMBER}
|
||||
|
||||
INTEGER [+-]?{NUMBER}
|
||||
HAT hat{WS}*
|
||||
PROFILE profile{WS}*
|
||||
KEYWORD [[:alpha:]_]+
|
||||
|
@ -332,7 +333,7 @@ GT >
|
|||
%x USERNS_MODE
|
||||
%x MQUEUE_MODE
|
||||
%x IOURING_MODE
|
||||
|
||||
%x INTEGER_MODE
|
||||
%%
|
||||
|
||||
%{
|
||||
|
@ -344,7 +345,7 @@ GT >
|
|||
}
|
||||
%}
|
||||
|
||||
<INITIAL,SUB_ID_WS,INCLUDE,INCLUDE_EXISTS,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,ABI_MODE,USERNS_MODE,MQUEUE_MODE,IOURING_MODE>{
|
||||
<INITIAL,SUB_ID_WS,INCLUDE,INCLUDE_EXISTS,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,ABI_MODE,USERNS_MODE,MQUEUE_MODE,IOURING_MODE,INTEGER_MODE>{
|
||||
{WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
|
||||
}
|
||||
|
||||
|
@ -389,6 +390,11 @@ GT >
|
|||
yylval.id = processid(yytext, yyleng);
|
||||
PUSH_AND_RETURN(EXTCONDLIST_MODE, TOK_CONDLISTID);
|
||||
}
|
||||
priority/{WS}*= {
|
||||
/* has to be before {VARIABLE_NAME} matches below */
|
||||
PUSH_AND_RETURN(INTEGER_MODE, TOK_PRIORITY);
|
||||
|
||||
}
|
||||
{VARIABLE_NAME}/{WS}*= {
|
||||
/* we match to the = in the lexer so that we can switch scanner
|
||||
* state. By the time the parser see the = it may be too late
|
||||
|
@ -630,6 +636,15 @@ GT >
|
|||
}
|
||||
}
|
||||
|
||||
<INTEGER_MODE>{
|
||||
{EQUALS} { RETURN_TOKEN(TOK_EQUALS); }
|
||||
|
||||
{INTEGER} {
|
||||
yylval.mode = strdup(yytext);
|
||||
POP_AND_RETURN(TOK_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
#include{WS}+if{WS}+exists/{WS}.*\r?\n {
|
||||
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
||||
* It needs to be handled specially
|
||||
|
@ -814,4 +829,5 @@ unordered_map<int, string> state_names = {
|
|||
STATE_TABLE_ENT(USERNS_MODE),
|
||||
STATE_TABLE_ENT(MQUEUE_MODE),
|
||||
STATE_TABLE_ENT(IOURING_MODE),
|
||||
STATE_TABLE_ENT(INTEGER_MODE),
|
||||
};
|
||||
|
|
|
@ -1583,7 +1583,10 @@ static bool get_kernel_features(struct aa_features **features)
|
|||
}
|
||||
kernel_supports_permstable32_v1 = aa_features_supports(*features, "policy/permstable32_version/0x000001");
|
||||
if (kernel_supports_permstable32_v1) {
|
||||
//fprintf(stderr, "kernel supports prompt_v1\n");
|
||||
/* permstabl32 is broken in kernels that only support v1
|
||||
* so disable it
|
||||
*/
|
||||
kernel_supports_permstable32 = false;
|
||||
}
|
||||
|
||||
/* set default prompt_compat_mode to the best that is supported */
|
||||
|
|
|
@ -131,7 +131,7 @@ static struct keyword_table keyword_table[] = {
|
|||
{"override_creds", TOK_OVERRIDE_CREDS},
|
||||
{"sqpoll", TOK_SQPOLL},
|
||||
{"all", TOK_ALL},
|
||||
|
||||
{"priority", TOK_PRIORITY},
|
||||
/* terminate */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
@ -984,6 +984,7 @@ struct cod_entry *new_entry(char *id, perm32_t perms, char *link_id)
|
|||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
entry->priority = 0;
|
||||
entry->name = id;
|
||||
entry->link_name = link_id;
|
||||
entry->perms = perms;
|
||||
|
@ -1010,6 +1011,7 @@ struct cod_entry *copy_cod_entry(struct cod_entry *orig)
|
|||
DUP_STRING(orig, entry, name, err);
|
||||
DUP_STRING(orig, entry, link_name, err);
|
||||
DUP_STRING(orig, entry, nt_name, err);
|
||||
entry->priority = orig->priority;
|
||||
entry->perms = orig->perms;
|
||||
entry->audit = orig->audit;
|
||||
entry->rule_mode = orig->rule_mode;
|
||||
|
|
|
@ -507,7 +507,7 @@ static int process_profile_name_xmatch(Profile *prof)
|
|||
aare_rules *rules = new aare_rules();
|
||||
if (!rules)
|
||||
return FALSE;
|
||||
if (!rules->add_rule(tbuf.c_str(), RULE_ALLOW,
|
||||
if (!rules->add_rule(tbuf.c_str(), 0, RULE_ALLOW,
|
||||
AA_MAY_EXEC, 0, parseopts)) {
|
||||
delete rules;
|
||||
return FALSE;
|
||||
|
@ -521,7 +521,7 @@ static int process_profile_name_xmatch(Profile *prof)
|
|||
ptype = convert_aaregex_to_pcre(alt->name, 0,
|
||||
glob_default,
|
||||
tbuf, &len);
|
||||
if (!rules->add_rule(tbuf.c_str(),
|
||||
if (!rules->add_rule(tbuf.c_str(), 0,
|
||||
RULE_ALLOW, AA_MAY_EXEC,
|
||||
0, parseopts)) {
|
||||
delete rules;
|
||||
|
@ -644,13 +644,14 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
if (entry->rule_mode == RULE_DENY) {
|
||||
if ((entry->perms & ~AA_LINK_BITS) &&
|
||||
!is_change_profile_perms(entry->perms) &&
|
||||
!dfarules->add_rule(tbuf.c_str(), entry->rule_mode,
|
||||
!dfarules->add_rule(tbuf.c_str(), entry->priority,
|
||||
entry->rule_mode,
|
||||
entry->perms & ~(AA_LINK_BITS | AA_CHANGE_PROFILE),
|
||||
entry->audit == AUDIT_FORCE ? entry->perms & ~(AA_LINK_BITS | AA_CHANGE_PROFILE) : 0,
|
||||
parseopts))
|
||||
return FALSE;
|
||||
} else if (!is_change_profile_perms(entry->perms)) {
|
||||
if (!dfarules->add_rule(tbuf.c_str(),
|
||||
if (!dfarules->add_rule(tbuf.c_str(), entry->priority,
|
||||
entry->rule_mode, entry->perms,
|
||||
entry->audit == AUDIT_FORCE ? entry->perms : 0,
|
||||
parseopts))
|
||||
|
@ -676,7 +677,10 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
perms |= LINK_TO_LINK_SUBSET(perms);
|
||||
vec[1] = "/[^/].*";
|
||||
}
|
||||
if (!dfarules->add_rule_vec(entry->rule_mode, perms, entry->audit == AUDIT_FORCE ? perms & AA_LINK_BITS : 0, 2, vec, parseopts, false))
|
||||
if (!dfarules->add_rule_vec(entry->priority,
|
||||
entry->rule_mode, perms,
|
||||
entry->audit == AUDIT_FORCE ? perms & AA_LINK_BITS : 0,
|
||||
2, vec, parseopts, false))
|
||||
return FALSE;
|
||||
}
|
||||
if (is_change_profile_perms(entry->perms)) {
|
||||
|
@ -727,13 +731,14 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
}
|
||||
|
||||
/* regular change_profile rule */
|
||||
if (!dfarules->add_rule_vec(entry->rule_mode,
|
||||
if (!dfarules->add_rule_vec(entry->priority, entry->rule_mode,
|
||||
AA_CHANGE_PROFILE | onexec_perms,
|
||||
0, index - 1, &vec[1], parseopts, false))
|
||||
return FALSE;
|
||||
|
||||
/* onexec rules - both rules are needed for onexec */
|
||||
if (!dfarules->add_rule_vec(entry->rule_mode, onexec_perms,
|
||||
if (!dfarules->add_rule_vec(entry->priority, entry->rule_mode,
|
||||
onexec_perms,
|
||||
0, 1, vec, parseopts, false))
|
||||
return FALSE;
|
||||
|
||||
|
@ -742,8 +747,9 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||
* unsafe exec transitions
|
||||
*/
|
||||
onexec_perms |= (entry->perms & (AA_EXEC_BITS | ALL_AA_EXEC_UNSAFE));
|
||||
if (!dfarules->add_rule_vec(entry->rule_mode, onexec_perms,
|
||||
0, index, vec, parseopts, false))
|
||||
if (!dfarules->add_rule_vec(entry->priority, entry->rule_mode,
|
||||
onexec_perms, 0, index, vec,
|
||||
parseopts, false))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -785,7 +791,7 @@ int process_profile_regex(Profile *prof)
|
|||
prof->dfa.dfa = prof->dfa.rules->create_dfablob(&prof->dfa.size,
|
||||
&xmatch_len, prof->dfa.perms_table,
|
||||
parseopts, true,
|
||||
prof->uses_prompt_rules && (prompt_compat_mode == PROMPT_COMPAT_PERMSV2),
|
||||
kernel_supports_permstable32,
|
||||
prof->uses_prompt_rules);
|
||||
delete prof->dfa.rules;
|
||||
prof->dfa.rules = NULL;
|
||||
|
@ -999,7 +1005,8 @@ static bool gen_net_rule(Profile *prof, u16 family, unsigned int type_mask,
|
|||
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (type_mask & 0xff);
|
||||
}
|
||||
buf = buffer.str();
|
||||
if (!prof->policy.rules->add_rule(buf.c_str(), rmode, map_perms(AA_VALID_NET_PERMS),
|
||||
if (!prof->policy.rules->add_rule(buf.c_str(), 0, rmode,
|
||||
map_perms(AA_VALID_NET_PERMS),
|
||||
audit ? map_perms(AA_VALID_NET_PERMS) : 0,
|
||||
parseopts))
|
||||
return false;
|
||||
|
@ -1076,6 +1083,20 @@ static const char *mediates_sysv_mqueue = CLASS_STR(AA_CLASS_SYSV_MQUEUE);
|
|||
static const char *mediates_io_uring = CLASS_STR(AA_CLASS_IO_URING);
|
||||
static const char *deny_file = ".*";
|
||||
|
||||
/* Set the mediates priority to the maximum possible. This is to help
|
||||
* ensure that the mediates information is not wiped out by a rule
|
||||
* of higher priority. Which for allow rules isn't really a problem
|
||||
* in that these are only used as a place holder to ensure we have
|
||||
* a valid state at the mediates check, and an allow rule that wipes
|
||||
* these out would guarantee it. But a deny rule wiping these out
|
||||
* could result in the dfa allowing stuff as unmediated when it shouldn't
|
||||
*
|
||||
* Note: it turns out the above bug does exist for dbus rules in parsers
|
||||
* that do not support priority, and we don't have a way to fix it.
|
||||
* We fix it here by capping user specified priority to be < INT_MAX.
|
||||
*/
|
||||
static int mediates_priority = INT_MAX;
|
||||
|
||||
int process_profile_policydb(Profile *prof)
|
||||
{
|
||||
int error = -1;
|
||||
|
@ -1091,7 +1112,7 @@ int process_profile_policydb(Profile *prof)
|
|||
* to be supported
|
||||
*/
|
||||
if (features_supports_userns &&
|
||||
!prof->policy.rules->add_rule(mediates_ns, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_ns, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
|
||||
/* don't add mediated classes to unconfined profiles */
|
||||
|
@ -1099,35 +1120,35 @@ int process_profile_policydb(Profile *prof)
|
|||
prof->flags.mode != MODE_DEFAULT_ALLOW) {
|
||||
/* note: this activates fs based unix domain sockets mediation on connect */
|
||||
if (kernel_abi_version > 5 &&
|
||||
!prof->policy.rules->add_rule(mediates_file, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_file, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_mount &&
|
||||
!prof->policy.rules->add_rule(mediates_mount, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_mount, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_dbus &&
|
||||
!prof->policy.rules->add_rule(mediates_dbus, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_dbus, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_signal &&
|
||||
!prof->policy.rules->add_rule(mediates_signal, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_signal, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_ptrace &&
|
||||
!prof->policy.rules->add_rule(mediates_ptrace, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_ptrace, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_networkv8 &&
|
||||
!prof->policy.rules->add_rule(mediates_netv8, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_netv8, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_unix &&
|
||||
(!prof->policy.rules->add_rule(mediates_extended_net, RULE_ALLOW, AA_MAY_READ, 0, parseopts) ||
|
||||
!prof->policy.rules->add_rule(mediates_net_unix, RULE_ALLOW, AA_MAY_READ, 0, parseopts)))
|
||||
(!prof->policy.rules->add_rule(mediates_extended_net, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts) ||
|
||||
!prof->policy.rules->add_rule(mediates_net_unix, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts)))
|
||||
goto out;
|
||||
if (features_supports_posix_mqueue &&
|
||||
!prof->policy.rules->add_rule(mediates_posix_mqueue, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_posix_mqueue, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_sysv_mqueue &&
|
||||
!prof->policy.rules->add_rule(mediates_sysv_mqueue, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_sysv_mqueue, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
if (features_supports_io_uring &&
|
||||
!prof->policy.rules->add_rule(mediates_io_uring, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
!prof->policy.rules->add_rule(mediates_io_uring, mediates_priority, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1136,11 +1157,11 @@ int process_profile_policydb(Profile *prof)
|
|||
// This requires file rule processing happen first
|
||||
if (!prof->dfa.rules->rule_count) {
|
||||
// add null dfa
|
||||
if (!prof->dfa.rules->add_rule(deny_file, RULE_DENY, AA_MAY_READ, 0, parseopts))
|
||||
if (!prof->dfa.rules->add_rule(deny_file, 0, RULE_DENY, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
}
|
||||
if (!prof->policy.rules->rule_count) {
|
||||
if (!prof->policy.rules->add_rule(mediates_file, RULE_DENY, AA_MAY_READ, 0, parseopts))
|
||||
if (!prof->policy.rules->add_rule(mediates_file, 0, RULE_DENY, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
}
|
||||
int xmatch_len = 0;
|
||||
|
@ -1167,7 +1188,7 @@ int process_profile_policydb(Profile *prof)
|
|||
&xmatch_len,
|
||||
prof->policy.perms_table,
|
||||
parseopts, false,
|
||||
prof->uses_prompt_rules && (prompt_compat_mode == PROMPT_COMPAT_PERMSV2),
|
||||
kernel_supports_permstable32,
|
||||
prof->uses_prompt_rules);
|
||||
delete prof->policy.rules;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#define YYERROR_VERBOSE 1
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
@ -149,6 +150,7 @@ static void abi_features(char *filename, bool search);
|
|||
%token TOK_OVERRIDE_CREDS
|
||||
%token TOK_SQPOLL
|
||||
%token TOK_ALL
|
||||
%token TOK_PRIORITY
|
||||
|
||||
/* rlimits */
|
||||
%token TOK_RLIMIT
|
||||
|
@ -222,7 +224,8 @@ static void abi_features(char *filename, bool search);
|
|||
struct value_list *val_list;
|
||||
struct cond_entry *cond_entry;
|
||||
struct cond_entry_list cond_entry_list;
|
||||
int boolean;
|
||||
bool boolean;
|
||||
int integer;
|
||||
owner_t owner;
|
||||
struct prefixes prefix;
|
||||
IncludeCache_t *includecache;
|
||||
|
@ -268,9 +271,10 @@ static void abi_features(char *filename, bool search);
|
|||
%type <id> id_or_var
|
||||
%type <id> opt_id_or_var
|
||||
%type <boolean> opt_subset_flag
|
||||
%type <integer> opt_priority
|
||||
%type <audit> opt_audit_flag
|
||||
%type <owner> opt_owner_flag
|
||||
%type <boolean> opt_profile_flag
|
||||
%type <integer> opt_profile_flag
|
||||
%type <boolean> opt_flags
|
||||
%type <rule_mode> opt_rule_mode
|
||||
%type <id> opt_id
|
||||
|
@ -294,7 +298,7 @@ static void abi_features(char *filename, bool search);
|
|||
%type <unix_entry> unix_rule
|
||||
%type <id> opt_target
|
||||
%type <id> opt_named_transition
|
||||
%type <boolean> opt_exec_mode
|
||||
%type <integer> opt_exec_mode
|
||||
%type <boolean> opt_file
|
||||
%type <fperms> userns_perm
|
||||
%type <fperms> userns_perms
|
||||
|
@ -588,13 +592,13 @@ flags: { /* nothing */
|
|||
$$ = fv;
|
||||
};
|
||||
|
||||
opt_flags: { /* nothing */ $$ = 0; }
|
||||
opt_flags: { /* nothing */ $$ = false; }
|
||||
| TOK_CONDID TOK_EQUALS
|
||||
{
|
||||
if (strcmp($1, "flags") != 0)
|
||||
yyerror("expected flags= got %s=", $1);
|
||||
free($1);
|
||||
$$ = 1;
|
||||
$$ = true;
|
||||
}
|
||||
|
||||
flags: opt_flags TOK_OPENPAREN flagvals TOK_CLOSEPAREN
|
||||
|
@ -626,6 +630,23 @@ opt_subset_flag: { /* nothing */ $$ = false; }
|
|||
| TOK_SUBSET { $$ = true; }
|
||||
| TOK_LE { $$ = true; }
|
||||
|
||||
|
||||
opt_priority: { $$ = 0; }
|
||||
| TOK_PRIORITY TOK_EQUALS TOK_VALUE
|
||||
{
|
||||
char *end;
|
||||
long tmp = strtol($3, &end, 10);
|
||||
if (end == $3 || *end != '\0')
|
||||
yyerror("invalid priority %s", $3);
|
||||
free($3);
|
||||
/* see note on mediates_priority */
|
||||
if (tmp > MAX_PRIORITY)
|
||||
yyerror("invalid priority %l > %d", tmp, MAX_PRIORITY);
|
||||
if (tmp < MIN_PRIORITY)
|
||||
yyerror("invalid priority %l > %d", tmp, MIN_PRIORITY);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
opt_audit_flag: { /* nothing */ $$ = AUDIT_UNSPECIFIED; }
|
||||
| TOK_AUDIT { $$ = AUDIT_FORCE; };
|
||||
|
||||
|
@ -638,11 +659,12 @@ opt_rule_mode: { /* nothing */ $$ = RULE_UNSPECIFIED; }
|
|||
| TOK_DENY { $$ = RULE_DENY; }
|
||||
| TOK_PROMPT { $$ = RULE_PROMPT; }
|
||||
|
||||
opt_prefix: opt_audit_flag opt_rule_mode opt_owner_flag
|
||||
opt_prefix: opt_priority opt_audit_flag opt_rule_mode opt_owner_flag
|
||||
{
|
||||
$$.audit = $1;
|
||||
$$.rule_mode = $2;
|
||||
$$.owner = $3;
|
||||
$$.priority = $1;
|
||||
$$.audit = $2;
|
||||
$$.rule_mode = $3;
|
||||
$$.owner = $4;
|
||||
}
|
||||
|
||||
rules: { /* nothing */
|
||||
|
@ -679,6 +701,9 @@ rules: rules opt_prefix block
|
|||
{
|
||||
struct cod_entry *entry, *tmp;
|
||||
|
||||
if (($2).priority != 0) {
|
||||
yyerror(_("priority is not allowed on rule blocks"));
|
||||
}
|
||||
PDEBUG("matched: %s%s%sblock\n",
|
||||
$2.audit == AUDIT_FORCE ? "audit " : "",
|
||||
$2.rule_mode == RULE_DENY ? "deny " : "",
|
||||
|
@ -1011,8 +1036,8 @@ opt_exec_mode: { /* nothing */ $$ = EXEC_MODE_EMPTY; }
|
|||
| TOK_UNSAFE { $$ = EXEC_MODE_UNSAFE; };
|
||||
| TOK_SAFE { $$ = EXEC_MODE_SAFE; };
|
||||
|
||||
opt_file: { /* nothing */ $$ = 0; }
|
||||
| TOK_FILE { $$ = 1; }
|
||||
opt_file: { /* nothing */ $$ = false; }
|
||||
| TOK_FILE { $$ = true; }
|
||||
|
||||
frule: id_or_var file_perms opt_named_transition TOK_END_OF_RULE
|
||||
{
|
||||
|
|
|
@ -133,9 +133,10 @@ int ptrace_rule::gen_policy_re(Profile &prof)
|
|||
|
||||
buf = buffer.str();
|
||||
if (perms & AA_VALID_PTRACE_PERMS) {
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -173,6 +173,7 @@ typedef enum { OWNER_UNSPECIFIED, OWNER_SPECIFIED, OWNER_NOT } owner_t;
|
|||
*/
|
||||
class prefixes {
|
||||
public:
|
||||
int priority;
|
||||
audit_t audit;
|
||||
rule_mode_t rule_mode;
|
||||
owner_t owner;
|
||||
|
@ -242,14 +243,15 @@ public:
|
|||
}
|
||||
|
||||
int cmp(prefixes const &rhs) const {
|
||||
if ((uint) audit < (uint) rhs.audit)
|
||||
return -1;
|
||||
if ((uint) audit > (uint) rhs.audit)
|
||||
return 1;
|
||||
if ((uint) rule_mode < (uint) rhs.rule_mode)
|
||||
return -1;
|
||||
if ((uint) rule_mode > (uint) rhs.rule_mode)
|
||||
return 1;
|
||||
int tmp = priority - rhs.priority;
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
tmp = (int) audit - (int) rhs.audit;
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
tmp = (int) rule_mode - (int) rhs.rule_mode;
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
if ((uint) owner < (uint) rhs.owner)
|
||||
return -1;
|
||||
if ((uint) owner > (uint) rhs.owner)
|
||||
|
@ -258,11 +260,7 @@ public:
|
|||
}
|
||||
|
||||
bool operator<(prefixes const &rhs) const {
|
||||
if ((uint) audit < (uint) rhs.audit)
|
||||
return true;
|
||||
if ((uint) rule_mode < (uint) rhs.rule_mode)
|
||||
return true;
|
||||
if ((uint) owner < (uint) rhs.owner)
|
||||
if (cmp(rhs) < 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -273,6 +271,7 @@ public:
|
|||
prefix_rule_t(int t = RULE_TYPE_PREFIX) : rule_t(t)
|
||||
{
|
||||
/* Must construct prefix here see note on prefixes */
|
||||
priority = 0;
|
||||
audit = AUDIT_UNSPECIFIED;
|
||||
rule_mode = RULE_UNSPECIFIED;
|
||||
owner = OWNER_UNSPECIFIED;
|
||||
|
@ -283,6 +282,19 @@ public:
|
|||
virtual bool add_prefix(const prefixes &p, const char *&error) {
|
||||
if (!valid_prefix(p, error))
|
||||
return false;
|
||||
|
||||
// priority does NOT conflict but allowed at the block
|
||||
// level yet. priority at the block level applies to
|
||||
// the entire block, but only for the level of rules
|
||||
// it is at.
|
||||
// priority within the block arranges order of rules
|
||||
// within the block.
|
||||
if (priority != 0) {
|
||||
error = "priority levels not supported";
|
||||
return false;
|
||||
}
|
||||
priority = p.priority;
|
||||
|
||||
/* audit conflicts */
|
||||
if (p.audit != AUDIT_UNSPECIFIED) {
|
||||
if (audit != AUDIT_UNSPECIFIED &&
|
||||
|
|
|
@ -316,7 +316,8 @@ int signal_rule::gen_policy_re(Profile &prof)
|
|||
|
||||
buf = buffer.str();
|
||||
if (perms & (AA_MAY_SEND | AA_MAY_RECEIVE)) {
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode,
|
||||
perms, audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
goto fail;
|
||||
|
|
|
@ -122,169 +122,175 @@ verify_binary_inequality()
|
|||
verify_binary "inequality" "$@"
|
||||
}
|
||||
|
||||
printf "Equality Tests:\n"
|
||||
|
||||
verify_binary_equality "dbus send" \
|
||||
"/t { dbus send, }" \
|
||||
"/t { dbus write, }" \
|
||||
"/t { dbus w, }"
|
||||
##########################################################################
|
||||
### wrapper fn, should be indented but isn't to reduce wrap
|
||||
verify_set()
|
||||
{
|
||||
local p1="$1"
|
||||
local p2="$2"
|
||||
echo -e "\n equality $e of '$p1' vs '$p2'\n"
|
||||
|
||||
verify_binary_equality "dbus receive" \
|
||||
"/t { dbus receive, }" \
|
||||
"/t { dbus read, }" \
|
||||
"/t { dbus r, }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus send" \
|
||||
"/t { $p1 dbus send, }" \
|
||||
"/t { $p2 dbus write, }" \
|
||||
"/t { $p2 dbus w, }"
|
||||
|
||||
verify_binary_equality "dbus send + receive" \
|
||||
"/t { dbus (send, receive), }" \
|
||||
"/t { dbus (read, write), }" \
|
||||
"/t { dbus (r, w), }" \
|
||||
"/t { dbus (rw), }" \
|
||||
"/t { dbus rw, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus receive" \
|
||||
"/t { $p1 dbus receive, }" \
|
||||
"/t { $p2 dbus read, }" \
|
||||
"/t { $p2 dbus r, }"
|
||||
|
||||
verify_binary_equality "dbus all accesses" \
|
||||
"/t { dbus (send, receive, bind, eavesdrop), }" \
|
||||
"/t { dbus (read, write, bind, eavesdrop), }" \
|
||||
"/t { dbus (r, w, bind, eavesdrop), }" \
|
||||
"/t { dbus (rw, bind, eavesdrop), }" \
|
||||
"/t { dbus (), }" \
|
||||
"/t { dbus, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus send + receive" \
|
||||
"/t { $p1 dbus (send, receive), }" \
|
||||
"/t { $p2 dbus (read, write), }" \
|
||||
"/t { $p2 dbus (r, w), }" \
|
||||
"/t { $p2 dbus (rw), }" \
|
||||
"/t { $p2 dbus rw, }" \
|
||||
|
||||
verify_binary_equality "dbus implied accesses with a bus conditional" \
|
||||
"/t { dbus (send, receive, bind, eavesdrop) bus=session, }" \
|
||||
"/t { dbus (read, write, bind, eavesdrop) bus=session, }" \
|
||||
"/t { dbus (r, w, bind, eavesdrop) bus=session, }" \
|
||||
"/t { dbus (rw, bind, eavesdrop) bus=session, }" \
|
||||
"/t { dbus () bus=session, }" \
|
||||
"/t { dbus bus=session, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus all accesses" \
|
||||
"/t { $p1 dbus (send, receive, bind, eavesdrop), }" \
|
||||
"/t { $p2 dbus (read, write, bind, eavesdrop), }" \
|
||||
"/t { $p2 dbus (r, w, bind, eavesdrop), }" \
|
||||
"/t { $p2 dbus (rw, bind, eavesdrop), }" \
|
||||
"/t { $p2 dbus (), }" \
|
||||
"/t { $p2 dbus, }" \
|
||||
|
||||
verify_binary_equality "dbus implied accesses for services" \
|
||||
"/t { dbus bind name=com.foo, }" \
|
||||
"/t { dbus name=com.foo, }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus implied accesses with a bus conditional" \
|
||||
"/t { $p1 dbus (send, receive, bind, eavesdrop) bus=session, }" \
|
||||
"/t { $p2 dbus (read, write, bind, eavesdrop) bus=session, }" \
|
||||
"/t { $p2 dbus (r, w, bind, eavesdrop) bus=session, }" \
|
||||
"/t { $p2 dbus (rw, bind, eavesdrop) bus=session, }" \
|
||||
"/t { $p2 dbus () bus=session, }" \
|
||||
"/t { $p2 dbus bus=session, }" \
|
||||
|
||||
verify_binary_equality "dbus implied accesses for messages" \
|
||||
"/t { dbus (send, receive) path=/com/foo interface=org.foo, }" \
|
||||
"/t { dbus path=/com/foo interface=org.foo, }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus implied accesses for services" \
|
||||
"/t { $p1 dbus bind name=com.foo, }" \
|
||||
"/t { $p2 dbus name=com.foo, }"
|
||||
|
||||
verify_binary_equality "dbus implied accesses for messages with peer names" \
|
||||
"/t { dbus (send, receive) path=/com/foo interface=org.foo peer=(name=com.foo), }" \
|
||||
"/t { dbus path=/com/foo interface=org.foo peer=(name=com.foo), }" \
|
||||
"/t { dbus (send, receive) path=/com/foo interface=org.foo peer=(name=(com.foo)), }" \
|
||||
"/t { dbus path=/com/foo interface=org.foo peer=(name=(com.foo)), }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus implied accesses for messages" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo interface=org.foo, }" \
|
||||
"/t { $p2 dbus path=/com/foo interface=org.foo, }"
|
||||
|
||||
verify_binary_equality "dbus implied accesses for messages with peer labels" \
|
||||
"/t { dbus (send, receive) path=/com/foo interface=org.foo peer=(label=/usr/bin/app), }" \
|
||||
"/t { dbus path=/com/foo interface=org.foo peer=(label=/usr/bin/app), }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus implied accesses for messages with peer names" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo interface=org.foo peer=(name=com.foo), }" \
|
||||
"/t { $p2 dbus path=/com/foo interface=org.foo peer=(name=com.foo), }" \
|
||||
"/t { $p2 dbus (send, receive) path=/com/foo interface=org.foo peer=(name=(com.foo)), }" \
|
||||
"/t { $p2 dbus path=/com/foo interface=org.foo peer=(name=(com.foo)), }"
|
||||
|
||||
verify_binary_equality "dbus element parsing" \
|
||||
"/t { dbus bus=b path=/ interface=i member=m peer=(name=n label=l), }" \
|
||||
"/t { dbus bus=\"b\" path=\"/\" interface=\"i\" member=\"m\" peer=(name=\"n\" label=\"l\"), }" \
|
||||
"/t { dbus bus=(b) path=(/) interface=(i) member=(m) peer=(name=(n) label=(l)), }" \
|
||||
"/t { dbus bus=(\"b\") path=(\"/\") interface=(\"i\") member=(\"m\") peer=(name=(\"n\") label=(\"l\")), }" \
|
||||
"/t { dbus bus =b path =/ interface =i member =m peer =(name =n label =l), }" \
|
||||
"/t { dbus bus= b path= / interface= i member= m peer= (name= n label= l), }" \
|
||||
"/t { dbus bus = b path = / interface = i member = m peer = ( name = n label = l ), }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus implied accesses for messages with peer labels" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo interface=org.foo peer=(label=/usr/bin/app), }" \
|
||||
"/t { $p2 dbus path=/com/foo interface=org.foo peer=(label=/usr/bin/app), }"
|
||||
|
||||
verify_binary_equality "dbus access parsing" \
|
||||
"/t { dbus, }" \
|
||||
"/t { dbus (), }" \
|
||||
"/t { dbus (send, receive, bind, eavesdrop), }" \
|
||||
"/t { dbus (send receive bind eavesdrop), }" \
|
||||
"/t { dbus (send, receive bind, eavesdrop), }" \
|
||||
"/t { dbus (send,receive,bind,eavesdrop), }" \
|
||||
"/t { dbus (send,receive,,,,,,,,,,,,,,,,bind,eavesdrop), }" \
|
||||
"/t { dbus (send,send,send,send send receive,bind eavesdrop), }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus element parsing" \
|
||||
"/t { $p1 dbus bus=b path=/ interface=i member=m peer=(name=n label=l), }" \
|
||||
"/t { $p2 dbus bus=\"b\" path=\"/\" interface=\"i\" member=\"m\" peer=(name=\"n\" label=\"l\"), }" \
|
||||
"/t { $p2 dbus bus=(b) path=(/) interface=(i) member=(m) peer=(name=(n) label=(l)), }" \
|
||||
"/t { $p2 dbus bus=(\"b\") path=(\"/\") interface=(\"i\") member=(\"m\") peer=(name=(\"n\") label=(\"l\")), }" \
|
||||
"/t { $p2 dbus bus =b path =/ interface =i member =m peer =(name =n label =l), }" \
|
||||
"/t { $p2 dbus bus= b path= / interface= i member= m peer= (name= n label= l), }" \
|
||||
"/t { $p2 dbus bus = b path = / interface = i member = m peer = ( name = n label = l ), }"
|
||||
|
||||
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), }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus access parsing" \
|
||||
"/t { $p1 dbus, }" \
|
||||
"/t { $p2 dbus (), }" \
|
||||
"/t { $p2 dbus (send, receive, bind, eavesdrop), }" \
|
||||
"/t { $p2 dbus (send receive bind eavesdrop), }" \
|
||||
"/t { $p2 dbus (send, receive bind, eavesdrop), }" \
|
||||
"/t { $p2 dbus (send,receive,bind,eavesdrop), }" \
|
||||
"/t { $p2 dbus (send,receive,,,,,,,,,,,,,,,,bind,eavesdrop), }" \
|
||||
"/t { $p2 dbus (send,send,send,send send receive,bind eavesdrop), }" \
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus variable expansion" \
|
||||
"/t { $p1 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}), }" \
|
||||
/t { $p2 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}), }" \
|
||||
/t { $p2 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}), }" \
|
||||
/t { $p2 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), }"
|
||||
/t { $p2 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, }" \
|
||||
"/t { dbus (send, receive) path=/com/{foo,bar}, }" \
|
||||
"/t { dbus (send, receive) path={/com/foo,/com/bar}, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus variable expansion, multiple values/rules" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo, $p1 dbus (send, receive) path=/com/bar, }" \
|
||||
"/t { $p2 dbus (send, receive) path=/com/{foo,bar}, }" \
|
||||
"/t { $p2 dbus (send, receive) path={/com/foo,/com/bar}, }" \
|
||||
"@{FOO}=foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com/bar, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/bar, }" \
|
||||
"@{FOO}=foo bar
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=bar foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}={bar,foo}
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=foo
|
||||
@{BAR}=bar
|
||||
/t { dbus (send, receive) path=/com/{@{FOO},@{BAR}}, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/{@{FOO},@{BAR}}, }" \
|
||||
|
||||
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, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus variable expansion, ensure rule de-duping occurs" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo, $p1 dbus (send, receive) path=/com/bar, }" \
|
||||
"/t { $p2 dbus (send, receive) path=/com/foo, $p2 dbus (send, receive) path=/com/bar, dbus (send, receive) path=/com/bar, }" \
|
||||
"@{FOO}=bar foo bar foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=bar foo bar foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com/@{FOO}, }"
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/@{FOO}, }"
|
||||
|
||||
verify_binary_equality "dbus minimization with all perms" \
|
||||
"/t { dbus, }" \
|
||||
"/t { dbus bus=session, dbus, }" \
|
||||
"/t { dbus (send, receive, bind, eavesdrop), dbus, }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with all perms" \
|
||||
"/t { $p1 dbus, }" \
|
||||
"/t { $p2 dbus bus=session, $p2 dbus, }" \
|
||||
"/t { $p2 dbus (send, receive, bind, eavesdrop), $p2 dbus, }"
|
||||
|
||||
verify_binary_equality "dbus minimization with bind" \
|
||||
"/t { dbus bind, }" \
|
||||
"/t { dbus bind bus=session, dbus bind, }" \
|
||||
"/t { dbus bind bus=system name=com.foo, dbus bind, }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with bind" \
|
||||
"/t { $p1 dbus bind, }" \
|
||||
"/t { $p2 dbus bind bus=session, $p2 dbus bind, }" \
|
||||
"/t { $p2 dbus bind bus=system name=com.foo, $p2 dbus bind, }"
|
||||
|
||||
verify_binary_equality "dbus minimization with send and a bus conditional" \
|
||||
"/t { dbus send bus=system, }" \
|
||||
"/t { dbus send bus=system path=/com/foo interface=com.foo member=bar, dbus send bus=system, }" \
|
||||
"/t { dbus send bus=system peer=(label=/usr/bin/foo), dbus send bus=system, }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with send and a bus conditional" \
|
||||
"/t { $p1 dbus send bus=system, }" \
|
||||
"/t { $p2 dbus send bus=system path=/com/foo interface=com.foo member=bar, dbus send bus=system, }" \
|
||||
"/t { $p2 dbus send bus=system peer=(label=/usr/bin/foo), $p2 dbus send bus=system, }"
|
||||
|
||||
verify_binary_equality "dbus minimization with an audit modifier" \
|
||||
"/t { audit dbus eavesdrop, }" \
|
||||
"/t { audit dbus eavesdrop bus=session, audit dbus eavesdrop, }"
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with an audit modifier" \
|
||||
"/t { $p1 audit dbus eavesdrop, }" \
|
||||
"/t { $p2 audit dbus eavesdrop bus=session, $p2 audit dbus eavesdrop, }"
|
||||
|
||||
verify_binary_equality "dbus minimization with a deny modifier" \
|
||||
"/t { deny dbus send bus=system peer=(name=com.foo), }" \
|
||||
"/t { deny dbus send bus=system peer=(name=com.foo label=/usr/bin/foo), deny dbus send bus=system peer=(name=com.foo), }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with a deny modifier" \
|
||||
"/t { $p1 deny dbus send bus=system peer=(name=com.foo), }" \
|
||||
"/t { $p2 deny dbus send bus=system peer=(name=com.foo label=/usr/bin/foo), $p2 deny dbus send bus=system peer=(name=com.foo), }" \
|
||||
|
||||
verify_binary_equality "dbus minimization found in dbus abstractions" \
|
||||
"/t { dbus send bus=session, }" \
|
||||
"/t { dbus send
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization found in dbus abstractions" \
|
||||
"/t { $p1 dbus send bus=session, }" \
|
||||
"/t { $p2 dbus send
|
||||
bus=session
|
||||
path=/org/freedesktop/DBus
|
||||
interface=org.freedesktop.DBus
|
||||
member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName}
|
||||
peer=(name=org.freedesktop.DBus),
|
||||
dbus send bus=session, }"
|
||||
$p2 dbus send bus=session, }"
|
||||
|
||||
# verify slash filtering for dbus paths.
|
||||
verify_binary_equality "dbus slash filtering for paths" \
|
||||
"/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, }" \
|
||||
"/t { dbus (send, receive) path=/com//{foo,bar}, }" \
|
||||
"/t { dbus (send, receive) path={//com/foo,/com//bar}, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' dbus slash filtering for paths" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo, $p1 dbus (send, receive) path=/com/bar, }" \
|
||||
"/t { $p2 dbus (send, receive) path=/com///foo, $p2 dbus (send, receive) path=///com/bar, }" \
|
||||
"/t { $p2 dbus (send, receive) path=/com//{foo,bar}, }" \
|
||||
"/t { $p2 dbus (send, receive) path={//com/foo,/com//bar}, }" \
|
||||
"@{FOO}=/foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com/bar, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/bar, }" \
|
||||
"@{FOO}=/foo /bar
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=/bar //foo
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=//{bar,foo}
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=/foo
|
||||
@{BAR}=bar
|
||||
/t { dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com//@{BAR}, }"
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com//@{BAR}, }"
|
||||
|
||||
# Rules compatible with audit, deny, and audit deny
|
||||
# note: change_profile does not support audit/allow/deny atm
|
||||
for rule in "capability" "capability mac_admin" \
|
||||
"network" "network tcp" "network inet6 tcp"\
|
||||
"mount" "mount /a" "mount /a -> /b" "mount options in (ro) /a -> b" \
|
||||
"remount" "remount /a" \
|
||||
"umount" "umount /a" \
|
||||
|
@ -302,6 +308,35 @@ for rule in "capability" "capability mac_admin" \
|
|||
"link /a -> /b" "link subset /a -> /b" \
|
||||
"l /a -> /b" "l subset /a -> /b" \
|
||||
"file l /a -> /b" "l subset /a -> /b"
|
||||
do
|
||||
verify_binary_equality "'$p1'x'$p2' allow modifier for \"${rule}\"" \
|
||||
"/t { $p1 ${rule}, }" \
|
||||
"/t { $p2 allow ${rule}, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' audit allow modifier for \"${rule}\"" \
|
||||
"/t { $p1 audit ${rule}, }" \
|
||||
"/t { $p2 audit allow ${rule}, }"
|
||||
|
||||
verify_binary_inequality "'$p1'x'$p2' audit, deny, and audit deny modifiers for \"${rule}\"" \
|
||||
"/t { $p1 ${rule}, }" \
|
||||
"/t { $p2 audit ${rule}, }" \
|
||||
"/t { $p2 audit allow ${rule}, }" \
|
||||
"/t { $p2 deny ${rule}, }" \
|
||||
"/t { $p2 audit deny ${rule}, }"
|
||||
|
||||
verify_binary_inequality "'$p1'x'$p2' audit vs deny and audit deny modifiers for \"${rule}\"" \
|
||||
"/t { $p1 audit ${rule}, }" \
|
||||
"/t { $p2 deny ${rule}, }" \
|
||||
"/t { $p2 audit deny ${rule}, }"
|
||||
|
||||
verify_binary_inequality "'$p1'x'$p2' deny and audit deny modifiers for \"${rule}\"" \
|
||||
"/t { $p1 deny ${rule}, }" \
|
||||
"/t { $p2 audit deny ${rule}, }"
|
||||
done
|
||||
|
||||
####### special case for network TODO: for network above when network
|
||||
####### rules fixed
|
||||
for rule in "network" "network tcp" "network inet6 tcp"
|
||||
do
|
||||
verify_binary_equality "allow modifier for \"${rule}\"" \
|
||||
"/t { ${rule}, }" \
|
||||
|
@ -357,36 +392,36 @@ for rule in "/f ux" "/f Ux" "/f px" "/f Px" "/f cx" "/f Cx" "/f ix" \
|
|||
"file /* cux -> b" "file /* Cux -> b" "file /* cix -> b" "file /* Cix -> b"
|
||||
|
||||
do
|
||||
verify_binary_equality "allow modifier for \"${rule}\"" \
|
||||
"/t { ${rule}, }" \
|
||||
"/t { allow ${rule}, }"
|
||||
verify_binary_equality "'$p1'x'$p2' allow modifier for \"${rule}\"" \
|
||||
"/t { $p1 ${rule}, }" \
|
||||
"/t { $p2 allow ${rule}, }"
|
||||
|
||||
verify_binary_equality "audit allow modifier for \"${rule}\"" \
|
||||
"/t { audit ${rule}, }" \
|
||||
"/t { audit allow ${rule}, }"
|
||||
verify_binary_equality "'$p1'x'$p2' audit allow modifier for \"${rule}\"" \
|
||||
"/t { $p1 audit ${rule}, }" \
|
||||
"/t { $p2 audit allow ${rule}, }"
|
||||
|
||||
# skip rules that don't end with x perm
|
||||
if [ -n "${rule##*x}" ] ; then continue ; fi
|
||||
|
||||
verify_binary_inequality "deny, audit deny modifier for \"${rule}\"" \
|
||||
"/t { ${rule}, }" \
|
||||
"/t { audit ${rule}, }" \
|
||||
"/t { audit allow ${rule}, }" \
|
||||
"/t { deny ${rule% *} x, }" \
|
||||
"/t { audit deny ${rule% *} x, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' deny, audit deny modifier for \"${rule}\"" \
|
||||
"/t { $p1 ${rule}, }" \
|
||||
"/t { $p2 audit ${rule}, }" \
|
||||
"/t { $p2 audit allow ${rule}, }" \
|
||||
"/t { $p2 deny ${rule% *} x, }" \
|
||||
"/t { $p2 audit deny ${rule% *} x, }"
|
||||
|
||||
verify_binary_inequality "audit vs deny and audit deny modifiers for \"${rule}\"" \
|
||||
"/t { audit ${rule}, }" \
|
||||
"/t { deny ${rule% *} x, }" \
|
||||
"/t { audit deny ${rule% *} x, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' audit vs deny and audit deny modifiers for \"${rule}\"" \
|
||||
"/t { $p1 audit ${rule}, }" \
|
||||
"/t { $p2 deny ${rule% *} x, }" \
|
||||
"/t { $p2 audit deny ${rule% *} x, }"
|
||||
|
||||
done
|
||||
|
||||
# verify deny and audit deny differ for x perms
|
||||
for prefix in "/f" "/*" "file /f" "file /*" ; do
|
||||
verify_binary_inequality "deny and audit deny x modifiers for \"${prefix}\"" \
|
||||
"/t { deny ${prefix} x, }" \
|
||||
"/t { audit deny ${prefix} x, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' deny and audit deny x modifiers for \"${prefix}\"" \
|
||||
"/t { $p1 deny ${prefix} x, }" \
|
||||
"/t { $p2 audit deny ${prefix} x, }"
|
||||
done
|
||||
|
||||
#Test equality of leading and trailing file permissions
|
||||
|
@ -403,26 +438,26 @@ for audit in "" "audit" ; do
|
|||
"lkm" "rwlk" "rwlm" "rwkm" \
|
||||
"ralk" "ralm" "wlkm" "alkm" \
|
||||
"rwlkm" "ralkm" ; do
|
||||
verify_binary_equality "leading and trailing perms for \"${perm}\"" \
|
||||
"/t { ${prefix} /f ${perm}, }" \
|
||||
"/t { ${prefix} ${perm} /f, }"
|
||||
verify_binary_equality "'$p1'x'$p2' leading and trailing perms for \"${perm}\"" \
|
||||
"/t { $p1 ${prefix} /f ${perm}, }" \
|
||||
"/t { $p2 ${prefix} ${perm} /f, }"
|
||||
done
|
||||
if [ "$allow" == "deny" ] ; then continue ; fi
|
||||
for perm in "ux" "Ux" "px" "Px" "cx" "Cx" \
|
||||
"ix" "pux" "Pux" "pix" "Pix" \
|
||||
"cux" "Cux" "cix" "Cix"
|
||||
do
|
||||
verify_binary_equality "leading and trailing perms for \"${perm}\"" \
|
||||
"/t { ${prefix} /f ${perm}, }" \
|
||||
"/t { ${prefix} ${perm} /f, }"
|
||||
verify_binary_equality "'$p1'x'$p2' leading and trailing perms for \"${perm}\"" \
|
||||
"/t { $p1 ${prefix} /f ${perm}, }" \
|
||||
"/t { $p2 ${prefix} ${perm} /f, }"
|
||||
done
|
||||
for perm in "px" "Px" "cx" "Cx" \
|
||||
"pux" "Pux" "pix" "Pix" \
|
||||
"cux" "Cux" "cix" "Cix"
|
||||
do
|
||||
verify_binary_equality "leading and trailing perms for x-transition \"${perm}\"" \
|
||||
"/t { ${prefix} /f ${perm} -> b, }" \
|
||||
"/t { ${prefix} ${perm} /f -> b, }"
|
||||
verify_binary_equality "'$p1'x'$p2' leading and trailing perms for x-transition \"${perm}\"" \
|
||||
"/t { $p1 ${prefix} /f ${perm} -> b, }" \
|
||||
"/t { $p2 ${prefix} ${perm} /f -> b, }"
|
||||
done
|
||||
done
|
||||
done
|
||||
|
@ -443,128 +478,103 @@ do
|
|||
"cix -> b" "Cix -> b"
|
||||
do
|
||||
if [ "$perm1" == "$perm2" ] ; then
|
||||
verify_binary_equality "Exec perm \"${perm1}\" - most specific match: same as glob" \
|
||||
"/t { /* ${perm1}, /f ${perm2}, }" \
|
||||
"/t { /* ${perm1}, }"
|
||||
verify_binary_equality "'$p1'x'$p2' Exec perm \"${perm1}\" - most specific match: same as glob" \
|
||||
"/t { $p1 /* ${perm1}, /f ${perm2}, }" \
|
||||
"/t { $p2 /* ${perm1}, }"
|
||||
else
|
||||
verify_binary_inequality "Exec \"${perm1}\" vs \"${perm2}\" - most specific match: different from glob" \
|
||||
"/t { /* ${perm1}, /f ${perm2}, }" \
|
||||
"/t { /* ${perm1}, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs \"${perm2}\" - most specific match: different from glob" \
|
||||
"/t { $p1 /* ${perm1}, /f ${perm2}, }" \
|
||||
"/t { $p2 /* ${perm1}, }"
|
||||
fi
|
||||
done
|
||||
verify_binary_inequality "Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
|
||||
"/t { /* ${perm1}, audit deny /f x, }" \
|
||||
"/t { /* ${perm1}, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' Exec \"${perm1}\" vs deny x - most specific match: different from glob" \
|
||||
"/t { $p1 /* ${perm1}, audit deny /f x, }" \
|
||||
"/t { $p2 /* ${perm1}, }"
|
||||
|
||||
done
|
||||
|
||||
#Test deny carves out permission
|
||||
verify_binary_inequality "Deny removes r perm" \
|
||||
"/t { /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { /foo/[abc] r, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' Deny removes r perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { $p2 /foo/[abc] r, }"
|
||||
|
||||
verify_binary_equality "Deny removes r perm" \
|
||||
"/t { /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { /foo/[ac] r, }"
|
||||
verify_binary_equality "'$p1'x'$p2' Deny removes r perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b r, }" \
|
||||
"/t { $p2 /foo/[ac] r, }"
|
||||
|
||||
#this one may not be true in the future depending on if the compiled profile
|
||||
#is explicitly including deny permissions for dynamic composition
|
||||
verify_binary_equality "Deny of ungranted perm" \
|
||||
"/t { /foo/[abc] r, audit deny /foo/b w, }" \
|
||||
"/t { /foo/[abc] r, }"
|
||||
verify_binary_equality "'$p1'x'$p2' Deny of ungranted perm" \
|
||||
"/t { $p1 /foo/[abc] r, audit deny /foo/b w, }" \
|
||||
"/t { $p2 /foo/[abc] r, }"
|
||||
|
||||
|
||||
verify_binary_equality "change_profile == change_profile -> **" \
|
||||
"/t { change_profile, }" \
|
||||
"/t { change_profile -> **, }"
|
||||
verify_binary_equality "'$p1'x'$p2' change_profile == change_profile -> **" \
|
||||
"/t { $p1 change_profile, }" \
|
||||
"/t { $p2 change_profile -> **, }"
|
||||
|
||||
verify_binary_equality "change_profile /** == change_profile /** -> **" \
|
||||
"/t { change_profile /**, }" \
|
||||
"/t { change_profile /** -> **, }"
|
||||
verify_binary_equality "'$p1'x'$p2' change_profile /** == change_profile /** -> **" \
|
||||
"/t { $p1 change_profile /**, }" \
|
||||
"/t { $p2 change_profile /** -> **, }"
|
||||
|
||||
verify_binary_equality "change_profile /** == change_profile /** -> **" \
|
||||
"/t { change_profile unsafe /**, }" \
|
||||
"/t { change_profile unsafe /** -> **, }"
|
||||
verify_binary_equality "'$p1'x'$p2' change_profile /** == change_profile /** -> **" \
|
||||
"/t { $p1 change_profile unsafe /**, }" \
|
||||
"/t { $p2 change_profile unsafe /** -> **, }"
|
||||
|
||||
verify_binary_equality "change_profile /** == change_profile /** -> **" \
|
||||
"/t { change_profile /**, }" \
|
||||
"/t { change_profile safe /** -> **, }"
|
||||
verify_binary_equality "'$p1'x'$p2' change_profile /** == change_profile /** -> **" \
|
||||
"/t { $p1 change_profile /**, }" \
|
||||
"/t { $p2 change_profile safe /** -> **, }"
|
||||
|
||||
verify_binary_inequality "change_profile /** == change_profile /** -> **" \
|
||||
"/t { change_profile /**, }" \
|
||||
"/t { change_profile unsafe /**, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' change_profile /** == change_profile /** -> **" \
|
||||
"/t { $p1 change_profile /**, }" \
|
||||
"/t { $p2 change_profile unsafe /**, }"
|
||||
|
||||
verify_binary_equality "profile name is hname in rule" \
|
||||
":ns:/hname { signal peer=/hname, }" \
|
||||
":ns:/hname { signal peer=@{profile_name}, }"
|
||||
verify_binary_equality "'$p1'x'$p2' profile name is hname in rule" \
|
||||
":ns:/hname { $p1 signal peer=/hname, }" \
|
||||
":ns:/hname { $p2 signal peer=@{profile_name}, }"
|
||||
|
||||
verify_binary_inequality "profile name is NOT fq name in rule" \
|
||||
":ns:/hname { signal peer=:ns:/hname, }" \
|
||||
":ns:/hname { signal peer=@{profile_name}, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' profile name is NOT fq name in rule" \
|
||||
":ns:/hname { $p1 signal peer=:ns:/hname, }" \
|
||||
":ns:/hname { $p2 signal peer=@{profile_name}, }"
|
||||
|
||||
verify_binary_equality "profile name is hname in sub pofile rule" \
|
||||
":ns:/hname { profile child { signal peer=/hname//child, } }" \
|
||||
":ns:/hname { profile child { signal peer=@{profile_name}, } }"
|
||||
verify_binary_equality "'$p1'x'$p2' profile name is hname in sub pofile rule" \
|
||||
":ns:/hname { profile child { $p1 signal peer=/hname//child, } }" \
|
||||
":ns:/hname { profile child { $p2 signal peer=@{profile_name}, } }"
|
||||
|
||||
verify_binary_inequality "profile name is NOT fq name in sub profile rule" \
|
||||
":ns:/hname { profile child { signal peer=:ns:/hname//child, } }" \
|
||||
":ns:/hname { profile child { signal peer=@{profile_name}, } }"
|
||||
verify_binary_inequality "'$p1'x'$p2' profile name is NOT fq name in sub profile rule" \
|
||||
":ns:/hname { profile child { $p1 signal peer=:ns:/hname//child, } }" \
|
||||
":ns:/hname { profile child { $p2 signal peer=@{profile_name}, } }"
|
||||
|
||||
verify_binary_equality "profile name is hname in hat rule" \
|
||||
":ns:/hname { ^child { signal peer=/hname//child, } }" \
|
||||
":ns:/hname { ^child { signal peer=@{profile_name}, } }"
|
||||
verify_binary_equality "'$p1'x'$p2' profile name is hname in hat rule" \
|
||||
":ns:/hname { ^child { $p1 signal peer=/hname//child, } }" \
|
||||
":ns:/hname { ^child { $p2 signal peer=@{profile_name}, } }"
|
||||
|
||||
verify_binary_inequality "profile name is NOT fq name in hat rule" \
|
||||
":ns:/hname { ^child { signal peer=:ns:/hname//child, } }" \
|
||||
":ns:/hname { ^child { signal peer=@{profile_name}, } }"
|
||||
verify_binary_inequality "'$p1'x'$p2' profile name is NOT fq name in hat rule" \
|
||||
":ns:/hname { ^child { $p1 signal peer=:ns:/hname//child, } }" \
|
||||
":ns:/hname { ^child { $p2 signal peer=@{profile_name}, } }"
|
||||
|
||||
verify_binary_equality "@{profile_name} is literal in peer" \
|
||||
"/{a,b} { signal peer=/\{a,b\}, }" \
|
||||
"/{a,b} { signal peer=@{profile_name}, }"
|
||||
verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer" \
|
||||
"/{a,b} { $p1 signal peer=/\{a,b\}, }" \
|
||||
"/{a,b} { $p2 signal peer=@{profile_name}, }"
|
||||
|
||||
verify_binary_equality "@{profile_name} is literal in peer with pattern" \
|
||||
"/{a,b} { signal peer={/\{a,b\},c}, }" \
|
||||
"/{a,b} { signal peer={@{profile_name},c}, }"
|
||||
verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer with pattern" \
|
||||
"/{a,b} { $p1 signal peer={/\{a,b\},c}, }" \
|
||||
"/{a,b} { $p2 signal peer={@{profile_name},c}, }"
|
||||
|
||||
verify_binary_inequality "@{profile_name} is not pattern in peer" \
|
||||
"/{a,b} { signal peer=/{a,b}, }" \
|
||||
"/{a,b} { signal peer=@{profile_name}, }"
|
||||
verify_binary_inequality "'$p1'x'$p2' @{profile_name} is not pattern in peer" \
|
||||
"/{a,b} { $p1 signal peer=/{a,b}, }" \
|
||||
"/{a,b} { $p2 signal peer=@{profile_name}, }"
|
||||
|
||||
verify_binary_equality "@{profile_name} is literal in peer with esc sequence" \
|
||||
"/\\\\a { signal peer=/\\\\a, }" \
|
||||
"/\\\\a { signal peer=@{profile_name}, }"
|
||||
verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer with esc sequence" \
|
||||
"/\\\\a { $p1 signal peer=/\\\\a, }" \
|
||||
"/\\\\a { $p2 signal peer=@{profile_name}, }"
|
||||
|
||||
verify_binary_equality "@{profile_name} is literal in peer with esc alt sequence" \
|
||||
"/\\{a,b\\},c { signal peer=/\\{a,b\\},c, }" \
|
||||
"/\\{a,b\\},c { signal peer=@{profile_name}, }"
|
||||
verify_binary_equality "'$p1'x'$p2' @{profile_name} is literal in peer with esc alt sequence" \
|
||||
"/\\{a,b\\},c { $p1 signal peer=/\\{a,b\\},c, }" \
|
||||
"/\\{a,b\\},c { $p2 signal peer=@{profile_name}, }"
|
||||
|
||||
|
||||
|
||||
# verify rlimit data conversions
|
||||
verify_binary_equality "set rlimit rttime <= 12 weeks" \
|
||||
"/t { set rlimit rttime <= 12 weeks, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7)) days, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24)) hours, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60)) minutes, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60)) seconds, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000)) ms, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)) us, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)), }"
|
||||
|
||||
verify_binary_equality "set rlimit cpu <= 42 weeks" \
|
||||
"/t { set rlimit cpu <= 42 weeks, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7)) days, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24)) hours, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60)) minutes, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)) seconds, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)), }"
|
||||
|
||||
verify_binary_equality "set rlimit memlock <= 2GB" \
|
||||
"/t { set rlimit memlock <= 2GB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024)) MB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024 * 1024)) KB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }"
|
||||
|
||||
# Unfortunately we can not just compare an empty profile and hat to a
|
||||
# ie. "/t { ^test { /f r, }}"
|
||||
# to the second profile with the equivalent rule inserted manually
|
||||
|
@ -577,62 +587,62 @@ verify_binary_equality "set rlimit memlock <= 2GB" \
|
|||
# the "write" permission in the second profile and the test will fail.
|
||||
# If the parser is adding the change_hat proc attr rules then the
|
||||
# rules should merge and be equivalent.
|
||||
verify_binary_equality "change_hat rules automatically inserted"\
|
||||
"/t { owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
|
||||
"/t { owner /proc/[0-9]*/attr/{apparmor/,}current w, ^test { owner /proc/[0-9]*/attr/{apparmor/,}current w, /f r, }}"
|
||||
verify_binary_equality "'$p1'x'$p2' change_hat rules automatically inserted"\
|
||||
"/t { $p1 owner /proc/[0-9]*/attr/{apparmor/,}current a, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current a, /f r, }}" \
|
||||
"/t { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, ^test { $p2 owner /proc/[0-9]*/attr/{apparmor/,}current w, /f r, }}"
|
||||
|
||||
# verify slash filtering for unix socket address paths.
|
||||
# see https://bugs.launchpad.net/apparmor/+bug/1856738
|
||||
verify_binary_equality "unix rules addr conditional" \
|
||||
"/t { unix bind addr=@/a/bar, }" \
|
||||
"/t { unix bind addr=@/a//bar, }" \
|
||||
"/t { unix bind addr=@//a/bar, }" \
|
||||
"/t { unix bind addr=@/a///bar, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' unix rules addr conditional" \
|
||||
"/t { $p1 unix bind addr=@/a/bar, }" \
|
||||
"/t { $p2 unix bind addr=@/a//bar, }" \
|
||||
"/t { $p2 unix bind addr=@//a/bar, }" \
|
||||
"/t { $p2 unix bind addr=@/a///bar, }" \
|
||||
"@{HOME}=/a/
|
||||
/t { unix bind addr=@@{HOME}/bar, }" \
|
||||
/t { $p2 unix bind addr=@@{HOME}/bar, }" \
|
||||
"@{HOME}=/a/
|
||||
/t { unix bind addr=@//@{HOME}bar, }" \
|
||||
/t { $p2 unix bind addr=@//@{HOME}bar, }" \
|
||||
"@{HOME}=/a/
|
||||
/t { unix bind addr=@/@{HOME}/bar, }"
|
||||
/t { $p2 unix bind addr=@/@{HOME}/bar, }"
|
||||
|
||||
verify_binary_equality "unix rules peer addr conditional" \
|
||||
"/t { unix peer=(addr=@/a/bar), }" \
|
||||
"/t { unix peer=(addr=@/a//bar), }" \
|
||||
"/t { unix peer=(addr=@//a/bar), }" \
|
||||
"/t { unix peer=(addr=@/a///bar), }" \
|
||||
verify_binary_equality "'$p1'x'$p2' unix rules peer addr conditional" \
|
||||
"/t { $p1 unix peer=(addr=@/a/bar), }" \
|
||||
"/t { $p2 unix peer=(addr=@/a//bar), }" \
|
||||
"/t { $p2 unix peer=(addr=@//a/bar), }" \
|
||||
"/t { $p2 unix peer=(addr=@/a///bar), }" \
|
||||
"@{HOME}=/a/
|
||||
/t { unix peer=(addr=@@{HOME}/bar), }" \
|
||||
/t { $p2 unix peer=(addr=@@{HOME}/bar), }" \
|
||||
"@{HOME}=/a/
|
||||
/t { unix peer=(addr=@//@{HOME}bar), }" \
|
||||
/t { $p2 unix peer=(addr=@//@{HOME}bar), }" \
|
||||
"@{HOME}=/a/
|
||||
/t { unix peer=(addr=@/@{HOME}/bar), }"
|
||||
/t { $p2 unix peer=(addr=@/@{HOME}/bar), }"
|
||||
|
||||
# verify slash filtering for mount rules
|
||||
verify_binary_equality "mount rules slash filtering" \
|
||||
"/t { mount /dev/foo -> /mnt/bar, }" \
|
||||
"/t { mount ///dev/foo -> /mnt/bar, }" \
|
||||
"/t { mount /dev/foo -> /mnt//bar, }" \
|
||||
"/t { mount /dev///foo -> ////mnt/bar, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' mount rules slash filtering" \
|
||||
"/t { $p1 mount /dev/foo -> /mnt/bar, }" \
|
||||
"/t { $p2 mount ///dev/foo -> /mnt/bar, }" \
|
||||
"/t { $p2 mount /dev/foo -> /mnt//bar, }" \
|
||||
"/t { $p2 mount /dev///foo -> ////mnt/bar, }" \
|
||||
"@{MNT}=/mnt/
|
||||
/t { mount /dev///foo -> @{MNT}/bar, }" \
|
||||
/t { $p2 mount /dev///foo -> @{MNT}/bar, }" \
|
||||
"@{FOO}=/foo
|
||||
/t { mount /dev//@{FOO} -> /mnt/bar, }"
|
||||
/t { $p2 mount /dev//@{FOO} -> /mnt/bar, }"
|
||||
|
||||
# verify slash filtering for link rules
|
||||
verify_binary_equality "link rules slash filtering" \
|
||||
"/t { link /dev/foo -> /mnt/bar, }" \
|
||||
"/t { link ///dev/foo -> /mnt/bar, }" \
|
||||
"/t { link /dev/foo -> /mnt//bar, }" \
|
||||
"/t { link /dev///foo -> ////mnt/bar, }" \
|
||||
verify_binary_equality "'$p1'x'$p2' link rules slash filtering" \
|
||||
"/t { $p1 link /dev/foo -> /mnt/bar, }" \
|
||||
"/t { $p2 link ///dev/foo -> /mnt/bar, }" \
|
||||
"/t { $p2 link /dev/foo -> /mnt//bar, }" \
|
||||
"/t { $p2 link /dev///foo -> ////mnt/bar, }" \
|
||||
"@{BAR}=/mnt/
|
||||
/t { link /dev///foo -> @{BAR}/bar, }" \
|
||||
/t { $p2 link /dev///foo -> @{BAR}/bar, }" \
|
||||
"@{FOO}=/dev/
|
||||
/t { link @{FOO}//foo -> /mnt/bar, }" \
|
||||
/t { $p2 link @{FOO}//foo -> /mnt/bar, }" \
|
||||
"@{FOO}=/dev/
|
||||
@{BAR}=/mnt/
|
||||
/t { link @{FOO}/foo -> @{BAR}/bar, }"
|
||||
/t { $p2 link @{FOO}/foo -> @{BAR}/bar, }"
|
||||
|
||||
verify_binary_equality "attachment slash filtering" \
|
||||
verify_binary_equality "'$p1'x'$p2' attachment slash filtering" \
|
||||
"/t /bin/foo { }" \
|
||||
"/t /bin//foo { }" \
|
||||
"@{BAR}=/bin/
|
||||
|
@ -660,9 +670,9 @@ verify_binary_equality "value like comment at end of set var" \
|
|||
# dfas dumped will be different, even if the binary is the same
|
||||
# Note: this test in the future will require -O filter-deny and
|
||||
# -O minimize and -O remove-unreachable.
|
||||
verify_binary_equality "mount specific deny doesn't affect non-overlapping" \
|
||||
"/t { mount options=bind /e/ -> /**, }" \
|
||||
"/t { audit deny mount /s/** -> /**,
|
||||
verify_binary_equality "'$p1'x'$p2' mount specific deny doesn't affect non-overlapping" \
|
||||
"/t { $p1 mount options=bind /e/ -> /**, }" \
|
||||
"/t { $p2 audit deny mount /s/** -> /**,
|
||||
mount options=bind /e/ -> /**, }"
|
||||
|
||||
if [ $fails -ne 0 ] || [ $errors -ne 0 ]
|
||||
|
@ -671,6 +681,139 @@ then
|
|||
exit $((fails + errors))
|
||||
fi
|
||||
|
||||
|
||||
## priority override equivalence tests
|
||||
## compare single rule, to multi-rule profile where one rule overrides
|
||||
## the other rule via priority.
|
||||
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus variable expansion, multiple values/rules" \
|
||||
"/t { dbus (send, receive) path=/com/foo, }" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo, $p2 dbus (send, receive) path=/com/foo, }" \
|
||||
"@{FOO}=foo
|
||||
/t { $p1 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/foo, }" \
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus variable expansion, ensure rule de-duping occurs" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, }" \
|
||||
"/t { $p2 dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, dbus (send, receive) path=/com/bar, }" \
|
||||
"@{FOO}=bar foo bar foo
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=bar foo bar foo
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, dbus (send, receive) path=/com/@{FOO}, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with all perms" \
|
||||
"/t { $p1 dbus, }" \
|
||||
"/t { $p2 dbus bus=session, $p2 dbus, }" \
|
||||
"/t { $p2 dbus (send, receive, bind, eavesdrop), $p2 dbus, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with bind" \
|
||||
"/t { $p1 dbus bind, }" \
|
||||
"/t { $p2 dbus bind bus=session, $p2 dbus bind, }" \
|
||||
"/t { $p2 dbus bind bus=system name=com.foo, $p2 dbus bind, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with send and a bus conditional" \
|
||||
"/t { $p1 dbus send bus=system, }" \
|
||||
"/t { $p2 dbus send bus=system path=/com/foo interface=com.foo member=bar, dbus send bus=system, }" \
|
||||
"/t { $p2 dbus send bus=system peer=(label=/usr/bin/foo), $p2 dbus send bus=system, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with an audit modifier" \
|
||||
"/t { $p1 audit dbus eavesdrop, }" \
|
||||
"/t { $p2 audit dbus eavesdrop bus=session, $p2 audit dbus eavesdrop, }"
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization with a deny modifier" \
|
||||
"/t { $p1 deny dbus send bus=system peer=(name=com.foo), }" \
|
||||
"/t { $p2 deny dbus send bus=system peer=(name=com.foo label=/usr/bin/foo), $p2 deny dbus send bus=system peer=(name=com.foo), }" \
|
||||
|
||||
verify_binary_equality "'$p1'x'$p2' dbus minimization found in dbus abstractions" \
|
||||
"/t { $p1 dbus send bus=session, }" \
|
||||
"/t { $p2 dbus send
|
||||
bus=session
|
||||
path=/org/freedesktop/DBus
|
||||
interface=org.freedesktop.DBus
|
||||
member={Hello,AddMatch,RemoveMatch,GetNameOwner,NameHasOwner,StartServiceByName}
|
||||
peer=(name=org.freedesktop.DBus),
|
||||
$p2 dbus send bus=session, }"
|
||||
|
||||
# verify slash filtering for dbus paths.
|
||||
verify_binary_equality "'$p1'x'$p2' dbus slash filtering for paths" \
|
||||
"/t { $p1 dbus (send, receive) path=/com/foo, dbus (send, receive) path=/com/bar, }" \
|
||||
"/t { $p2 dbus (send, receive) path=/com///foo, dbus (send, receive) path=///com/bar, }" \
|
||||
"/t { $p2 dbus (send, receive) path=/com//{foo,bar}, }" \
|
||||
"/t { $p2 dbus (send, receive) path={//com/foo,/com//bar}, }" \
|
||||
"@{FOO}=/foo
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com/bar, }" \
|
||||
"@{FOO}=/foo /bar
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=/bar //foo
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=//{bar,foo}
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, }" \
|
||||
"@{FOO}=/foo
|
||||
@{BAR}=bar
|
||||
/t { $p2 dbus (send, receive) path=/com/@{FOO}, $p2 dbus (send, receive) path=/com//@{BAR}, }"
|
||||
|
||||
|
||||
|
||||
#### end of wrapper fn
|
||||
}
|
||||
|
||||
|
||||
printf "Equality Tests:\n"
|
||||
|
||||
#rules that don't support priority
|
||||
|
||||
# verify rlimit data conversions
|
||||
verify_binary_equality "set rlimit rttime <= 12 weeks" \
|
||||
"/t { set rlimit rttime <= 12 weeks, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7)) days, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24)) hours, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60)) minutes, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60)) seconds, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000)) ms, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)) us, }" \
|
||||
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)), }"
|
||||
|
||||
verify_binary_equality "set rlimit cpu <= 42 weeks" \
|
||||
"/t { set rlimit cpu <= 42 weeks, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7)) days, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24)) hours, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60)) minutes, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)) seconds, }" \
|
||||
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)), }"
|
||||
|
||||
verify_binary_equality "set rlimit memlock <= 2GB" \
|
||||
"/t { set rlimit memlock <= 2GB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024)) MB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024 * 1024)) KB, }" \
|
||||
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }"
|
||||
|
||||
|
||||
# verify combinations of different priority levels
|
||||
# for single rule comparisons, rules should keep same expected result
|
||||
# even when the priorities are different.
|
||||
# different priorities within a profile comparison resulting in
|
||||
# different permission could affected expected results
|
||||
|
||||
|
||||
priorities="none 0 1 -1"
|
||||
|
||||
for pri1 in $priorities ; do
|
||||
if [ "$pri1" = "none" ] ; then
|
||||
priority1=""
|
||||
else
|
||||
priority1="priority=$pri1"
|
||||
fi
|
||||
for pri2 in $priorities ; do
|
||||
if [ "$pri2" = "none" ] ; then
|
||||
priority2=""
|
||||
else
|
||||
priority2="priority=$pri2"
|
||||
fi
|
||||
|
||||
verify_set "$priority1" "$priority2"
|
||||
done
|
||||
done
|
||||
|
||||
[ -z "${verbose}" ] && printf "\n"
|
||||
printf "PASS\n"
|
||||
exit 0
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
capability {0xffffff
|
||||
}
|
||||
caps {extended {yes
|
||||
}
|
||||
mask {chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read perfmon bpf checkpoint_restore
|
||||
}
|
||||
}
|
||||
dbus {mask {acquire send receive
|
||||
}
|
||||
}
|
||||
domain {attach_conditions {xattr {yes
|
||||
}
|
||||
}
|
||||
change_hat {yes
|
||||
}
|
||||
change_hatv {yes
|
||||
}
|
||||
change_onexec {yes
|
||||
}
|
||||
change_profile {yes
|
||||
}
|
||||
computed_longest_left {yes
|
||||
}
|
||||
disconnected.path {yes
|
||||
}
|
||||
fix_binfmt_elf_mmap {yes
|
||||
}
|
||||
interruptible {yes
|
||||
}
|
||||
kill.signal {yes
|
||||
}
|
||||
post_nnp_subset {yes
|
||||
}
|
||||
stack {yes
|
||||
}
|
||||
unconfined_allowed_children {yes
|
||||
}
|
||||
version {1.2
|
||||
}
|
||||
}
|
||||
policy {outofband {0x000001
|
||||
}
|
||||
permstable32 {allow deny subtree cond kill complain prompt audit quiet hide xindex tag label
|
||||
}
|
||||
permstable32_version {0x000003
|
||||
}
|
||||
set_load {yes
|
||||
}
|
||||
versions {v5 {yes
|
||||
}
|
||||
v6 {yes
|
||||
}
|
||||
v7 {yes
|
||||
}
|
||||
v8 {yes
|
||||
}
|
||||
v9 {yes
|
||||
}
|
||||
}
|
||||
}
|
||||
query {label {data {yes
|
||||
}
|
||||
multi_transaction {yes
|
||||
}
|
||||
perms {allow deny audit quiet
|
||||
}
|
||||
}
|
||||
}
|
117
parser/tst/features_files/features.extended-perms-policydb
Normal file
117
parser/tst/features_files/features.extended-perms-policydb
Normal file
|
@ -0,0 +1,117 @@
|
|||
capability {0xffffff
|
||||
}
|
||||
caps {extended {yes
|
||||
}
|
||||
mask {chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap mac_override mac_admin syslog wake_alarm block_suspend audit_read perfmon bpf checkpoint_restore
|
||||
}
|
||||
}
|
||||
dbus {mask {acquire send receive
|
||||
}
|
||||
}
|
||||
domain {attach_conditions {xattr {yes
|
||||
}
|
||||
}
|
||||
change_hat {yes
|
||||
}
|
||||
change_hatv {yes
|
||||
}
|
||||
change_onexec {yes
|
||||
}
|
||||
change_profile {yes
|
||||
}
|
||||
computed_longest_left {yes
|
||||
}
|
||||
disconnected.path {yes
|
||||
}
|
||||
fix_binfmt_elf_mmap {yes
|
||||
}
|
||||
interruptible {yes
|
||||
}
|
||||
kill.signal {yes
|
||||
}
|
||||
post_nnp_subset {yes
|
||||
}
|
||||
stack {yes
|
||||
}
|
||||
unconfined_allowed_children {yes
|
||||
}
|
||||
version {1.2
|
||||
}
|
||||
}
|
||||
file {mask {create read write exec append mmap_exec link lock
|
||||
}
|
||||
}
|
||||
io_uring {mask {sqpoll override_creds
|
||||
}
|
||||
}
|
||||
ipc {posix_mqueue {create read write open delete setattr getattr
|
||||
}
|
||||
}
|
||||
mount {mask {mount umount pivot_root
|
||||
}
|
||||
move_mount {detached
|
||||
}
|
||||
}
|
||||
namespaces {mask {userns_create
|
||||
}
|
||||
pivot_root {no
|
||||
}
|
||||
profile {yes
|
||||
}
|
||||
userns_create {pciu&
|
||||
}
|
||||
}
|
||||
network {af_mask {unspec unix inet ax25 ipx appletalk netrom bridge atmpvc x25 inet6 rose netbeui security key netlink packet ash econet atmsvc rds sna irda pppox wanpipe llc ib mpls can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock kcm qipcrtr smc xdp mctp
|
||||
}
|
||||
af_unix {yes
|
||||
}
|
||||
}
|
||||
network_v8 {af_inet {yes
|
||||
}
|
||||
af_mask {unspec unix inet ax25 ipx appletalk netrom bridge atmpvc x25 inet6 rose netbeui security key netlink packet ash econet atmsvc rds sna irda pppox wanpipe llc ib mpls can tipc bluetooth iucv rxrpc isdn phonet ieee802154 caif alg nfc vsock kcm qipcrtr smc xdp mctp
|
||||
}
|
||||
}
|
||||
policy {outofband {0x000001
|
||||
}
|
||||
permstable32 {allow deny subtree cond kill complain prompt audit quiet hide xindex tag label
|
||||
}
|
||||
permstable32_version {0x000003
|
||||
}
|
||||
set_load {yes
|
||||
}
|
||||
unconfined_restrictions {change_profile {yes
|
||||
}
|
||||
io_uring {0
|
||||
}
|
||||
userns {0
|
||||
}
|
||||
}
|
||||
versions {v5 {yes
|
||||
}
|
||||
v6 {yes
|
||||
}
|
||||
v7 {yes
|
||||
}
|
||||
v8 {yes
|
||||
}
|
||||
v9 {yes
|
||||
}
|
||||
}
|
||||
}
|
||||
ptrace {mask {read trace
|
||||
}
|
||||
}
|
||||
query {label {data {yes
|
||||
}
|
||||
multi_transaction {yes
|
||||
}
|
||||
perms {allow deny audit quiet
|
||||
}
|
||||
}
|
||||
}
|
||||
rlimit {mask {cpu fsize data stack core rss nproc nofile memlock as locks sigpending msgqueue nice rtprio rttime
|
||||
}
|
||||
}
|
||||
signal {mask {hup int quit ill trap abrt bus fpe kill usr1 segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg xcpu xfsz vtalrm prof winch io pwr sys emt lost
|
||||
}
|
||||
}
|
|
@ -78,7 +78,7 @@ APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
|
|||
# {a} (0x 40030/0/0/0)
|
||||
|
||||
echo -n "Minimize profiles basic perms "
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} (.*)$')" -ne 6 ] ; then
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 6 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
|
@ -93,7 +93,7 @@ echo "ok"
|
|||
# {9} (0x 12804a/0/2800a/0)
|
||||
# {c} (0x 40030/0/0/0)
|
||||
echo -n "Minimize profiles audit perms "
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} (.*)$')" -ne 6 ] ; then
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 6 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
|
@ -112,7 +112,7 @@ echo "ok"
|
|||
# {c} (0x 40030/0/0/0)
|
||||
|
||||
echo -n "Minimize profiles deny perms "
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} (.*)$')" -ne 6 ] ; then
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 6 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
|
@ -130,13 +130,59 @@ echo "ok"
|
|||
# {c} (0x 40030/0/0/0)
|
||||
|
||||
echo -n "Minimize profiles audit deny perms "
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} (.*)$')" -ne 5 ] ; then
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -O filter-deny -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 5 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
|
||||
# ---------------------- extended perms ------------------------------
|
||||
|
||||
|
||||
# Test that not filtering deny results in more states. This test is testing
|
||||
# without filtering. The following test does the filtering
|
||||
#
|
||||
# {1} <== (allow/deny/prompt/audit/quiet)
|
||||
# {3} (0x 0/2800a///0/0/0)
|
||||
# {4} (0x 10004/2800a///0/0/0)
|
||||
# {7} (0x 40010/2800a///0/0/0)
|
||||
# {8} (0x 80020/2800a///0/0/0)
|
||||
# {9} (0x 100040/2800a///0/0/0)
|
||||
# {12} (0x 40030/0///0/0/0)
|
||||
# {2} (0x 4/0//0/0/0) <- from policydb still showing up bug
|
||||
|
||||
## NOTE: change count from 6 to 7 when extend perms is not dependent on
|
||||
## prompt rules being present
|
||||
echo -n "Minimize profiles extended no-filter audit deny perms "
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ${APPARMOR_PARSER} -M features_files/features.extended-perms-no-policydb -QT -O minimize -O no-filter-deny -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 7 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
# same test as above except with filter-deny which should result in one less
|
||||
# accept state
|
||||
#
|
||||
# {1} <== (allow/deny/prompt/audit/quiet)
|
||||
# {4} (0x 10004/0///0/0/0)
|
||||
# {7} (0x 40010/0///0/0/0)
|
||||
# {8} (0x 80020/0///0/0/0)
|
||||
# {9} (0x 100040/0///0/0/0)
|
||||
# {12} (0x 40030/0///0/0/0)
|
||||
# {2} (0x 4/0//0/0/0) <- from policydb still showing up bug
|
||||
|
||||
echo -n "Minimize profiles extended filter audit deny perms "
|
||||
if [ "$(echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ${APPARMOR_PARSER} -M features_files/features.extended-perms-no-policydb -QT -O minimize -O filter-deny -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 6 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
echo "ok"
|
||||
|
||||
|
||||
|
||||
# ======================= x transition ===============================
|
||||
|
||||
# The x transition test profile is setup so that there are 3 conflicting x
|
||||
# permissions, two are on paths that won't collide during dfa creation. The
|
||||
# 3rd is a generic permission that should be overridden during dfa creation.
|
||||
|
@ -162,7 +208,7 @@ echo "ok"
|
|||
#
|
||||
|
||||
echo -n "Minimize profiles xtrans "
|
||||
if [ "$(echo "/t { /b px, /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} (.*)$')" -ne 3 ] ; then
|
||||
if [ "$(echo "/t { /b px, /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 3 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
|
@ -170,7 +216,7 @@ echo "ok"
|
|||
|
||||
# same test as above + audit
|
||||
echo -n "Minimize profiles audit xtrans "
|
||||
if [ "$(echo "/t { /b px, audit /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} (.*)$')" -ne 3 ] ; then
|
||||
if [ "$(echo "/t { /b px, audit /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 3 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
|
@ -183,7 +229,7 @@ echo "ok"
|
|||
# {3} (0x 0/fe17f85/0/14005)
|
||||
|
||||
echo -n "Minimize profiles deny xtrans "
|
||||
if [ "$(echo "/t { /b px, deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} (.*)$')" -ne 1 ] ; then
|
||||
if [ "$(echo "/t { /b px, deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 1 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
|
@ -195,7 +241,7 @@ echo "ok"
|
|||
# {3} (0x 0/fe17f85/0/0)
|
||||
|
||||
echo -n "Minimize profiles audit deny xtrans "
|
||||
if [ "$(echo "/t { /b px, audit deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} (.*)$')" -ne 0 ] ; then
|
||||
if [ "$(echo "/t { /b px, audit deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -M features_files/features.nopolicydb -QT -O minimize -O no-filter-deny -D dfa-states 2>&1 | grep -v '<==' | grep -c '^{.*} 0 (.*)$')" -ne 0 ] ; then
|
||||
echo "failed"
|
||||
exit 1;
|
||||
fi
|
||||
|
|
24
parser/tst/simple_tests/file/priority/front_perms_ok_1.sd
Normal file
24
parser/tst/simple_tests/file/priority/front_perms_ok_1.sd
Normal file
|
@ -0,0 +1,24 @@
|
|||
#
|
||||
#=DESCRIPTION perms before pathname
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
|
||||
priority=-1 file r /foo1,
|
||||
priority=-1 file w /foo1,
|
||||
priority=-1 file a /foo1,
|
||||
priority=-1 file k /foo1,
|
||||
priority=-1 file m /foo1,
|
||||
priority=-1 file l /foo1,
|
||||
priority=-1 file px /foo1,
|
||||
priority=-1 file Px /foo2,
|
||||
priority=-1 file ux /foo3,
|
||||
priority=-1 file Ux /foo4,
|
||||
priority=-1 file ix /foo5,
|
||||
priority=-1 file unsafe px /foo6,
|
||||
priority=-1 file unsafe Px /foo7,
|
||||
priority=-1 file unsafe ux /foo8,
|
||||
priority=-1 file unsafe Ux /foo9,
|
||||
priority=-1 file unsafe ix /foo10,
|
||||
|
||||
}
|
24
parser/tst/simple_tests/file/priority/front_perms_ok_2.sd
Normal file
24
parser/tst/simple_tests/file/priority/front_perms_ok_2.sd
Normal file
|
@ -0,0 +1,24 @@
|
|||
#
|
||||
#=DESCRIPTION perms before pathname
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
|
||||
priority=-1 r /foo1,
|
||||
priority=-1 w /foo1,
|
||||
priority=-1 a /foo1,
|
||||
priority=-1 k /foo1,
|
||||
priority=-1 m /foo1,
|
||||
priority=-1 l /foo1,
|
||||
priority=-1 px /foo1,
|
||||
priority=-1 Px /foo2,
|
||||
priority=-1 ux /foo3,
|
||||
priority=-1 Ux /foo4,
|
||||
priority=-1 ix /foo5,
|
||||
priority=-1 unsafe px /foo6,
|
||||
priority=-1 unsafe Px /foo7,
|
||||
priority=-1 unsafe ux /foo8,
|
||||
priority=-1 unsafe Ux /foo9,
|
||||
priority=-1 unsafe ix /foo10,
|
||||
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_1.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_1.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description basic file rule
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /usr/bin/foo r,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_2.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_2.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description basic uppercase permission file rule (should emit warning)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /usr/bin/foo RWM,
|
||||
}
|
9
parser/tst/simple_tests/file/priority/ok_3.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_3.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION A simple successful profile
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
/usr/bin/foo r,
|
||||
priority=-1 /usr/bin/blah rix,
|
||||
}
|
||||
|
7
parser/tst/simple_tests/file/priority/ok_4.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_4.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description basic inherit uppercase exec permission (should emit warning)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /usr/bin/foo iX,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_5.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_5.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description basic unconfined uppercase exec permission (should emit warning)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=+5 /usr/bin/foo UX,
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description basic file rule w/alternations
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=0 /a/b/c/**{cache,data,download,/ext,fileadmin,files,images,joomla,moodledata/sessions}/** rw,
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description basic file rule w/nested alternations
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /a/b/c/**{cache,data,download,/ext,file{admin,s},images,joomla,moodledata/sessions}/** rw,
|
||||
}
|
File diff suppressed because one or more lines are too long
13
parser/tst/simple_tests/file/priority/ok_append_1.sd
Normal file
13
parser/tst/simple_tests/file/priority/ok_append_1.sd
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
#=DESCRIPTION test append
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
/bin/cat a,
|
||||
/bin/true ra,
|
||||
/bin/false ma,
|
||||
priority=-1 /lib/libc.so la,
|
||||
/bin/less ixa,
|
||||
/bin/more pxa,
|
||||
/a uxa,
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 audit deny link /alpha/beta -> /tmp/**,
|
||||
}
|
||||
|
8
parser/tst/simple_tests/file/priority/ok_bare_1.sd
Normal file
8
parser/tst/simple_tests/file/priority/ok_bare_1.sd
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
#=Description bare file rule
|
||||
#=EXRESULT PASS
|
||||
#=TODO https://launchpad.net/bugs/1215637
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=19 deny file,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_carat_1.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_carat_1.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION carat in pathname
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /foo^bar r,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_carat_2.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_carat_2.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION trailing carat in pathname
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /foo/bar^ r,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_comma_1.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_comma_1.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION comma in pathname
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /foo,bar r,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_comma_2.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_comma_2.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION comma at end of pathname
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 "/foobar," r,
|
||||
}
|
9
parser/tst/simple_tests/file/priority/ok_deny_1.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_deny_1.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION A simple deny rule
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=apparmor
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 deny /usr/bin/foo r,
|
||||
}
|
||||
|
9
parser/tst/simple_tests/file/priority/ok_deny_2.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_deny_2.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION A simple deny rule
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=apparmor
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 deny /usr/bin/foo r,
|
||||
}
|
||||
|
10
parser/tst/simple_tests/file/priority/ok_deny_3.sd
Normal file
10
parser/tst/simple_tests/file/priority/ok_deny_3.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION an overlapping deny rule
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=apparmor
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /usr/bin/** r,
|
||||
priority=5 deny /usr/bin/foo r,
|
||||
}
|
||||
|
10
parser/tst/simple_tests/file/priority/ok_deny_4.sd
Normal file
10
parser/tst/simple_tests/file/priority/ok_deny_4.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION an exact overlapping deny rule
|
||||
#=EXRESULT PASS
|
||||
# vim:syntax=apparmor
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /usr/bin/foo r,
|
||||
priority=-1 deny /usr/bin/foo r,
|
||||
}
|
||||
|
9
parser/tst/simple_tests/file/priority/ok_deny_link.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_deny_link.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 deny link /alpha/beta -> /tmp/**,
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#=DESCRIPTION Simple test case for embedded spaces
|
||||
#=EXRESULT PASS
|
||||
|
||||
/bin/foo {
|
||||
priority=-1 "/abc\ def" r,
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#=DESCRIPTION Simple test case for embedded spaces
|
||||
#=EXRESULT PASS
|
||||
|
||||
/bin/foo {
|
||||
priority=-1 "/abc def" r,
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#=DESCRIPTION Simple test case for embedded spaces
|
||||
#=EXRESULT PASS
|
||||
|
||||
"/bin/fo o" {
|
||||
priority=-1 "/abc def" r,
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#=DESCRIPTION Simple test case for embedded spaces
|
||||
#=EXRESULT PASS
|
||||
|
||||
/bin/foo {
|
||||
priority=-1 /abc\ def r,
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION carat in pathname
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /foo[^me]bar r,
|
||||
}
|
10
parser/tst/simple_tests/file/priority/ok_link_1.sd
Normal file
10
parser/tst/simple_tests/file/priority/ok_link_1.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 /alpha/beta rl,
|
||||
/gamma/* rwl,
|
||||
}
|
||||
|
10
parser/tst/simple_tests/file/priority/ok_link_2.sd
Normal file
10
parser/tst/simple_tests/file/priority/ok_link_2.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 link /alpha/beta -> /tmp/**,
|
||||
/tmp/** r,
|
||||
}
|
||||
|
10
parser/tst/simple_tests/file/priority/ok_link_3.sd
Normal file
10
parser/tst/simple_tests/file/priority/ok_link_3.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 link subset /alpha/beta -> /tmp/**,
|
||||
/tmp/** r,
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION link access test with audit deny and owner restriction
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 audit deny owner link subset /alpha/beta -> /tmp/**,
|
||||
/tmp/** r,
|
||||
}
|
||||
|
10
parser/tst/simple_tests/file/priority/ok_link_owner.sd
Normal file
10
parser/tst/simple_tests/file/priority/ok_link_owner.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test with owner restriction
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 owner link subset /alpha/beta -> /tmp/**,
|
||||
/tmp/** r,
|
||||
}
|
||||
|
17
parser/tst/simple_tests/file/priority/ok_lock_1.sd
Normal file
17
parser/tst/simple_tests/file/priority/ok_lock_1.sd
Normal file
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
#=DESCRIPTION k and other perms do not conflict
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
/bin/a k,
|
||||
/bin/b rk,
|
||||
/bin/c wk,
|
||||
priority=-1 /bin/d ak,
|
||||
/bin/e lk,
|
||||
/bin/e mk,
|
||||
/bin/f pxk,
|
||||
/bin/g Pxk,
|
||||
/bin/h ixk,
|
||||
/bin/i uxk,
|
||||
/bin/j Uxk,
|
||||
}
|
12
parser/tst/simple_tests/file/priority/ok_mmap_1.sd
Normal file
12
parser/tst/simple_tests/file/priority/ok_mmap_1.sd
Normal file
|
@ -0,0 +1,12 @@
|
|||
#
|
||||
#=DESCRIPTION m and [uUpPi]x do not conflict
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /bin/cat mix,
|
||||
/bin/true mpx,
|
||||
priority=-1 /bin/false mux,
|
||||
priority=-1 /lib/libc.so rwlm,
|
||||
/bin/less mUx,
|
||||
priority=10 /bin/more mPx,
|
||||
}
|
14
parser/tst/simple_tests/file/priority/ok_mmap_2.sd
Normal file
14
parser/tst/simple_tests/file/priority/ok_mmap_2.sd
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
#=DESCRIPTION m and [upi]x do not conflict, separate rules
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
/bin/cat rm,
|
||||
/bin/cat ix,
|
||||
priority=-1 /bin/true px,
|
||||
/bin/true m,
|
||||
/bin/false m,
|
||||
/bin/false ux,
|
||||
priority=-1 /lib/libc.so rwl,
|
||||
/lib/libc.so m,
|
||||
}
|
8
parser/tst/simple_tests/file/priority/ok_octal_1.sd
Normal file
8
parser/tst/simple_tests/file/priority/ok_octal_1.sd
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
#=DESCRIPTION simple octal test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile ascii {
|
||||
priority=-1 /bin/\141bcde rix,
|
||||
}
|
8
parser/tst/simple_tests/file/priority/ok_octal_2.sd
Normal file
8
parser/tst/simple_tests/file/priority/ok_octal_2.sd
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
#=DESCRIPTION simple quoted octal expansion
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile octal {
|
||||
priority=-1 "/bin/a b \143 d e" rix,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_other_1.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_other_1.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION simple other flag test
|
||||
#=EXRESULT PASS
|
||||
|
||||
profile test {
|
||||
priority=-1 other /tmp/** rw,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_other_2.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_other_2.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION simple deny other flag test
|
||||
#=EXRESULT PASS
|
||||
|
||||
profile test {
|
||||
priority=-1 deny other /tmp/** rw,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/ok_other_3.sd
Normal file
7
parser/tst/simple_tests/file/priority/ok_other_3.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=DESCRIPTION simple other flag test
|
||||
#=EXRESULT PASS
|
||||
|
||||
profile test {
|
||||
priority=-1 audit other /tmp/** rw,
|
||||
}
|
9
parser/tst/simple_tests/file/priority/ok_quoted_1.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_quoted_1.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION simple quoted tab expansion
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 "/bin/alpha\tbeta" rix,
|
||||
}
|
||||
|
9
parser/tst/simple_tests/file/priority/ok_quoted_2.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_quoted_2.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION simple quoted newline expansion
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 "/bin/alpha\nbeta" rix,
|
||||
}
|
||||
|
9
parser/tst/simple_tests/file/priority/ok_quoted_3.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_quoted_3.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION simple quoted carriage return expansion
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 "/bin/alpha\rbeta" rix,
|
||||
}
|
||||
|
9
parser/tst/simple_tests/file/priority/ok_quoted_4.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_quoted_4.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION simple quoted quote expansion
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 "/bin/alpha\"beta" rix,
|
||||
}
|
||||
|
9
parser/tst/simple_tests/file/priority/ok_quoted_5.sd
Normal file
9
parser/tst/simple_tests/file/priority/ok_quoted_5.sd
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
#=DESCRIPTION simple quoted backslash expansion
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile test {
|
||||
priority=-1 "/bin/alpha\\beta" rix,
|
||||
}
|
||||
|
8
parser/tst/simple_tests/file/priority/ok_slashquote_1.sd
Normal file
8
parser/tst/simple_tests/file/priority/ok_slashquote_1.sd
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
#=DESCRIPTION unnecessary slash quotes are okay (should emit warning)
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
profile blart {
|
||||
priority=-1 /bingo/bang\o/bongo rw,
|
||||
}
|
7
parser/tst/simple_tests/file/priority/stacking_ok_1.sd
Normal file
7
parser/tst/simple_tests/file/priority/stacking_ok_1.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description basic file exec rule with stacking target
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/foo {
|
||||
priority=-1 /bin/bar px -> &baz,
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 audit deny link @{var} -> @{var},
|
||||
}
|
||||
|
10
parser/tst/simple_tests/file/priority/var1_ok_deny_link.sd
Normal file
10
parser/tst/simple_tests/file/priority/var1_ok_deny_link.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 deny link @{var} -> @{var},
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var1_ok_link_1.sd
Normal file
11
parser/tst/simple_tests/file/priority/var1_ok_link_1.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 @{var} rl,
|
||||
priority=-1 /gamma/* rwl,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var1_ok_link_2.sd
Normal file
11
parser/tst/simple_tests/file/priority/var1_ok_link_2.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 link @{var} -> @{var},
|
||||
priority=-1 @{var} r,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var1_ok_link_3.sd
Normal file
11
parser/tst/simple_tests/file/priority/var1_ok_link_3.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 link subset @{var} -> @{var},
|
||||
priority=-1 @{var} r,
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 audit deny link @{var} -> /tmp/**,
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 deny link @{var} -> /tmp/**,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var1_src_ok_link_1.sd
Normal file
11
parser/tst/simple_tests/file/priority/var1_src_ok_link_1.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 @{var} rl,
|
||||
priority=-1 /gamma/* rwl,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var1_src_ok_link_2.sd
Normal file
11
parser/tst/simple_tests/file/priority/var1_src_ok_link_2.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 link @{var} -> /tmp/**,
|
||||
priority=-1 /tmp/** r,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var1_src_ok_link_3.sd
Normal file
11
parser/tst/simple_tests/file/priority/var1_src_ok_link_3.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 link subset @{var} -> /tmp/**,
|
||||
/tmp/** r,
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 audit deny link /alpha/beta -> @{var},
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 deny link /alpha/beta -> @{var},
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 /alpha/beta rl,
|
||||
/gamma/* rwl,
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 link /alpha/beta -> @{var},
|
||||
priority=-1 @{var} r,
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 link subset /alpha/beta -> @{var},
|
||||
priority=-1 @{var} r,
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 audit deny link /foo@{var} -> /foo@{var},
|
||||
}
|
||||
|
10
parser/tst/simple_tests/file/priority/var2_ok_deny_link.sd
Normal file
10
parser/tst/simple_tests/file/priority/var2_ok_deny_link.sd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 deny link /foo@{var} -> /foo@{var},
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var2_ok_link_1.sd
Normal file
11
parser/tst/simple_tests/file/priority/var2_ok_link_1.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=11 /foo@{var} rl,
|
||||
/gamma/* rwl,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var2_ok_link_2.sd
Normal file
11
parser/tst/simple_tests/file/priority/var2_ok_link_2.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 link /foo@{var} -> /foo@{var},
|
||||
/foo@{var} r,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var2_ok_link_3.sd
Normal file
11
parser/tst/simple_tests/file/priority/var2_ok_link_3.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
priority=-1 link subset /foo@{var} -> /foo@{var},
|
||||
/foo@{var} r,
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
audit deny link /foo@{var} -> /tmp/**,
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
deny link /foo@{var} -> /tmp/**,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var2_src_ok_link_1.sd
Normal file
11
parser/tst/simple_tests/file/priority/var2_src_ok_link_1.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
/foo@{var} rl,
|
||||
/gamma/* rwl,
|
||||
}
|
||||
|
11
parser/tst/simple_tests/file/priority/var2_src_ok_link_2.sd
Normal file
11
parser/tst/simple_tests/file/priority/var2_src_ok_link_2.sd
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
#=DESCRIPTION simple link access test
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
|
||||
@{var}=/test
|
||||
profile test {
|
||||
link /foo@{var} -> /tmp/**,
|
||||
/tmp/** r,
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue