diff --git a/parser/libapparmor_re/chfa.cc b/parser/libapparmor_re/chfa.cc index 5f069e439..262d7777b 100644 --- a/parser/libapparmor_re/chfa.cc +++ b/parser/libapparmor_re/chfa.cc @@ -31,6 +31,7 @@ #include "hfa.h" #include "chfa.h" +#include "../immunix.h" void CHFA::init_free_list(vector > &free_list, size_t prev, size_t start) @@ -112,8 +113,8 @@ CHFA::CHFA(DFA &dfa, map &eq, dfaflags_t flags): eq(eq) for (Partition::iterator i = dfa.states.begin(); i != dfa.states.end(); i++) { if (*i != dfa.nonmatching && *i != dfa.start) { insert_state(free_list, *i, dfa); - accept[num.size()] = (*i)->accept; - accept2[num.size()] = (*i)->audit; + accept[num.size()] = (*i)->perms.allow; + accept2[num.size()] = PACK_AUDIT_CTL((*i)->perms.audit, (*i)->perms.quiet & (*i)->perms.deny); num.insert(make_pair(*i, num.size())); } if (flags & (DFA_DUMP_TRANS_PROGRESS)) { @@ -129,8 +130,8 @@ CHFA::CHFA(DFA &dfa, map &eq, dfaflags_t flags): eq(eq) if (i->second != dfa.nonmatching && i->second != dfa.start) { insert_state(free_list, i->second, dfa); - accept[num.size()] = i->second->accept; - accept2[num.size()] = i->second->audit; + accept[num.size()] = i->second->perms.allow; + accept2[num.size()] = PACK_AUDIT_CTL(i->second->perms.audit, i->second->perms.quiet & i->second->perms.deny); num.insert(make_pair(i->second, num.size())); } if (flags & (DFA_DUMP_TRANS_PROGRESS)) { diff --git a/parser/libapparmor_re/hfa.cc b/parser/libapparmor_re/hfa.cc index dca93048e..c6c56baf3 100644 --- a/parser/libapparmor_re/hfa.cc +++ b/parser/libapparmor_re/hfa.cc @@ -291,15 +291,16 @@ State *DFA::match(const char *str) void DFA::dump_uniq_perms(const char *s) { - set > uniq; + set uniq; for (Partition::iterator i = states.begin(); i != states.end(); i++) - uniq.insert(make_pair((*i)->accept, (*i)->audit)); + uniq.insert((*i)->perms); cerr << "Unique Permission sets: " << s << " (" << uniq.size() << ")\n"; cerr << "----------------------\n"; - for (set >::iterator i = uniq.begin(); - i != uniq.end(); i++) { - cerr << " " << hex << i->first << " " << i->second << dec << "\n"; + for (set::iterator i = uniq.begin(); i != uniq.end(); i++) { + cerr << " allow:" << hex << i->allow << " deny:" + << i->deny << " audit:" << i->audit + << " quiet:" << i->quiet << dec << "\n"; } } @@ -339,10 +340,12 @@ void DFA::remove_unreachable(dfaflags_t flags) cerr << "unreachable: " << **i; if (*i == start) cerr << " <=="; - if ((*i)->accept) { + if (!(*i)->perms.is_null()) { cerr << " (0x" << hex - << (*i)->accept << " " - << (*i)->audit << dec + << (*i)->perms.allow << " " + << (*i)->perms.deny << " " + << (*i)->perms.audit << " " + << (*i)->perms.quiet << dec << ')'; } cerr << "\n"; @@ -438,9 +441,9 @@ void DFA::minimize(dfaflags_t flags) uint64_t perm_hash = 0; if (flags & DFA_CONTROL_MINIMIZE_HASH_PERMS) { /* make every unique perm create a new partition */ - perm_hash = ((uint64_t) (*i)->audit) << 32 | - (uint64_t) (*i)->accept; - } else if ((*i)->audit || (*i)->accept) { + perm_hash = ((uint64_t) PACK_AUDIT_CTL((*i)->perms.audit, (*i)->perms.quiet & (*i)->perms.deny)) << 32 | + (uint64_t) (*i)->perms.allow; + } else if (!(*i)->perms.is_null()) { /* combine all perms together into a single parition */ perm_hash = 1; } /* else not an accept state so 0 for perm_hash */ @@ -467,7 +470,6 @@ void DFA::minimize(dfaflags_t flags) << partitions.size() << "\tinit " << partitions.size() << " (accept " << accept_count << ")\r"; } - /* perm_map is no longer needed so free the memory it is using. * Don't remove - doing it manually here helps reduce peak memory usage. */ @@ -567,10 +569,12 @@ void DFA::minimize(dfaflags_t flags) if (flags & DFA_DUMP_MIN_PARTS) cerr << **i << ", "; (*i)->label = -1; - rep->accept |= (*i)->accept; - rep->audit |= (*i)->audit; + rep->perms.allow |= (*i)->perms.allow; + rep->perms.deny |= (*i)->perms.deny; + rep->perms.audit |= (*i)->perms.audit; + rep->perms.quiet |= (*i)->perms.quiet; } - if (rep->accept || rep->audit) + if (rep->perms.allow || rep->perms.audit || rep->perms.quiet) final_accept++; //if ((*p)->size() > 1) //cerr << "\n"; @@ -625,13 +629,15 @@ out: void DFA::dump(ostream & os) { for (Partition::iterator i = states.begin(); i != states.end(); i++) { - if (*i == start || (*i)->accept) { + if (*i == start || !(*i)->perms.is_null()) { os << **i; if (*i == start) os << " <=="; - if ((*i)->accept) { - os << " (0x" << hex << (*i)->accept << " " - << (*i)->audit << dec << ')'; + if ((*i)->perms.allow) { + os << " (0x" << hex << (*i)->perms.allow << " " + << (*i)->perms.deny << " " + << (*i)->perms.audit << " " + << (*i)->perms.audit << dec << ')'; } os << "\n"; } @@ -665,7 +671,7 @@ void DFA::dump_dot_graph(ostream & os) if (*i == start) { os << "\t\tstyle=bold" << "\n"; } - uint32_t perms = (*i)->accept; + uint32_t perms = (*i)->perms.allow; if (perms) { os << "\t\tlabel=\"" << **i << "\\n(" << perms << ")\"" << "\n"; @@ -847,17 +853,16 @@ static inline int diff_qualifiers(uint32_t perm1, uint32_t perm2) * have any exact matches, then they override the execute and safe * execute flags. */ -uint32_t accept_perms(NodeSet *state, uint32_t *audit_ctl, int *error) +int accept_perms(NodeSet *state, perms_t &perms) { - uint32_t perms = 0, exact_match_perms = 0; + int error = 0; + uint32_t allow = 0, exact_match_allow = 0; uint32_t audit = 0, exact_audit = 0, quiet = 0, deny = 0; - if (error) - *error = 0; - if (!state) { - *audit_ctl = 0; - return perms; - } + perms.clear(); + + if (!state) + return error; for (NodeSet::iterator i = state->begin(); i != state->end(); i++) { MatchFlag *match; @@ -865,68 +870,69 @@ uint32_t accept_perms(NodeSet *state, uint32_t *audit_ctl, int *error) continue; if (dynamic_cast(match)) { /* exact match only ever happens with x */ - if (!is_merged_x_consistent(exact_match_perms, - match->flag) && error) - *error = 1;; - exact_match_perms |= match->flag; + if (!is_merged_x_consistent(exact_match_allow, + match->flag)) + error = 1;; + exact_match_allow |= match->flag; exact_audit |= match->audit; } else if (dynamic_cast(match)) { deny |= match->flag; quiet |= match->audit; } else { - if (!is_merged_x_consistent(perms, match->flag) - && error) - *error = 1; - perms |= match->flag; + if (!is_merged_x_consistent(allow, match->flag)) + error = 1; + allow |= match->flag; audit |= match->audit; } } //if (audit || quiet) -//fprintf(stderr, "perms: 0x%x, audit: 0x%x exact: 0x%x eaud: 0x%x deny: 0x%x quiet: 0x%x\n", perms, audit, exact_match_perms, exact_audit, deny, quiet); +//fprintf(stderr, "allow: 0x%x, audit: 0x%x exact: 0x%x eaud: 0x%x deny: 0x%x quiet: 0x%x\n", allow, audit, exact_match_allow, exact_audit, deny, quiet); - perms |= exact_match_perms & ~(AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE); + allow |= exact_match_allow & ~(AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE); - if (exact_match_perms & AA_USER_EXEC_TYPE) { - perms = (exact_match_perms & AA_USER_EXEC_TYPE) | - (perms & ~AA_USER_EXEC_TYPE); + if (exact_match_allow & AA_USER_EXEC_TYPE) { + allow = (exact_match_allow & AA_USER_EXEC_TYPE) | + (allow & ~AA_USER_EXEC_TYPE); audit = (exact_audit & AA_USER_EXEC_TYPE) | (audit & ~AA_USER_EXEC_TYPE); } - if (exact_match_perms & AA_OTHER_EXEC_TYPE) { - perms = (exact_match_perms & AA_OTHER_EXEC_TYPE) | - (perms & ~AA_OTHER_EXEC_TYPE); + if (exact_match_allow & AA_OTHER_EXEC_TYPE) { + allow = (exact_match_allow & AA_OTHER_EXEC_TYPE) | + (allow & ~AA_OTHER_EXEC_TYPE); audit = (exact_audit & AA_OTHER_EXEC_TYPE) | (audit & ~AA_OTHER_EXEC_TYPE); } - if (perms & AA_USER_EXEC & deny) - perms &= ~AA_USER_EXEC_TYPE; + if (allow & AA_USER_EXEC & deny) + allow &= ~AA_USER_EXEC_TYPE; - if (perms & AA_OTHER_EXEC & deny) - perms &= ~AA_OTHER_EXEC_TYPE; + if (allow & AA_OTHER_EXEC & deny) + allow &= ~AA_OTHER_EXEC_TYPE; - perms &= ~deny; + allow &= ~deny; - if (audit_ctl) - *audit_ctl = PACK_AUDIT_CTL(audit, quiet & deny); + perms.allow = allow & ~deny; + perms.deny = deny; + perms.audit = audit; + perms.quiet = quiet & deny; -// if (perms & AA_ERROR_BIT) { -// fprintf(stderr, "error bit 0x%x\n", perms); +// if (allow & AA_ERROR_BIT) { +// fprintf(stderr, "error bit 0x%x\n", allow); // exit(255); //} - //if (perms & AA_EXEC_BITS) - //fprintf(stderr, "accept perm: 0x%x\n", perms); + //if (allow & AA_EXEC_BITS) + //fprintf(stderr, "accept perm: 0x%x\n", allow); /* - if (perms & ~AA_VALID_PERMS) - yyerror(_("Internal error accumulated invalid perm 0x%llx\n"), perms); + if (allow & ~AA_VALID_PERMS) + yyerror(_("Internal error accumulated invalid perm 0x%llx\n"), allow); */ -//if (perms & AA_CHANGE_HAT) -// fprintf(stderr, "change_hat 0x%x\n", perms); +//if (allow & AA_CHANGE_HAT) +// fprintf(stderr, "change_hat 0x%x\n", allow); - if (*error) + if (error) fprintf(stderr, "profile has merged rule with conflicting x modifiers\n"); - return perms; + return error; } diff --git a/parser/libapparmor_re/hfa.h b/parser/libapparmor_re/hfa.h index 66f0a70b3..62512d615 100644 --- a/parser/libapparmor_re/hfa.h +++ b/parser/libapparmor_re/hfa.h @@ -37,7 +37,36 @@ class State; typedef map StateTrans; typedef list Partition; -uint32_t accept_perms(NodeSet *state, uint32_t *audit_ctl, int *error); +class perms_t { +public: + perms_t(void): allow(0), deny(0), audit(0), quiet(0) { }; + + bool is_null(void) { return !(allow | deny | audit | quiet); } + + void clear(void) { allow = deny = audit = quiet = 0; } + void add(perms_t &rhs) + { + deny |= rhs.deny; + allow = (allow | rhs.audit) & ~deny; + audit |= rhs.audit; + quiet = (quiet | rhs.quiet) & deny; + } + + bool operator<(perms_t const &rhs)const + { + if (allow < rhs.allow) + return allow < rhs.allow; + if (deny < rhs.deny) + return deny < rhs.deny; + if (audit < rhs.audit) + return audit < rhs.audit; + return quiet < rhs.quiet; + } + + uint32_t allow, deny, audit, quiet; +}; + +int accept_perms(NodeSet *state, perms_t &perms); /* * hashedNodes - for efficient set comparison @@ -256,7 +285,7 @@ public: class State { public: State(int l, ProtoState &n, State *other) throw(int): - label(l), audit(0), accept(0), trans() + label(l), perms(), trans() { int error; @@ -268,7 +297,7 @@ public: proto = n; /* Compute permissions associated with the State. */ - accept = accept_perms(n.anodes, &audit, &error); + error = accept_perms(n.anodes, perms); if (error) { //cerr << "Failing on accept perms " << error << "\n"; throw error; @@ -283,7 +312,7 @@ public: }; int label; - uint32_t audit, accept; + perms_t perms; StateTrans trans; State *otherwise;