mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +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);
|
write_to_prot(buffer);
|
||||||
if ((mask & AA_NET_CREATE) && !has_peer_conds()) {
|
if ((mask & AA_NET_CREATE) && !has_peer_conds()) {
|
||||||
buf = buffer.str();
|
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(AA_NET_CREATE),
|
||||||
map_perms(audit == AUDIT_FORCE ? AA_NET_CREATE : 0),
|
map_perms(audit == AUDIT_FORCE ? AA_NET_CREATE : 0),
|
||||||
parseopts))
|
parseopts))
|
||||||
|
@ -369,7 +370,8 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
tmp << "\\x00";
|
tmp << "\\x00";
|
||||||
|
|
||||||
buf = tmp.str();
|
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(AA_NET_BIND),
|
||||||
map_perms(audit == AUDIT_FORCE ? AA_NET_BIND : 0),
|
map_perms(audit == AUDIT_FORCE ? AA_NET_BIND : 0),
|
||||||
parseopts))
|
parseopts))
|
||||||
|
@ -394,7 +396,8 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
AA_LOCAL_NET_PERMS & ~AA_LOCAL_NET_CMD;
|
AA_LOCAL_NET_PERMS & ~AA_LOCAL_NET_CMD;
|
||||||
if (mask & local_mask) {
|
if (mask & local_mask) {
|
||||||
buf = buffer.str();
|
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(mask & local_mask),
|
||||||
map_perms(audit == AUDIT_FORCE ? mask & local_mask : 0),
|
map_perms(audit == AUDIT_FORCE ? mask & local_mask : 0),
|
||||||
parseopts))
|
parseopts))
|
||||||
|
@ -408,7 +411,9 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
/* TODO: backlog conditional: for now match anything*/
|
/* TODO: backlog conditional: for now match anything*/
|
||||||
tmp << "..";
|
tmp << "..";
|
||||||
buf = tmp.str();
|
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(AA_NET_LISTEN),
|
||||||
map_perms(audit == AUDIT_FORCE ? AA_NET_LISTEN : 0),
|
map_perms(audit == AUDIT_FORCE ? AA_NET_LISTEN : 0),
|
||||||
parseopts))
|
parseopts))
|
||||||
|
@ -422,6 +427,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
tmp << "..";
|
tmp << "..";
|
||||||
buf = tmp.str();
|
buf = tmp.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(),
|
if (!prof.policy.rules->add_rule(buf.c_str(),
|
||||||
|
priority,
|
||||||
rule_mode,
|
rule_mode,
|
||||||
map_perms(mask & AA_NET_OPT),
|
map_perms(mask & AA_NET_OPT),
|
||||||
map_perms(audit == AUDIT_FORCE ?
|
map_perms(audit == AUDIT_FORCE ?
|
||||||
|
@ -444,7 +450,10 @@ int unix_rule::gen_policy_re(Profile &prof)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
buf = buffer.str();
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -274,23 +274,24 @@ int dbus_rule::gen_policy_re(Profile &prof)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perms & AA_DBUS_BIND) {
|
if (perms & AA_DBUS_BIND) {
|
||||||
if (!prof.policy.rules->add_rule_vec(rule_mode, perms & AA_DBUS_BIND,
|
if (!prof.policy.rules->add_rule_vec(priority, rule_mode,
|
||||||
audit == AUDIT_FORCE ? perms & AA_DBUS_BIND : 0,
|
perms & AA_DBUS_BIND,
|
||||||
2, vec, parseopts, false))
|
audit == AUDIT_FORCE ? perms & AA_DBUS_BIND : 0,
|
||||||
|
2, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
|
if (perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
|
||||||
if (!prof.policy.rules->add_rule_vec(rule_mode,
|
if (!prof.policy.rules->add_rule_vec(priority, rule_mode,
|
||||||
perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
|
perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
|
||||||
audit == AUDIT_FORCE ? perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE) : 0,
|
audit == AUDIT_FORCE ? perms & (AA_DBUS_SEND | AA_DBUS_RECEIVE) : 0,
|
||||||
6, vec, parseopts, false))
|
6, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (perms & AA_DBUS_EAVESDROP) {
|
if (perms & AA_DBUS_EAVESDROP) {
|
||||||
if (!prof.policy.rules->add_rule_vec(rule_mode,
|
if (!prof.policy.rules->add_rule_vec(priority, rule_mode,
|
||||||
perms & AA_DBUS_EAVESDROP,
|
perms & AA_DBUS_EAVESDROP,
|
||||||
audit == AUDIT_FORCE ? perms & AA_DBUS_EAVESDROP : 0,
|
audit == AUDIT_FORCE ? perms & AA_DBUS_EAVESDROP : 0,
|
||||||
1, vec, parseopts, false))
|
1, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,16 +122,18 @@ int io_uring_rule::gen_policy_re(Profile &prof)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perms & AA_VALID_IO_URING_PERMS) {
|
if (perms & AA_VALID_IO_URING_PERMS) {
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms,
|
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||||
audit == AUDIT_FORCE ? perms : 0,
|
rule_mode, perms,
|
||||||
parseopts))
|
audit == AUDIT_FORCE ? perms : 0,
|
||||||
|
parseopts))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (perms & AA_IO_URING_OVERRIDE_CREDS) {
|
if (perms & AA_IO_URING_OVERRIDE_CREDS) {
|
||||||
buf = buffer.str(); /* update buf to have label */
|
buf = buffer.str(); /* update buf to have label */
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode,
|
if (!prof.policy.rules->add_rule(buf.c_str(),
|
||||||
perms, audit == AUDIT_FORCE ? perms : 0,
|
priority, rule_mode,
|
||||||
parseopts))
|
perms, audit == AUDIT_FORCE ? perms : 0,
|
||||||
|
parseopts))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,10 +44,11 @@ aare_rules::~aare_rules(void)
|
||||||
expr_map.clear();
|
expr_map.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool aare_rules::add_rule(const char *rule, rule_mode_t mode, perm32_t perms,
|
bool aare_rules::add_rule(const char *rule, int priority, rule_mode_t mode,
|
||||||
perm32_t audit, optflags const &opts)
|
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)
|
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);
|
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,
|
bool aare_rules::add_rule_vec(int priority, rule_mode_t mode, perm32_t perms,
|
||||||
int count, const char **rulev, optflags const &opts,
|
perm32_t audit, int count, const char **rulev,
|
||||||
bool oob)
|
optflags const &opts, bool oob)
|
||||||
{
|
{
|
||||||
Node *tree = NULL, *accept;
|
Node *tree = NULL, *accept;
|
||||||
int exact_match;
|
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)
|
if (reverse)
|
||||||
flip_tree(tree);
|
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) {
|
if (opts.dump & DUMP_DFA_RULE_EXPR) {
|
||||||
const char *separator;
|
const char *separator;
|
||||||
|
@ -124,6 +125,7 @@ bool aare_rules::add_rule_vec(rule_mode_t mode, perm32_t perms, perm32_t audit,
|
||||||
cerr << " -> ";
|
cerr << " -> ";
|
||||||
tree->dump(cerr);
|
tree->dump(cerr);
|
||||||
// TODO: split out from prefixes class
|
// TODO: split out from prefixes class
|
||||||
|
cerr << " priority=" << priority;
|
||||||
if (mode == RULE_DENY)
|
if (mode == RULE_DENY)
|
||||||
cerr << " deny";
|
cerr << " deny";
|
||||||
else if (mode == RULE_PROMPT)
|
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)
|
if (opts.dump & DUMP_DFA_UNIQ_PERMS)
|
||||||
dfa.dump_uniq_perms("dfa");
|
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) {
|
if (opts.control & CONTROL_DFA_MINIMIZE) {
|
||||||
dfa.minimize(opts);
|
dfa.minimize(opts);
|
||||||
|
|
||||||
|
@ -263,22 +279,6 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
||||||
dfa.dump_uniq_perms("minimized dfa");
|
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)
|
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE)
|
||||||
dfa.remove_unreachable(opts);
|
dfa.remove_unreachable(opts);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
class UniquePerm {
|
class UniquePerm {
|
||||||
public:
|
public:
|
||||||
|
int priority;
|
||||||
rule_mode_t mode;
|
rule_mode_t mode;
|
||||||
bool exact_match;
|
bool exact_match;
|
||||||
uint32_t perms;
|
uint32_t perms;
|
||||||
|
@ -42,6 +43,8 @@ public:
|
||||||
|
|
||||||
bool operator<(UniquePerm const &rhs)const
|
bool operator<(UniquePerm const &rhs)const
|
||||||
{
|
{
|
||||||
|
if (priority < rhs.priority)
|
||||||
|
return priority < rhs.priority;
|
||||||
if (mode >= rhs.mode) {
|
if (mode >= rhs.mode) {
|
||||||
if (exact_match == rhs.exact_match) {
|
if (exact_match == rhs.exact_match) {
|
||||||
if (perms == rhs.perms)
|
if (perms == rhs.perms)
|
||||||
|
@ -71,21 +74,21 @@ public:
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *insert(rule_mode_t mode, uint32_t perms, uint32_t audit,
|
Node *insert(int priority, rule_mode_t mode, uint32_t perms,
|
||||||
bool exact_match)
|
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);
|
iterator res = nodes.find(tmp);
|
||||||
if (res == nodes.end()) {
|
if (res == nodes.end()) {
|
||||||
Node *node;
|
Node *node;
|
||||||
if (mode == RULE_DENY)
|
if (mode == RULE_DENY)
|
||||||
node = new DenyMatchFlag(perms, audit);
|
node = new DenyMatchFlag(priority, perms, audit);
|
||||||
else if (mode == RULE_PROMPT)
|
else if (mode == RULE_PROMPT)
|
||||||
node = new PromptMatchFlag(perms, audit);
|
node = new PromptMatchFlag(priority, perms, audit);
|
||||||
else if (exact_match)
|
else if (exact_match)
|
||||||
node = new ExactMatchFlag(perms, audit);
|
node = new ExactMatchFlag(priority, perms, audit);
|
||||||
else
|
else
|
||||||
node = new MatchFlag(perms, audit);
|
node = new MatchFlag(priority, perms, audit);
|
||||||
pair<iterator, bool> val = nodes.insert(make_pair(tmp, node));
|
pair<iterator, bool> val = nodes.insert(make_pair(tmp, node));
|
||||||
if (val.second == false)
|
if (val.second == false)
|
||||||
return val.first->second;
|
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(int reverse): root(NULL), unique_perms(), expr_map(), reverse(reverse), rule_count(0) { };
|
||||||
~aare_rules();
|
~aare_rules();
|
||||||
|
|
||||||
bool add_rule(const char *rule, rule_mode_t mode, perm32_t perms,
|
bool add_rule(const char *rule, int priority, rule_mode_t mode,
|
||||||
perm32_t audit, optflags const &opts);
|
perm32_t perms, perm32_t audit, optflags const &opts);
|
||||||
bool add_rule_vec(rule_mode_t mode, perm32_t perms, perm32_t audit,
|
bool add_rule_vec(int priority, rule_mode_t mode, perm32_t perms,
|
||||||
int count, const char **rulev, optflags const &opts,
|
perm32_t audit, int count, const char **rulev,
|
||||||
bool oob);
|
optflags const &opts, bool oob);
|
||||||
bool append_rule(const char *rule, bool oob, bool with_perm, optflags const &opts);
|
bool append_rule(const char *rule, bool oob, bool with_perm, optflags const &opts);
|
||||||
CHFA *create_chfa(int *min_match_len,
|
CHFA *create_chfa(int *min_match_len,
|
||||||
vector <aa_perms> &perms_table,
|
vector <aa_perms> &perms_table,
|
||||||
|
|
|
@ -886,19 +886,20 @@ public:
|
||||||
|
|
||||||
class MatchFlag: public AcceptNode {
|
class MatchFlag: public AcceptNode {
|
||||||
public:
|
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;
|
type_flags |= NODE_TYPE_MATCHFLAG;
|
||||||
}
|
}
|
||||||
ostream &dump(ostream &os) { return os << "< 0x" << hex << perms << '>'; }
|
ostream &dump(ostream &os) { return os << "< 0x" << hex << perms << '>'; }
|
||||||
|
|
||||||
|
int priority;
|
||||||
perm32_t perms;
|
perm32_t perms;
|
||||||
perm32_t audit;
|
perm32_t audit;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExactMatchFlag: public MatchFlag {
|
class ExactMatchFlag: public MatchFlag {
|
||||||
public:
|
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;
|
type_flags |= NODE_TYPE_EXACTMATCHFLAG;
|
||||||
}
|
}
|
||||||
|
@ -906,7 +907,7 @@ public:
|
||||||
|
|
||||||
class DenyMatchFlag: public MatchFlag {
|
class DenyMatchFlag: public MatchFlag {
|
||||||
public:
|
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;
|
type_flags |= NODE_TYPE_DENYMATCHFLAG;
|
||||||
}
|
}
|
||||||
|
@ -914,7 +915,7 @@ public:
|
||||||
|
|
||||||
class PromptMatchFlag: public MatchFlag {
|
class PromptMatchFlag: public MatchFlag {
|
||||||
public:
|
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();
|
nnodes_cache.clear();
|
||||||
node_map.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()
|
DFA::~DFA()
|
||||||
|
@ -646,6 +651,12 @@ int DFA::apply_and_clear_deny(void)
|
||||||
return c;
|
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 */
|
/* 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 accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
perm32_t exact_match_allow = 0;
|
perms_t exact;
|
||||||
perm32_t exact_match_prompt = 0;
|
|
||||||
perm32_t exact_audit = 0;
|
|
||||||
|
|
||||||
perms.clear();
|
perms.clear();
|
||||||
|
|
||||||
|
@ -1393,13 +1402,20 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MatchFlag *match = static_cast<MatchFlag *>(*i);
|
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)) {
|
if (match->is_type(NODE_TYPE_EXACTMATCHFLAG)) {
|
||||||
/* exact match only ever happens with x */
|
/* exact match only ever happens with x */
|
||||||
if (filedfa && !is_merged_x_consistent(exact_match_allow,
|
if (filedfa &&
|
||||||
match->perms))
|
!is_merged_x_consistent(exact.allow, match->perms))
|
||||||
error = 1;;
|
error = 1;
|
||||||
exact_match_allow |= match->perms;
|
exact.allow |= match->perms;
|
||||||
exact_audit |= match->audit;
|
exact.audit |= match->audit;
|
||||||
} else if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) {
|
} else if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) {
|
||||||
perms.deny |= match->perms;
|
perms.deny |= match->perms;
|
||||||
perms.quiet |= match->audit;
|
perms.quiet |= match->audit;
|
||||||
|
@ -1407,7 +1423,8 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
||||||
perms.prompt |= match->perms;
|
perms.prompt |= match->perms;
|
||||||
perms.audit |= match->audit;
|
perms.audit |= match->audit;
|
||||||
} else {
|
} else {
|
||||||
if (filedfa && !is_merged_x_consistent(perms.allow, match->perms))
|
if (filedfa &&
|
||||||
|
!is_merged_x_consistent(perms.allow, match->perms))
|
||||||
error = 1;
|
error = 1;
|
||||||
perms.allow |= match->perms;
|
perms.allow |= match->perms;
|
||||||
perms.audit |= match->audit;
|
perms.audit |= match->audit;
|
||||||
|
@ -1415,21 +1432,21 @@ int accept_perms(NodeVec *state, perms_t &perms, bool filedfa)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filedfa) {
|
if (filedfa) {
|
||||||
perms.allow |= exact_match_allow & ~(ALL_AA_EXEC_TYPE);
|
perms.allow |= exact.allow & ~(ALL_AA_EXEC_TYPE);
|
||||||
perms.prompt |= exact_match_prompt & ~(ALL_AA_EXEC_TYPE);
|
perms.prompt |= exact.prompt & ~(ALL_AA_EXEC_TYPE);
|
||||||
perms.audit |= exact_audit & ~(ALL_AA_EXEC_TYPE);
|
perms.audit |= exact.audit & ~(ALL_AA_EXEC_TYPE);
|
||||||
} else {
|
} else {
|
||||||
perms.allow |= exact_match_allow;
|
perms.allow |= exact.allow;
|
||||||
perms.prompt |= exact_match_prompt;
|
perms.prompt |= exact.prompt;
|
||||||
perms.audit |= exact_audit;
|
perms.audit |= exact.audit;
|
||||||
}
|
}
|
||||||
if (exact_match_allow & AA_USER_EXEC) {
|
if (exact.allow & AA_USER_EXEC) {
|
||||||
perms.allow = (exact_match_allow & AA_USER_EXEC_TYPE) |
|
perms.allow = (exact.allow & AA_USER_EXEC_TYPE) |
|
||||||
(perms.allow & ~AA_USER_EXEC_TYPE);
|
(perms.allow & ~AA_USER_EXEC_TYPE);
|
||||||
perms.exact = AA_USER_EXEC_TYPE;
|
perms.exact = AA_USER_EXEC_TYPE;
|
||||||
}
|
}
|
||||||
if (exact_match_allow & AA_OTHER_EXEC) {
|
if (exact.allow & AA_OTHER_EXEC) {
|
||||||
perms.allow = (exact_match_allow & AA_OTHER_EXEC_TYPE) |
|
perms.allow = (exact.allow & AA_OTHER_EXEC_TYPE) |
|
||||||
(perms.allow & ~AA_OTHER_EXEC_TYPE);
|
(perms.allow & ~AA_OTHER_EXEC_TYPE);
|
||||||
perms.exact |= 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.quiet &= perms.deny;
|
||||||
perms.prompt &= ~perms.deny;
|
perms.prompt &= ~perms.deny;
|
||||||
perms.prompt &= ~perms.allow;
|
perms.prompt &= ~perms.allow;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
fprintf(stderr, "profile has merged rule with conflicting x modifiers\n");
|
fprintf(stderr, "profile has merged rule with conflicting x modifiers\n");
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "expr-tree.h"
|
#include "expr-tree.h"
|
||||||
|
@ -51,24 +52,37 @@ ostream &operator<<(ostream &os, State &state);
|
||||||
|
|
||||||
class perms_t {
|
class perms_t {
|
||||||
public:
|
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); }
|
bool is_accept(void) { return (allow | deny | prompt | audit | quiet); }
|
||||||
|
|
||||||
void dump_header(ostream &os)
|
void dump_header(ostream &os)
|
||||||
{
|
{
|
||||||
os << "(allow/deny/prompt/audit/quiet)";
|
os << "priority (allow/deny/prompt/audit/quiet)";
|
||||||
}
|
}
|
||||||
void dump(ostream &os)
|
void dump(ostream &os)
|
||||||
{
|
{
|
||||||
os << " (0x " << hex
|
os << " " << priority << " (0x " << hex
|
||||||
<< allow << "/" << deny << "/" << "/" << prompt << "/" << audit << "/" << quiet
|
<< allow << "/" << deny << "/" << "/" << prompt << "/" << audit << "/" << quiet
|
||||||
<< ')' << dec;
|
<< ')' << 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)
|
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;
|
deny |= rhs.deny;
|
||||||
|
|
||||||
if (filedfa && !is_merged_x_consistent(allow & ALL_USER_EXEC,
|
if (filedfa && !is_merged_x_consistent(allow & ALL_USER_EXEC,
|
||||||
|
@ -131,6 +145,8 @@ public:
|
||||||
|
|
||||||
bool operator<(perms_t const &rhs)const
|
bool operator<(perms_t const &rhs)const
|
||||||
{
|
{
|
||||||
|
if (priority < rhs.priority)
|
||||||
|
return priority < rhs.priority;
|
||||||
if (allow < rhs.allow)
|
if (allow < rhs.allow)
|
||||||
return allow < rhs.allow;
|
return allow < rhs.allow;
|
||||||
if (deny < rhs.deny)
|
if (deny < rhs.deny)
|
||||||
|
@ -142,6 +158,7 @@ public:
|
||||||
return quiet < rhs.quiet;
|
return quiet < rhs.quiet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int priority;
|
||||||
perm32_t allow, deny, prompt, audit, quiet, exact;
|
perm32_t allow, deny, prompt, audit, quiet, exact;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -351,6 +368,7 @@ public:
|
||||||
bool same_mappings(State *s1, State *s2);
|
bool same_mappings(State *s1, State *s2);
|
||||||
void minimize(optflags const &flags);
|
void minimize(optflags const &flags);
|
||||||
int apply_and_clear_deny(void);
|
int apply_and_clear_deny(void);
|
||||||
|
void clear_priorities(void);
|
||||||
|
|
||||||
void diff_encode(optflags const &flags);
|
void diff_encode(optflags const &flags);
|
||||||
void undiff_encode(void);
|
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
|
* if a data match is required this only has AA_MATCH_CONT perms
|
||||||
* else it has full perms
|
* else it has full perms
|
||||||
*/
|
*/
|
||||||
if (!prof.policy.rules->add_rule_vec(rule_mode, tmpperms, tmpaudit, 4,
|
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, tmpperms,
|
||||||
vec, parseopts, false))
|
tmpaudit, 4, vec, parseopts,
|
||||||
|
false))
|
||||||
goto fail;
|
goto fail;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
@ -808,7 +809,7 @@ int mnt_rule::gen_policy_remount(Profile &prof, int &count,
|
||||||
if (!build_mnt_opts(optsbuf, opts))
|
if (!build_mnt_opts(optsbuf, opts))
|
||||||
goto fail;
|
goto fail;
|
||||||
vec[4] = optsbuf.c_str();
|
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),
|
(audit == AUDIT_FORCE ? perms : 0),
|
||||||
5, vec, parseopts, false))
|
5, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -850,7 +851,8 @@ int mnt_rule::gen_policy_bind_mount(Profile &prof, int &count,
|
||||||
opt_flags & MS_BIND_FLAGS))
|
opt_flags & MS_BIND_FLAGS))
|
||||||
goto fail;
|
goto fail;
|
||||||
vec[3] = flagsbuf;
|
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,
|
4, vec,
|
||||||
parseopts, false))
|
parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -907,7 +909,8 @@ int mnt_rule::gen_policy_change_mount_type(Profile &prof, int &count,
|
||||||
opt_flags & MS_MAKE_FLAGS))
|
opt_flags & MS_MAKE_FLAGS))
|
||||||
goto fail;
|
goto fail;
|
||||||
vec[3] = flagsbuf;
|
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,
|
4, vec,
|
||||||
parseopts, false))
|
parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -950,7 +953,8 @@ int mnt_rule::gen_policy_move_mount(Profile &prof, int &count,
|
||||||
opt_flags & MS_MOVE_FLAGS))
|
opt_flags & MS_MOVE_FLAGS))
|
||||||
goto fail;
|
goto fail;
|
||||||
vec[3] = flagsbuf;
|
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,
|
4, vec,
|
||||||
parseopts, false))
|
parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1002,8 +1006,9 @@ int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
|
||||||
tmpaudit = audit == AUDIT_FORCE ? perms : 0;
|
tmpaudit = audit == AUDIT_FORCE ? perms : 0;
|
||||||
}
|
}
|
||||||
/* rule for match without required data || data MATCH_CONT */
|
/* rule for match without required data || data MATCH_CONT */
|
||||||
if (!prof.policy.rules->add_rule_vec(rule_mode, tmpperms, tmpaudit, 4,
|
if (!prof.policy.rules->add_rule_vec(priority, rule_mode, tmpperms,
|
||||||
vec, parseopts, false))
|
tmpaudit, 4, vec, parseopts,
|
||||||
|
false))
|
||||||
goto fail;
|
goto fail;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
@ -1013,7 +1018,7 @@ int mnt_rule::gen_policy_new_mount(Profile &prof, int &count,
|
||||||
if (!build_mnt_opts(optsbuf, opts))
|
if (!build_mnt_opts(optsbuf, opts))
|
||||||
goto fail;
|
goto fail;
|
||||||
vec[4] = optsbuf.c_str();
|
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,
|
audit == AUDIT_FORCE ? perms : 0,
|
||||||
5, vec, parseopts, false))
|
5, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1105,7 +1110,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
||||||
if (!convert_entry(mntbuf, mnt_point))
|
if (!convert_entry(mntbuf, mnt_point))
|
||||||
goto fail;
|
goto fail;
|
||||||
vec[0] = mntbuf.c_str();
|
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,
|
(audit == AUDIT_FORCE ? perms : 0), 1, vec,
|
||||||
parseopts, false))
|
parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1120,7 +1125,7 @@ int mnt_rule::gen_policy_re(Profile &prof)
|
||||||
if (!clear_and_convert_entry(devbuf, device))
|
if (!clear_and_convert_entry(devbuf, device))
|
||||||
goto fail;
|
goto fail;
|
||||||
vec[1] = devbuf.c_str();
|
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,
|
(audit == AUDIT_FORCE ? perms : 0), 2, vec,
|
||||||
parseopts, false))
|
parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -231,10 +231,19 @@ int mqueue_rule::gen_policy_re(Profile &prof)
|
||||||
/* store perms at name match so label doesn't need
|
/* store perms at name match so label doesn't need
|
||||||
* to be checked
|
* 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;
|
goto fail;
|
||||||
/* also provide label match with perm */
|
/* 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;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,10 +275,19 @@ int mqueue_rule::gen_policy_re(Profile &prof)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perms & AA_VALID_SYSV_MQ_PERMS) {
|
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;
|
goto fail;
|
||||||
/* also provide label match with perm */
|
/* 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;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -697,7 +697,8 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
|
||||||
|
|
||||||
buf = oss.str();
|
buf = oss.str();
|
||||||
/* AA_CONT_MATCH mapping (cond_perms) only applies to perms, not audit */
|
/* 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,
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
return false;
|
return false;
|
||||||
|
@ -710,7 +711,8 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
|
||||||
oss << "\\x00"; /* null transition */
|
oss << "\\x00"; /* null transition */
|
||||||
|
|
||||||
buf = oss.str();
|
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,
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
return false;
|
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)) {
|
if (!features_supports_inet || (family != AF_INET && family != AF_INET6)) {
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
|
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
rule_mode, map_perms(perms),
|
||||||
parseopts))
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
|
parseopts))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -745,7 +748,8 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
/* create perms need to be generated excluding the rest of the perms */
|
/* create perms need to be generated excluding the rest of the perms */
|
||||||
if (perms & AA_NET_CREATE) {
|
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,
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms & AA_NET_CREATE) : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
return false;
|
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 */
|
/* length of queue allowed - not used for now */
|
||||||
listen_buffer << "..";
|
listen_buffer << "..";
|
||||||
buf = listen_buffer.str();
|
buf = listen_buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
|
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
rule_mode, map_perms(perms),
|
||||||
parseopts))
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
|
parseopts))
|
||||||
return false;
|
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 */
|
/* socket mapping - not used for now */
|
||||||
opt_buffer << "..";
|
opt_buffer << "..";
|
||||||
buf = opt_buffer.str();
|
buf = opt_buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, map_perms(perms),
|
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
rule_mode, map_perms(perms),
|
||||||
parseopts))
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
|
parseopts))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@ struct cond_entry_list {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cod_entry {
|
struct cod_entry {
|
||||||
|
int priority;
|
||||||
char *name;
|
char *name;
|
||||||
union {
|
union {
|
||||||
char *link_name;
|
char *link_name;
|
||||||
|
|
|
@ -984,6 +984,7 @@ struct cod_entry *new_entry(char *id, perm32_t perms, char *link_id)
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
entry->priority = 0;
|
||||||
entry->name = id;
|
entry->name = id;
|
||||||
entry->link_name = link_id;
|
entry->link_name = link_id;
|
||||||
entry->perms = perms;
|
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, name, err);
|
||||||
DUP_STRING(orig, entry, link_name, err);
|
DUP_STRING(orig, entry, link_name, err);
|
||||||
DUP_STRING(orig, entry, nt_name, err);
|
DUP_STRING(orig, entry, nt_name, err);
|
||||||
|
entry->priority = orig->priority;
|
||||||
entry->perms = orig->perms;
|
entry->perms = orig->perms;
|
||||||
entry->audit = orig->audit;
|
entry->audit = orig->audit;
|
||||||
entry->rule_mode = orig->rule_mode;
|
entry->rule_mode = orig->rule_mode;
|
||||||
|
|
|
@ -507,7 +507,7 @@ static int process_profile_name_xmatch(Profile *prof)
|
||||||
aare_rules *rules = new aare_rules();
|
aare_rules *rules = new aare_rules();
|
||||||
if (!rules)
|
if (!rules)
|
||||||
return FALSE;
|
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)) {
|
AA_MAY_EXEC, 0, parseopts)) {
|
||||||
delete rules;
|
delete rules;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -521,7 +521,7 @@ static int process_profile_name_xmatch(Profile *prof)
|
||||||
ptype = convert_aaregex_to_pcre(alt->name, 0,
|
ptype = convert_aaregex_to_pcre(alt->name, 0,
|
||||||
glob_default,
|
glob_default,
|
||||||
tbuf, &len);
|
tbuf, &len);
|
||||||
if (!rules->add_rule(tbuf.c_str(),
|
if (!rules->add_rule(tbuf.c_str(), 0,
|
||||||
RULE_ALLOW, AA_MAY_EXEC,
|
RULE_ALLOW, AA_MAY_EXEC,
|
||||||
0, parseopts)) {
|
0, parseopts)) {
|
||||||
delete rules;
|
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->rule_mode == RULE_DENY) {
|
||||||
if ((entry->perms & ~AA_LINK_BITS) &&
|
if ((entry->perms & ~AA_LINK_BITS) &&
|
||||||
!is_change_profile_perms(entry->perms) &&
|
!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->perms & ~(AA_LINK_BITS | AA_CHANGE_PROFILE),
|
||||||
entry->audit == AUDIT_FORCE ? entry->perms & ~(AA_LINK_BITS | AA_CHANGE_PROFILE) : 0,
|
entry->audit == AUDIT_FORCE ? entry->perms & ~(AA_LINK_BITS | AA_CHANGE_PROFILE) : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} else if (!is_change_profile_perms(entry->perms)) {
|
} 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->rule_mode, entry->perms,
|
||||||
entry->audit == AUDIT_FORCE ? entry->perms : 0,
|
entry->audit == AUDIT_FORCE ? entry->perms : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
|
@ -676,7 +677,10 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
||||||
perms |= LINK_TO_LINK_SUBSET(perms);
|
perms |= LINK_TO_LINK_SUBSET(perms);
|
||||||
vec[1] = "/[^/].*";
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (is_change_profile_perms(entry->perms)) {
|
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 */
|
/* 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,
|
AA_CHANGE_PROFILE | onexec_perms,
|
||||||
0, index - 1, &vec[1], parseopts, false))
|
0, index - 1, &vec[1], parseopts, false))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* onexec rules - both rules are needed for onexec */
|
/* 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))
|
0, 1, vec, parseopts, false))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -742,8 +747,9 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
||||||
* unsafe exec transitions
|
* unsafe exec transitions
|
||||||
*/
|
*/
|
||||||
onexec_perms |= (entry->perms & (AA_EXEC_BITS | ALL_AA_EXEC_UNSAFE));
|
onexec_perms |= (entry->perms & (AA_EXEC_BITS | ALL_AA_EXEC_UNSAFE));
|
||||||
if (!dfarules->add_rule_vec(entry->rule_mode, onexec_perms,
|
if (!dfarules->add_rule_vec(entry->priority, entry->rule_mode,
|
||||||
0, index, vec, parseopts, false))
|
onexec_perms, 0, index, vec,
|
||||||
|
parseopts, false))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
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);
|
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (type_mask & 0xff);
|
||||||
}
|
}
|
||||||
buf = buffer.str();
|
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,
|
audit ? map_perms(AA_VALID_NET_PERMS) : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1091,7 +1098,7 @@ int process_profile_policydb(Profile *prof)
|
||||||
* to be supported
|
* to be supported
|
||||||
*/
|
*/
|
||||||
if (features_supports_userns &&
|
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;
|
goto out;
|
||||||
|
|
||||||
/* don't add mediated classes to unconfined profiles */
|
/* don't add mediated classes to unconfined profiles */
|
||||||
|
@ -1099,35 +1106,35 @@ int process_profile_policydb(Profile *prof)
|
||||||
prof->flags.mode != MODE_DEFAULT_ALLOW) {
|
prof->flags.mode != MODE_DEFAULT_ALLOW) {
|
||||||
/* note: this activates fs based unix domain sockets mediation on connect */
|
/* note: this activates fs based unix domain sockets mediation on connect */
|
||||||
if (kernel_abi_version > 5 &&
|
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;
|
goto out;
|
||||||
if (features_supports_mount &&
|
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;
|
goto out;
|
||||||
if (features_supports_dbus &&
|
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;
|
goto out;
|
||||||
if (features_supports_signal &&
|
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;
|
goto out;
|
||||||
if (features_supports_ptrace &&
|
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;
|
goto out;
|
||||||
if (features_supports_networkv8 &&
|
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;
|
goto out;
|
||||||
if (features_supports_unix &&
|
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_extended_net, 0, 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_net_unix, 0, RULE_ALLOW, AA_MAY_READ, 0, parseopts)))
|
||||||
goto out;
|
goto out;
|
||||||
if (features_supports_posix_mqueue &&
|
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;
|
goto out;
|
||||||
if (features_supports_sysv_mqueue &&
|
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;
|
goto out;
|
||||||
if (features_supports_io_uring &&
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1136,11 +1143,11 @@ int process_profile_policydb(Profile *prof)
|
||||||
// This requires file rule processing happen first
|
// This requires file rule processing happen first
|
||||||
if (!prof->dfa.rules->rule_count) {
|
if (!prof->dfa.rules->rule_count) {
|
||||||
// add null dfa
|
// 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;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!prof->policy.rules->rule_count) {
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
int xmatch_len = 0;
|
int xmatch_len = 0;
|
||||||
|
|
|
@ -133,9 +133,10 @@ int ptrace_rule::gen_policy_re(Profile &prof)
|
||||||
|
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (perms & AA_VALID_PTRACE_PERMS) {
|
if (perms & AA_VALID_PTRACE_PERMS) {
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode, perms,
|
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||||
audit == AUDIT_FORCE ? perms : 0,
|
rule_mode, perms,
|
||||||
parseopts))
|
audit == AUDIT_FORCE ? perms : 0,
|
||||||
|
parseopts))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,10 +82,11 @@ class rule_t {
|
||||||
public:
|
public:
|
||||||
int rule_type;
|
int rule_type;
|
||||||
rule_flags_t flags;
|
rule_flags_t flags;
|
||||||
|
int priority;
|
||||||
|
|
||||||
rule_t *removed_by;
|
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() { };
|
virtual ~rule_t() { };
|
||||||
|
|
||||||
bool is_type(int type) { return rule_type == type; }
|
bool is_type(int type) { return rule_type == type; }
|
||||||
|
@ -113,6 +114,9 @@ public:
|
||||||
virtual int expand_variables(void) = 0;
|
virtual int expand_variables(void) = 0;
|
||||||
|
|
||||||
virtual int cmp(rule_t const &rhs) const {
|
virtual int cmp(rule_t const &rhs) const {
|
||||||
|
int tmp = priority - rhs.priority;
|
||||||
|
if (tmp != 0)
|
||||||
|
return tmp;
|
||||||
return rule_type - rhs.rule_type;
|
return rule_type - rhs.rule_type;
|
||||||
}
|
}
|
||||||
virtual bool operator<(rule_t const &rhs) const {
|
virtual bool operator<(rule_t const &rhs) const {
|
||||||
|
|
|
@ -316,7 +316,8 @@ int signal_rule::gen_policy_re(Profile &prof)
|
||||||
|
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (perms & (AA_MAY_SEND | AA_MAY_RECEIVE)) {
|
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,
|
perms, audit == AUDIT_FORCE ? perms : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
goto fail;
|
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)
|
# {a} (0x 40030/0/0/0)
|
||||||
|
|
||||||
echo -n "Minimize profiles basic perms "
|
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"
|
echo "failed"
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
@ -93,7 +93,7 @@ echo "ok"
|
||||||
# {9} (0x 12804a/0/2800a/0)
|
# {9} (0x 12804a/0/2800a/0)
|
||||||
# {c} (0x 40030/0/0/0)
|
# {c} (0x 40030/0/0/0)
|
||||||
echo -n "Minimize profiles audit perms "
|
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"
|
echo "failed"
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
@ -112,7 +112,7 @@ echo "ok"
|
||||||
# {c} (0x 40030/0/0/0)
|
# {c} (0x 40030/0/0/0)
|
||||||
|
|
||||||
echo -n "Minimize profiles deny perms "
|
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"
|
echo "failed"
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
@ -130,13 +130,59 @@ echo "ok"
|
||||||
# {c} (0x 40030/0/0/0)
|
# {c} (0x 40030/0/0/0)
|
||||||
|
|
||||||
echo -n "Minimize profiles audit deny perms "
|
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"
|
echo "failed"
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
echo "ok"
|
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
|
# 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
|
# 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.
|
# 3rd is a generic permission that should be overridden during dfa creation.
|
||||||
|
@ -162,7 +208,7 @@ echo "ok"
|
||||||
#
|
#
|
||||||
|
|
||||||
echo -n "Minimize profiles xtrans "
|
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"
|
echo "failed"
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
@ -170,7 +216,7 @@ echo "ok"
|
||||||
|
|
||||||
# same test as above + audit
|
# same test as above + audit
|
||||||
echo -n "Minimize profiles audit xtrans "
|
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"
|
echo "failed"
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
@ -183,7 +229,7 @@ echo "ok"
|
||||||
# {3} (0x 0/fe17f85/0/14005)
|
# {3} (0x 0/fe17f85/0/14005)
|
||||||
|
|
||||||
echo -n "Minimize profiles deny xtrans "
|
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"
|
echo "failed"
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
@ -195,7 +241,7 @@ echo "ok"
|
||||||
# {3} (0x 0/fe17f85/0/0)
|
# {3} (0x 0/fe17f85/0/0)
|
||||||
|
|
||||||
echo -n "Minimize profiles audit deny xtrans "
|
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"
|
echo "failed"
|
||||||
exit 1;
|
exit 1;
|
||||||
fi
|
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;
|
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_NS;
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (perms & AA_VALID_USERNS_PERMS) {
|
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,
|
audit == AUDIT_FORCE ? perms : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
Loading…
Add table
Reference in a new issue