mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 00:14:44 +01:00
parser: minimization - remove unnecessary second minimization pass
Moving apply_and_clear_deny() before the first minimization pass, which was necessary to propperly support building accept information for older none extended permission dfas, allows us to also get rid of doing a second minimization pass if we want to force clearing explicit deny info from extended permission tables. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
1fa45b7c1f
commit
2737cb2c2b
21 changed files with 477 additions and 150 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,6 +651,12 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* minimize the number of dfa states */
|
||||
|
@ -1379,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();
|
||||
|
||||
|
@ -1393,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;
|
||||
|
@ -1407,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;
|
||||
|
@ -1415,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;
|
||||
}
|
||||
|
@ -1443,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 | 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@ struct cond_entry_list {
|
|||
};
|
||||
|
||||
struct cod_entry {
|
||||
int priority;
|
||||
char *name;
|
||||
union {
|
||||
char *link_name;
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1091,7 +1098,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, 0, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
|
||||
/* don't add mediated classes to unconfined profiles */
|
||||
|
@ -1099,35 +1106,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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, RULE_ALLOW, AA_MAY_READ, 0, parseopts) ||
|
||||
!prof->policy.rules->add_rule(mediates_net_unix, 0, 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, 0, 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, 0, 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, 0, RULE_ALLOW, AA_MAY_READ, 0, parseopts))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1136,11 +1143,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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,10 +82,11 @@ class rule_t {
|
|||
public:
|
||||
int rule_type;
|
||||
rule_flags_t flags;
|
||||
int priority;
|
||||
|
||||
rule_t *removed_by;
|
||||
|
||||
rule_t(int t): rule_type(t), flags(RULE_FLAG_NONE), removed_by(NULL) { }
|
||||
rule_t(int t): rule_type(t), flags(RULE_FLAG_NONE), priority(0), removed_by(NULL) { }
|
||||
virtual ~rule_t() { };
|
||||
|
||||
bool is_type(int type) { return rule_type == type; }
|
||||
|
@ -113,6 +114,9 @@ public:
|
|||
virtual int expand_variables(void) = 0;
|
||||
|
||||
virtual int cmp(rule_t const &rhs) const {
|
||||
int tmp = priority - rhs.priority;
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
return rule_type - rhs.rule_type;
|
||||
}
|
||||
virtual bool operator<(rule_t const &rhs) const {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 6 ] ; 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
|
||||
|
|
|
@ -95,7 +95,8 @@ int userns_rule::gen_policy_re(Profile &prof)
|
|||
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NS;
|
||||
buf = buffer.str();
|
||||
if (perms & AA_VALID_USERNS_PERMS) {
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms,
|
||||
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||
rule_mode, perms,
|
||||
audit == AUDIT_FORCE ? perms : 0,
|
||||
parseopts))
|
||||
goto fail;
|
||||
|
|
Loading…
Add table
Reference in a new issue