parser: don't apply exec mapping computations to the policydb

v8 network permissions extend into the range used by exec mapping
so it is important to not blindly do execmapping on both the
file dfa and policydb dfa any more.

Track what type of dfa and its permissions we are building so
we can properly apply exec mapping only when building the
file dfa.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/521
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2020-07-07 09:42:41 -07:00
parent e92478a9c5
commit c9d01a325d
5 changed files with 37 additions and 28 deletions

View file

@ -195,7 +195,8 @@ bool aare_rules::append_rule(const char *rule, bool oob, bool with_perm,
* else NULL on failure, @min_match_len set to the shortest string * else NULL on failure, @min_match_len set to the shortest string
* that can match the dfa for determining xmatch priority. * that can match the dfa for determining xmatch priority.
*/ */
void *aare_rules::create_dfa(size_t *size, int *min_match_len, dfaflags_t flags) void *aare_rules::create_dfa(size_t *size, int *min_match_len, dfaflags_t flags,
bool filedfa)
{ {
char *buffer = NULL; char *buffer = NULL;
@ -249,7 +250,7 @@ void *aare_rules::create_dfa(size_t *size, int *min_match_len, dfaflags_t flags)
stringstream stream; stringstream stream;
try { try {
DFA dfa(root, flags); DFA dfa(root, flags, filedfa);
if (flags & DFA_DUMP_UNIQ_PERMS) if (flags & DFA_DUMP_UNIQ_PERMS)
dfa.dump_uniq_perms("dfa"); dfa.dump_uniq_perms("dfa");

View file

@ -105,7 +105,8 @@ class aare_rules {
bool add_rule_vec(int deny, uint32_t perms, uint32_t audit, int count, bool add_rule_vec(int deny, uint32_t perms, uint32_t audit, int count,
const char **rulev, dfaflags_t flags, bool oob); const char **rulev, dfaflags_t flags, bool oob);
bool append_rule(const char *rule, bool oob, bool with_perm, dfaflags_t flags); bool append_rule(const char *rule, bool oob, bool with_perm, dfaflags_t flags);
void *create_dfa(size_t *size, int *min_match_len, dfaflags_t flags); void *create_dfa(size_t *size, int *min_match_len, dfaflags_t flags,
bool filedfa);
}; };
#endif /* __LIBAA_RE_RULES_H */ #endif /* __LIBAA_RE_RULES_H */

View file

@ -309,7 +309,7 @@ State *DFA::add_new_state(NodeSet *anodes, NodeSet *nnodes, State *other)
ProtoState proto; ProtoState proto;
proto.init(nnodev, anodes); proto.init(nnodev, anodes);
State *state = new State(node_map.size(), proto, other); State *state = new State(node_map.size(), proto, other, filedfa);
pair<NodeMap::iterator,bool> x = node_map.insert(proto, state); pair<NodeMap::iterator,bool> x = node_map.insert(proto, state);
if (x.second == false) { if (x.second == false) {
delete state; delete state;
@ -420,7 +420,7 @@ void DFA::process_work_queue(const char *header, dfaflags_t flags)
/** /**
* Construct a DFA from a syntax tree. * Construct a DFA from a syntax tree.
*/ */
DFA::DFA(Node *root, dfaflags_t flags): root(root) DFA::DFA(Node *root, dfaflags_t flags, bool buildfiledfa): root(root), filedfa(buildfiledfa)
{ {
diffcount = 0; /* set by diff_encode */ diffcount = 0; /* set by diff_encode */
max_range = 256; max_range = 256;
@ -785,7 +785,7 @@ void DFA::minimize(dfaflags_t flags)
if (flags & DFA_DUMP_MIN_PARTS) if (flags & DFA_DUMP_MIN_PARTS)
cerr << **i << ", "; cerr << **i << ", ";
(*i)->label = -1; (*i)->label = -1;
rep->perms.add((*i)->perms); rep->perms.add((*i)->perms, filedfa);
} }
if (rep->perms.is_accept()) if (rep->perms.is_accept())
final_accept++; final_accept++;
@ -1340,7 +1340,7 @@ static inline int diff_qualifiers(uint32_t perm1, uint32_t perm2)
* have any exact matches, then they override the execute and safe * have any exact matches, then they override the execute and safe
* execute flags. * execute flags.
*/ */
int accept_perms(NodeSet *state, perms_t &perms) int accept_perms(NodeSet *state, perms_t &perms, bool filedfa)
{ {
int error = 0; int error = 0;
uint32_t exact_match_allow = 0; uint32_t exact_match_allow = 0;
@ -1357,7 +1357,7 @@ int accept_perms(NodeSet *state, perms_t &perms)
continue; continue;
if (dynamic_cast<ExactMatchFlag *>(match)) { if (dynamic_cast<ExactMatchFlag *>(match)) {
/* exact match only ever happens with x */ /* exact match only ever happens with x */
if (!is_merged_x_consistent(exact_match_allow, if (filedfa && !is_merged_x_consistent(exact_match_allow,
match->flag)) match->flag))
error = 1;; error = 1;;
exact_match_allow |= match->flag; exact_match_allow |= match->flag;
@ -1366,16 +1366,20 @@ int accept_perms(NodeSet *state, perms_t &perms)
perms.deny |= match->flag; perms.deny |= match->flag;
perms.quiet |= match->audit; perms.quiet |= match->audit;
} else { } else {
if (!is_merged_x_consistent(perms.allow, match->flag)) if (filedfa && !is_merged_x_consistent(perms.allow, match->flag))
error = 1; error = 1;
perms.allow |= match->flag; perms.allow |= match->flag;
perms.audit |= match->audit; perms.audit |= match->audit;
} }
} }
if (filedfa) {
perms.allow |= exact_match_allow & ~(ALL_AA_EXEC_TYPE); perms.allow |= exact_match_allow & ~(ALL_AA_EXEC_TYPE);
perms.audit |= exact_audit & ~(ALL_AA_EXEC_TYPE); perms.audit |= exact_audit & ~(ALL_AA_EXEC_TYPE);
} else {
perms.allow |= exact_match_allow;
perms.audit |= exact_audit;
}
if (exact_match_allow & AA_USER_EXEC) { if (exact_match_allow & AA_USER_EXEC) {
perms.allow = (exact_match_allow & AA_USER_EXEC_TYPE) | perms.allow = (exact_match_allow & AA_USER_EXEC_TYPE) |
(perms.allow & ~AA_USER_EXEC_TYPE); (perms.allow & ~AA_USER_EXEC_TYPE);
@ -1386,10 +1390,10 @@ int accept_perms(NodeSet *state, perms_t &perms)
(perms.allow & ~AA_OTHER_EXEC_TYPE); (perms.allow & ~AA_OTHER_EXEC_TYPE);
perms.exact |= AA_OTHER_EXEC_TYPE; perms.exact |= AA_OTHER_EXEC_TYPE;
} }
if (AA_USER_EXEC & perms.deny) if (filedfa && (AA_USER_EXEC & perms.deny))
perms.deny |= AA_USER_EXEC_TYPE; perms.deny |= AA_USER_EXEC_TYPE;
if (AA_OTHER_EXEC & perms.deny) if (filedfa && (AA_OTHER_EXEC & perms.deny))
perms.deny |= AA_OTHER_EXEC_TYPE; perms.deny |= AA_OTHER_EXEC_TYPE;
perms.allow &= ~perms.deny; perms.allow &= ~perms.deny;

View file

@ -59,11 +59,11 @@ public:
} }
void clear(void) { allow = deny = audit = quiet = 0; } void clear(void) { allow = deny = audit = quiet = 0; }
void add(perms_t &rhs) void add(perms_t &rhs, bool filedfa)
{ {
deny |= rhs.deny; deny |= rhs.deny;
if (!is_merged_x_consistent(allow & ALL_USER_EXEC, if (filedfa && !is_merged_x_consistent(allow & ALL_USER_EXEC,
rhs.allow & ALL_USER_EXEC)) { rhs.allow & ALL_USER_EXEC)) {
if ((exact & AA_USER_EXEC_TYPE) && if ((exact & AA_USER_EXEC_TYPE) &&
!(rhs.exact & AA_USER_EXEC_TYPE)) { !(rhs.exact & AA_USER_EXEC_TYPE)) {
@ -74,10 +74,10 @@ public:
(rhs.allow & AA_USER_EXEC_TYPE); (rhs.allow & AA_USER_EXEC_TYPE);
} else } else
throw 1; throw 1;
} else } else if (filedfa)
allow |= rhs.allow & AA_USER_EXEC_TYPE; allow |= rhs.allow & AA_USER_EXEC_TYPE;
if (!is_merged_x_consistent(allow & ALL_OTHER_EXEC, if (filedfa && !is_merged_x_consistent(allow & ALL_OTHER_EXEC,
rhs.allow & ALL_OTHER_EXEC)) { rhs.allow & ALL_OTHER_EXEC)) {
if ((exact & AA_OTHER_EXEC_TYPE) && if ((exact & AA_OTHER_EXEC_TYPE) &&
!(rhs.exact & AA_OTHER_EXEC_TYPE)) { !(rhs.exact & AA_OTHER_EXEC_TYPE)) {
@ -88,11 +88,13 @@ public:
(rhs.allow & AA_OTHER_EXEC_TYPE); (rhs.allow & AA_OTHER_EXEC_TYPE);
} else } else
throw 1; throw 1;
} else } else if (filedfa)
allow |= rhs.allow & AA_OTHER_EXEC_TYPE; allow |= rhs.allow & AA_OTHER_EXEC_TYPE;
if (filedfa)
allow = (allow | (rhs.allow & ~ALL_AA_EXEC_TYPE)); allow = (allow | (rhs.allow & ~ALL_AA_EXEC_TYPE));
else
allow |= rhs.allow;
audit |= rhs.audit; audit |= rhs.audit;
quiet = (quiet | rhs.quiet); quiet = (quiet | rhs.quiet);
@ -131,7 +133,7 @@ public:
uint32_t allow, deny, audit, quiet, exact; uint32_t allow, deny, audit, quiet, exact;
}; };
int accept_perms(NodeSet *state, perms_t &perms); int accept_perms(NodeSet *state, perms_t &perms, bool filedfa);
/* /*
* ProtoState - NodeSet and ancillery information used to create a state * ProtoState - NodeSet and ancillery information used to create a state
@ -195,7 +197,7 @@ struct DiffDag {
*/ */
class State { class State {
public: public:
State(int l, ProtoState &n, State *other): State(int l, ProtoState &n, State *other, bool filedfa):
label(l), flags(0), perms(), trans() label(l), flags(0), perms(), trans()
{ {
int error; int error;
@ -208,7 +210,7 @@ public:
proto = n; proto = n;
/* Compute permissions associated with the State. */ /* Compute permissions associated with the State. */
error = accept_perms(n.anodes, perms); error = accept_perms(n.anodes, perms, filedfa);
if (error) { if (error) {
//cerr << "Failing on accept perms " << error << "\n"; //cerr << "Failing on accept perms " << error << "\n";
throw error; throw error;
@ -316,7 +318,7 @@ class DFA {
list<State *> work_queue; list<State *> work_queue;
public: public:
DFA(Node *root, dfaflags_t flags); DFA(Node *root, dfaflags_t flags, bool filedfa);
virtual ~DFA(); virtual ~DFA();
State *match_len(State *state, const char *str, size_t len); State *match_len(State *state, const char *str, size_t len);
@ -347,6 +349,7 @@ public:
Node *root; Node *root;
State *nonmatching, *start; State *nonmatching, *start;
Partition states; Partition states;
bool filedfa;
}; };
void dump_equivalence_classes(ostream &os, map<transchar, transchar> &eq); void dump_equivalence_classes(ostream &os, map<transchar, transchar> &eq);

View file

@ -557,7 +557,7 @@ static int process_profile_name_xmatch(Profile *prof)
} }
} }
build: build:
prof->xmatch = rules->create_dfa(&prof->xmatch_size, &prof->xmatch_len, dfaflags); prof->xmatch = rules->create_dfa(&prof->xmatch_size, &prof->xmatch_len, dfaflags, true);
delete rules; delete rules;
if (!prof->xmatch) if (!prof->xmatch)
return FALSE; return FALSE;
@ -755,7 +755,7 @@ int process_profile_regex(Profile *prof)
if (prof->dfa.rules->rule_count > 0) { if (prof->dfa.rules->rule_count > 0) {
int xmatch_len = 0; int xmatch_len = 0;
prof->dfa.dfa = prof->dfa.rules->create_dfa(&prof->dfa.size, prof->dfa.dfa = prof->dfa.rules->create_dfa(&prof->dfa.size,
&xmatch_len, dfaflags); &xmatch_len, dfaflags, true);
delete prof->dfa.rules; delete prof->dfa.rules;
prof->dfa.rules = NULL; prof->dfa.rules = NULL;
if (!prof->dfa.dfa) if (!prof->dfa.dfa)
@ -973,7 +973,7 @@ int process_profile_policydb(Profile *prof)
if (prof->policy.rules->rule_count > 0) { if (prof->policy.rules->rule_count > 0) {
int xmatch_len = 0; int xmatch_len = 0;
prof->policy.dfa = prof->policy.rules->create_dfa(&prof->policy.size, prof->policy.dfa = prof->policy.rules->create_dfa(&prof->policy.size,
&xmatch_len, dfaflags); &xmatch_len, dfaflags, false);
delete prof->policy.rules; delete prof->policy.rules;
prof->policy.rules = NULL; prof->policy.rules = NULL;