mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-23 02:27:12 +00:00
Lindent + some hand cleanups hfa
Signed-off-by: John Johansen <john.johansen@canonical.com> Acked-by: Seth Arnold <seth.arnold@gmail.com>
This commit is contained in:
parent
3cfe47d3f0
commit
9a377bb9da
@ -30,7 +30,7 @@ using namespace std;
|
|||||||
|
|
||||||
class TransitionTable {
|
class TransitionTable {
|
||||||
typedef vector<pair<const State *, size_t> > DefaultBase;
|
typedef vector<pair<const State *, size_t> > DefaultBase;
|
||||||
typedef vector<pair<const State *, const State *> >NextCheck;
|
typedef vector<pair<const State *, const State *> > NextCheck;
|
||||||
public:
|
public:
|
||||||
TransitionTable(DFA &dfa, map<uchar, uchar> &eq, dfaflags_t flags);
|
TransitionTable(DFA &dfa, map<uchar, uchar> &eq, dfaflags_t flags);
|
||||||
void dump(ostream & os);
|
void dump(ostream & os);
|
||||||
|
@ -35,9 +35,7 @@
|
|||||||
#include "hfa.h"
|
#include "hfa.h"
|
||||||
#include "../immunix.h"
|
#include "../immunix.h"
|
||||||
|
|
||||||
|
ostream &operator<<(ostream &os, const State &state)
|
||||||
|
|
||||||
ostream& operator<<(ostream& os, const State& state)
|
|
||||||
{
|
{
|
||||||
/* dump the state label */
|
/* dump the state label */
|
||||||
os << '{';
|
os << '{';
|
||||||
@ -46,7 +44,9 @@ ostream& operator<<(ostream& os, const State& state)
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
State* DFA::add_new_state(NodeMap &nodemap, pair <unsigned long, NodeSet *> index, NodeSet *nodes, dfa_stats_t &stats)
|
State *DFA::add_new_state(NodeMap &nodemap,
|
||||||
|
pair<unsigned long, NodeSet *> index,
|
||||||
|
NodeSet *nodes, dfa_stats_t &stats)
|
||||||
{
|
{
|
||||||
State *state = new State(nodemap.size(), nodes);
|
State *state = new State(nodemap.size(), nodes);
|
||||||
states.push_back(state);
|
states.push_back(state);
|
||||||
@ -57,14 +57,14 @@ State* DFA::add_new_state(NodeMap &nodemap, pair <unsigned long, NodeSet *> inde
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
State *DFA::find_target_state(NodeMap &nodemap, list <State *> &work_queue,
|
State *DFA::find_target_state(NodeMap &nodemap, list<State *> &work_queue,
|
||||||
NodeSet *nodes, dfa_stats_t &stats)
|
NodeSet *nodes, dfa_stats_t &stats)
|
||||||
{
|
{
|
||||||
State *target;
|
State *target;
|
||||||
|
|
||||||
pair <unsigned long, NodeSet *> index = make_pair(hash_NodeSet(nodes), nodes);
|
pair<unsigned long, NodeSet *> index = make_pair(hash_NodeSet(nodes), nodes);
|
||||||
|
|
||||||
map<pair <unsigned long, NodeSet *>, State *, deref_less_than>::iterator x = nodemap.find(index);
|
map<pair<unsigned long, NodeSet *>, State *, deref_less_than>::iterator x = nodemap.find(index);
|
||||||
|
|
||||||
if (x == nodemap.end()) {
|
if (x == nodemap.end()) {
|
||||||
/* set of nodes isn't known so create new state, and nodes to
|
/* set of nodes isn't known so create new state, and nodes to
|
||||||
@ -75,16 +75,15 @@ State *DFA::find_target_state(NodeMap &nodemap, list <State *> &work_queue,
|
|||||||
} else {
|
} else {
|
||||||
/* set of nodes already has a mapping so free this one */
|
/* set of nodes already has a mapping so free this one */
|
||||||
stats.duplicates++;
|
stats.duplicates++;
|
||||||
delete (nodes);
|
delete(nodes);
|
||||||
target = x->second;
|
target = x->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DFA::update_state_transitions(NodeMap &nodemap,
|
void DFA::update_state_transitions(NodeMap &nodemap, list<State *> &work_queue,
|
||||||
list <State *> &work_queue, State *state,
|
State *state, dfa_stats_t &stats)
|
||||||
dfa_stats_t &stats)
|
|
||||||
{
|
{
|
||||||
/* Compute possible transitions for state->nodes. This is done by
|
/* Compute possible transitions for state->nodes. This is done by
|
||||||
* iterating over all the nodes in state->nodes and combining the
|
* iterating over all the nodes in state->nodes and combining the
|
||||||
@ -113,8 +112,7 @@ void DFA::update_state_transitions(NodeMap &nodemap,
|
|||||||
*/
|
*/
|
||||||
for (NodeCases::iterator j = cases.begin(); j != cases.end(); j++) {
|
for (NodeCases::iterator j = cases.begin(); j != cases.end(); j++) {
|
||||||
State *target;
|
State *target;
|
||||||
target = find_target_state(nodemap, work_queue, j->second,
|
target = find_target_state(nodemap, work_queue, j->second, stats);
|
||||||
stats);
|
|
||||||
|
|
||||||
/* Don't insert transition that the default transition
|
/* Don't insert transition that the default transition
|
||||||
* already covers
|
* already covers
|
||||||
@ -124,7 +122,6 @@ void DFA::update_state_transitions(NodeMap &nodemap,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* WARNING: This routine can only be called from within DFA creation as
|
/* WARNING: This routine can only be called from within DFA creation as
|
||||||
* the nodes value is only valid during dfa construction.
|
* the nodes value is only valid during dfa construction.
|
||||||
*/
|
*/
|
||||||
@ -140,7 +137,7 @@ void DFA::dump_node_to_dfa(void)
|
|||||||
/**
|
/**
|
||||||
* 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): root(root)
|
||||||
{
|
{
|
||||||
dfa_stats_t stats = { 0, 0, 0 };
|
dfa_stats_t stats = { 0, 0, 0 };
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -163,7 +160,7 @@ DFA::DFA(Node *root, dfaflags_t flags) : root(root)
|
|||||||
NodeMap nodemap;
|
NodeMap nodemap;
|
||||||
NodeSet *emptynode = new NodeSet;
|
NodeSet *emptynode = new NodeSet;
|
||||||
nonmatching = add_new_state(nodemap,
|
nonmatching = add_new_state(nodemap,
|
||||||
make_pair(hash_NodeSet(emptynode), emptynode),
|
make_pair(hash_NodeSet(emptynode), emptynode),
|
||||||
emptynode, stats);
|
emptynode, stats);
|
||||||
|
|
||||||
NodeSet *first = new NodeSet(root->firstpos);
|
NodeSet *first = new NodeSet(root->firstpos);
|
||||||
@ -185,7 +182,9 @@ DFA::DFA(Node *root, dfaflags_t flags) : root(root)
|
|||||||
|
|
||||||
while (!work_queue.empty()) {
|
while (!work_queue.empty()) {
|
||||||
if (i % 1000 == 0 && (flags & DFA_DUMP_PROGRESS))
|
if (i % 1000 == 0 && (flags & DFA_DUMP_PROGRESS))
|
||||||
fprintf(stderr, "\033[2KCreating dfa: queue %ld\tstates %ld\teliminated duplicates %d\r", work_queue.size(), states.size(), stats.duplicates);
|
fprintf(stderr, "\033[2KCreating dfa: queue %ld\tstates %ld\teliminated duplicates %d\r",
|
||||||
|
work_queue.size(), states.size(),
|
||||||
|
stats.duplicates);
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
State *from = work_queue.front();
|
State *from = work_queue.front();
|
||||||
@ -196,7 +195,7 @@ DFA::DFA(Node *root, dfaflags_t flags) : root(root)
|
|||||||
*/
|
*/
|
||||||
update_state_transitions(nodemap, work_queue, from, stats);
|
update_state_transitions(nodemap, work_queue, from, stats);
|
||||||
|
|
||||||
} /* for (NodeSet *nodes ... */
|
} /* while (!work_queue.empty()) */
|
||||||
|
|
||||||
/* cleanup Sets of nodes used computing the DFA as they are no longer
|
/* cleanup Sets of nodes used computing the DFA as they are no longer
|
||||||
* needed.
|
* needed.
|
||||||
@ -215,37 +214,37 @@ DFA::DFA(Node *root, dfaflags_t flags) : root(root)
|
|||||||
nodemap.clear();
|
nodemap.clear();
|
||||||
|
|
||||||
if (flags & (DFA_DUMP_STATS))
|
if (flags & (DFA_DUMP_STATS))
|
||||||
fprintf(stderr, "\033[2KCreated dfa: states %ld,\teliminated duplicates %d,\tprotostate sets: longest %u, avg %u\n", states.size(), stats.duplicates, stats.proto_max, (unsigned int) (stats.proto_sum/states.size()));
|
fprintf(stderr, "\033[2KCreated dfa: states %ld,\teliminated duplicates %d,\tprotostate sets: longest %u, avg %u\n",
|
||||||
|
states.size(), stats.duplicates, stats.proto_max,
|
||||||
|
(unsigned int)(stats.proto_sum / states.size()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DFA::~DFA()
|
DFA::~DFA()
|
||||||
{
|
{
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); i++)
|
for (Partition::iterator i = states.begin(); i != states.end(); i++)
|
||||||
delete *i;
|
delete *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DFA::dump_uniq_perms(const char *s)
|
void DFA::dump_uniq_perms(const char *s)
|
||||||
{
|
{
|
||||||
set < pair<uint32_t, uint32_t> > uniq;
|
set<pair<uint32_t, uint32_t> > uniq;
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); i++)
|
for (Partition::iterator i = states.begin(); i != states.end(); i++)
|
||||||
uniq.insert(make_pair((*i)->accept, (*i)->audit));
|
uniq.insert(make_pair((*i)->accept, (*i)->audit));
|
||||||
|
|
||||||
cerr << "Unique Permission sets: " << s << " (" << uniq.size() << ")\n";
|
cerr << "Unique Permission sets: " << s << " (" << uniq.size() << ")\n";
|
||||||
cerr << "----------------------\n";
|
cerr << "----------------------\n";
|
||||||
for (set< pair<uint32_t, uint32_t> >::iterator i = uniq.begin();
|
for (set<pair<uint32_t, uint32_t> >::iterator i = uniq.begin();
|
||||||
i != uniq.end(); i++) {
|
i != uniq.end(); i++) {
|
||||||
cerr << " " << hex << i->first << " " << i->second << dec <<"\n";
|
cerr << " " << hex << i->first << " " << i->second << dec << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Remove dead or unreachable states */
|
/* Remove dead or unreachable states */
|
||||||
void DFA::remove_unreachable(dfaflags_t flags)
|
void DFA::remove_unreachable(dfaflags_t flags)
|
||||||
{
|
{
|
||||||
set <State *> reachable;
|
set<State *> reachable;
|
||||||
list <State *> work_queue;
|
list<State *> work_queue;
|
||||||
|
|
||||||
/* find the set of reachable states */
|
/* find the set of reachable states */
|
||||||
reachable.insert(nonmatching);
|
reachable.insert(nonmatching);
|
||||||
@ -259,8 +258,7 @@ void DFA::remove_unreachable(dfaflags_t flags)
|
|||||||
(reachable.find(from->cases.otherwise) == reachable.end()))
|
(reachable.find(from->cases.otherwise) == reachable.end()))
|
||||||
work_queue.push_back(from->cases.otherwise);
|
work_queue.push_back(from->cases.otherwise);
|
||||||
|
|
||||||
for (Cases::iterator j = from->cases.begin();
|
for (Cases::iterator j = from->cases.begin(); j != from->cases.end(); j++) {
|
||||||
j != from->cases.end(); j++) {
|
|
||||||
if (reachable.find(j->second) == reachable.end())
|
if (reachable.find(j->second) == reachable.end())
|
||||||
work_queue.push_back(j->second);
|
work_queue.push_back(j->second);
|
||||||
}
|
}
|
||||||
@ -276,14 +274,16 @@ void DFA::remove_unreachable(dfaflags_t flags)
|
|||||||
next++;
|
next++;
|
||||||
if (reachable.find(*i) == reachable.end()) {
|
if (reachable.find(*i) == reachable.end()) {
|
||||||
if (flags & DFA_DUMP_UNREACHABLE) {
|
if (flags & DFA_DUMP_UNREACHABLE) {
|
||||||
cerr << "unreachable: "<< **i;
|
cerr << "unreachable: " << **i;
|
||||||
if (*i == start)
|
if (*i == start)
|
||||||
cerr << " <==";
|
cerr << " <==";
|
||||||
if ((*i)->accept) {
|
if ((*i)->accept) {
|
||||||
cerr << " (0x" << hex << (*i)->accept
|
cerr << " (0x" << hex
|
||||||
<< " " << (*i)->audit << dec << ')';
|
<< (*i)->accept << " "
|
||||||
|
<< (*i)->audit << dec
|
||||||
|
<< ')';
|
||||||
}
|
}
|
||||||
cerr << endl;
|
cerr << "\n";
|
||||||
}
|
}
|
||||||
State *current = *i;
|
State *current = *i;
|
||||||
states.erase(i);
|
states.erase(i);
|
||||||
@ -314,8 +314,7 @@ bool DFA::same_mappings(State *s1, State *s2)
|
|||||||
|
|
||||||
if (s1->cases.cases.size() != s2->cases.cases.size())
|
if (s1->cases.cases.size() != s2->cases.cases.size())
|
||||||
return false;
|
return false;
|
||||||
for (Cases::iterator j1 = s1->cases.begin(); j1 != s1->cases.end();
|
for (Cases::iterator j1 = s1->cases.begin(); j1 != s1->cases.end(); j1++) {
|
||||||
j1++){
|
|
||||||
Cases::iterator j2 = s2->cases.cases.find(j1->first);
|
Cases::iterator j2 = s2->cases.cases.find(j1->first);
|
||||||
if (j2 == s2->cases.end())
|
if (j2 == s2->cases.end())
|
||||||
return false;
|
return false;
|
||||||
@ -337,9 +336,9 @@ bool DFA::same_mappings(State *s1, State *s2)
|
|||||||
*/
|
*/
|
||||||
size_t DFA::hash_trans(State *s)
|
size_t DFA::hash_trans(State *s)
|
||||||
{
|
{
|
||||||
unsigned long hash = 5381;
|
unsigned long hash = 5381;
|
||||||
|
|
||||||
for (Cases::iterator j = s->cases.begin(); j != s->cases.end(); j++){
|
for (Cases::iterator j = s->cases.begin(); j != s->cases.end(); j++) {
|
||||||
hash = ((hash << 5) + hash) + j->first;
|
hash = ((hash << 5) + hash) + j->first;
|
||||||
State *k = j->second;
|
State *k = j->second;
|
||||||
hash = ((hash << 5) + hash) + k->cases.cases.size();
|
hash = ((hash << 5) + hash) + k->cases.cases.size();
|
||||||
@ -352,15 +351,15 @@ size_t DFA::hash_trans(State *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
hash = (hash << 8) | s->cases.cases.size();
|
hash = (hash << 8) | s->cases.cases.size();
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* minimize the number of dfa states */
|
/* minimize the number of dfa states */
|
||||||
void DFA::minimize(dfaflags_t flags)
|
void DFA::minimize(dfaflags_t flags)
|
||||||
{
|
{
|
||||||
map <pair <uint64_t, size_t>, Partition *> perm_map;
|
map<pair<uint64_t, size_t>, Partition *> perm_map;
|
||||||
list <Partition *> partitions;
|
list<Partition *> partitions;
|
||||||
|
|
||||||
/* Set up the initial partitions
|
/* Set up the initial partitions
|
||||||
* minimium of - 1 non accepting, and 1 accepting
|
* minimium of - 1 non accepting, and 1 accepting
|
||||||
* if trans hashing is used the accepting and non-accepting partitions
|
* if trans hashing is used the accepting and non-accepting partitions
|
||||||
@ -377,18 +376,17 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
uint64_t perm_hash = 0;
|
uint64_t perm_hash = 0;
|
||||||
if (flags & DFA_CONTROL_MINIMIZE_HASH_PERMS) {
|
if (flags & DFA_CONTROL_MINIMIZE_HASH_PERMS) {
|
||||||
/* make every unique perm create a new partition */
|
/* make every unique perm create a new partition */
|
||||||
perm_hash = ((uint64_t)(*i)->audit)<<32 |
|
perm_hash = ((uint64_t) (*i)->audit) << 32 |
|
||||||
(uint64_t)(*i)->accept;
|
(uint64_t) (*i)->accept;
|
||||||
} else if ((*i)->audit || (*i)->accept) {
|
} else if ((*i)->audit || (*i)->accept) {
|
||||||
/* combine all perms together into a single parition */
|
/* combine all perms together into a single parition */
|
||||||
perm_hash = 1;
|
perm_hash = 1;
|
||||||
} /* else not an accept state so 0 for perm_hash */
|
} /* else not an accept state so 0 for perm_hash */
|
||||||
|
|
||||||
size_t trans_hash = 0;
|
size_t trans_hash = 0;
|
||||||
if (flags & DFA_CONTROL_MINIMIZE_HASH_TRANS)
|
if (flags & DFA_CONTROL_MINIMIZE_HASH_TRANS)
|
||||||
trans_hash = hash_trans(*i);
|
trans_hash = hash_trans(*i);
|
||||||
pair <uint64_t, size_t> group = make_pair(perm_hash, trans_hash);
|
pair<uint64_t, size_t> group = make_pair(perm_hash, trans_hash);
|
||||||
map <pair <uint64_t, size_t>, Partition *>::iterator p = perm_map.find(group);
|
map<pair<uint64_t, size_t>, Partition *>::iterator p = perm_map.find(group);
|
||||||
if (p == perm_map.end()) {
|
if (p == perm_map.end()) {
|
||||||
Partition *part = new Partition();
|
Partition *part = new Partition();
|
||||||
part->push_back(*i);
|
part->push_back(*i);
|
||||||
@ -402,9 +400,10 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
p->second->push_back(*i);
|
p->second->push_back(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & DFA_DUMP_PROGRESS) &&
|
if ((flags & DFA_DUMP_PROGRESS) && (partitions.size() % 1000 == 0))
|
||||||
(partitions.size() % 1000 == 0))
|
cerr << "\033[2KMinimize dfa: partitions "
|
||||||
cerr << "\033[2KMinimize dfa: partitions " << partitions.size() << "\tinit " << partitions.size() << " (accept " << accept_count << ")\r";
|
<< partitions.size() << "\tinit " << partitions.size()
|
||||||
|
<< " (accept " << accept_count << ")\r";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* perm_map is no longer needed so free the memory it is using.
|
/* perm_map is no longer needed so free the memory it is using.
|
||||||
@ -414,7 +413,9 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
|
|
||||||
int init_count = partitions.size();
|
int init_count = partitions.size();
|
||||||
if (flags & DFA_DUMP_PROGRESS)
|
if (flags & DFA_DUMP_PROGRESS)
|
||||||
cerr << "\033[2KMinimize dfa: partitions " << partitions.size() << "\tinit " << init_count << " (accept " << accept_count << ")\r";
|
cerr << "\033[2KMinimize dfa: partitions " << partitions.size()
|
||||||
|
<< "\tinit " << init_count << " (accept "
|
||||||
|
<< accept_count << ")\r";
|
||||||
|
|
||||||
/* Now do repartitioning until each partition contains the set of
|
/* Now do repartitioning until each partition contains the set of
|
||||||
* states that are the same. This will happen when the partition
|
* states that are the same. This will happen when the partition
|
||||||
@ -425,20 +426,19 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
int new_part_count;
|
int new_part_count;
|
||||||
do {
|
do {
|
||||||
new_part_count = 0;
|
new_part_count = 0;
|
||||||
for (list <Partition *>::iterator p = partitions.begin();
|
for (list<Partition *>::iterator p = partitions.begin();
|
||||||
p != partitions.end(); p++) {
|
p != partitions.end(); p++) {
|
||||||
new_part = NULL;
|
new_part = NULL;
|
||||||
State *rep = *((*p)->begin());
|
State *rep = *((*p)->begin());
|
||||||
Partition::iterator next;
|
Partition::iterator next;
|
||||||
for (Partition::iterator s = ++(*p)->begin();
|
for (Partition::iterator s = ++(*p)->begin(); s != (*p)->end();) {
|
||||||
s != (*p)->end(); ) {
|
|
||||||
if (same_mappings(rep, *s)) {
|
if (same_mappings(rep, *s)) {
|
||||||
++s;
|
++s;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!new_part) {
|
if (!new_part) {
|
||||||
new_part = new Partition;
|
new_part = new Partition;
|
||||||
list <Partition *>::iterator tmp = p;
|
list<Partition *>::iterator tmp = p;
|
||||||
partitions.insert(++tmp, new_part);
|
partitions.insert(++tmp, new_part);
|
||||||
new_part_count++;
|
new_part_count++;
|
||||||
}
|
}
|
||||||
@ -454,16 +454,19 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
(*m)->partition = new_part;
|
(*m)->partition = new_part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((flags & DFA_DUMP_PROGRESS) &&
|
if ((flags & DFA_DUMP_PROGRESS) && (partitions.size() % 100 == 0))
|
||||||
(partitions.size() % 100 == 0))
|
cerr << "\033[2KMinimize dfa: partitions "
|
||||||
cerr << "\033[2KMinimize dfa: partitions " << partitions.size() << "\tinit " << init_count << " (accept " << accept_count << ")\r";
|
<< partitions.size() << "\tinit "
|
||||||
|
<< init_count << " (accept "
|
||||||
|
<< accept_count << ")\r";
|
||||||
}
|
}
|
||||||
} while(new_part_count);
|
} while (new_part_count);
|
||||||
|
|
||||||
if (partitions.size() == states.size()) {
|
if (partitions.size() == states.size()) {
|
||||||
if (flags & DFA_DUMP_STATS)
|
if (flags & DFA_DUMP_STATS)
|
||||||
cerr << "\033[2KDfa minimization no states removed: partitions " << partitions.size() << "\tinit " << init_count << " (accept " << accept_count << ")\n";
|
cerr << "\033[2KDfa minimization no states removed: partitions "
|
||||||
|
<< partitions.size() << "\tinit " << init_count
|
||||||
|
<< " (accept " << accept_count << ")\n";
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -474,7 +477,7 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
* to states within the same partitions, however this can slow
|
* to states within the same partitions, however this can slow
|
||||||
* down compressed dfa compression as there are more states,
|
* down compressed dfa compression as there are more states,
|
||||||
*/
|
*/
|
||||||
for (list <Partition *>::iterator p = partitions.begin();
|
for (list<Partition *>::iterator p = partitions.begin();
|
||||||
p != partitions.end(); p++) {
|
p != partitions.end(); p++) {
|
||||||
/* representative state for this partition */
|
/* representative state for this partition */
|
||||||
State *rep = *((*p)->begin());
|
State *rep = *((*p)->begin());
|
||||||
@ -484,8 +487,7 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
Partition *partition = rep->cases.otherwise->partition;
|
Partition *partition = rep->cases.otherwise->partition;
|
||||||
rep->cases.otherwise = *partition->begin();
|
rep->cases.otherwise = *partition->begin();
|
||||||
}
|
}
|
||||||
for (Cases::iterator c = rep->cases.begin();
|
for (Cases::iterator c = rep->cases.begin(); c != rep->cases.end(); c++) {
|
||||||
c != rep->cases.end(); c++) {
|
|
||||||
Partition *partition = c->second->partition;
|
Partition *partition = c->second->partition;
|
||||||
c->second = *partition->begin();
|
c->second = *partition->begin();
|
||||||
}
|
}
|
||||||
@ -506,9 +508,10 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
//cerr << "\n";
|
//cerr << "\n";
|
||||||
}
|
}
|
||||||
if (flags & DFA_DUMP_STATS)
|
if (flags & DFA_DUMP_STATS)
|
||||||
cerr << "\033[2KMinimized dfa: final partitions " << partitions.size() << " (accept " << final_accept << ")" << "\tinit " << init_count << " (accept " << accept_count << ")\n";
|
cerr << "\033[2KMinimized dfa: final partitions "
|
||||||
|
<< partitions.size() << " (accept " << final_accept
|
||||||
|
<< ")" << "\tinit " << init_count << " (accept "
|
||||||
|
<< accept_count << ")\n";
|
||||||
|
|
||||||
/* make sure nonmatching and start state are up to date with the
|
/* make sure nonmatching and start state are up to date with the
|
||||||
* mappings */
|
* mappings */
|
||||||
@ -528,7 +531,7 @@ void DFA::minimize(dfaflags_t flags)
|
|||||||
* that are not the representive states for their partition, they
|
* that are not the representive states for their partition, they
|
||||||
* will have a label == -1
|
* will have a label == -1
|
||||||
*/
|
*/
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); ) {
|
for (Partition::iterator i = states.begin(); i != states.end();) {
|
||||||
if ((*i)->label == -1) {
|
if ((*i)->label == -1) {
|
||||||
State *s = *i;
|
State *s = *i;
|
||||||
i = states.erase(i);
|
i = states.erase(i);
|
||||||
@ -549,83 +552,85 @@ out:
|
|||||||
/**
|
/**
|
||||||
* text-dump the DFA (for debugging).
|
* text-dump the DFA (for debugging).
|
||||||
*/
|
*/
|
||||||
void DFA::dump(ostream& os)
|
void DFA::dump(ostream & os)
|
||||||
{
|
{
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||||
if (*i == start || (*i)->accept) {
|
if (*i == start || (*i)->accept) {
|
||||||
os << **i;
|
os << **i;
|
||||||
if (*i == start)
|
if (*i == start)
|
||||||
os << " <==";
|
os << " <==";
|
||||||
if ((*i)->accept) {
|
if ((*i)->accept) {
|
||||||
os << " (0x" << hex << (*i)->accept << " " << (*i)->audit << dec << ')';
|
os << " (0x" << hex << (*i)->accept << " "
|
||||||
}
|
<< (*i)->audit << dec << ')';
|
||||||
os << endl;
|
}
|
||||||
|
os << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
os << "\n";
|
||||||
os << endl;
|
|
||||||
|
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||||
if ((*i)->cases.otherwise)
|
if ((*i)->cases.otherwise)
|
||||||
os << **i << " -> " << (*i)->cases.otherwise << endl;
|
os << **i << " -> " << (*i)->cases.otherwise << "\n";
|
||||||
for (Cases::iterator j = (*i)->cases.begin(); j != (*i)->cases.end(); j++) {
|
for (Cases::iterator j = (*i)->cases.begin();
|
||||||
os << **i << " -> " << j->second << ": " << j->first << endl;
|
j != (*i)->cases.end(); j++) {
|
||||||
|
os << **i << " -> " << j->second << ": "
|
||||||
|
<< j->first << "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
os << "\n";
|
||||||
os << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a dot (graphviz) graph from the DFA (for debugging).
|
* Create a dot (graphviz) graph from the DFA (for debugging).
|
||||||
*/
|
*/
|
||||||
void DFA::dump_dot_graph(ostream& os)
|
void DFA::dump_dot_graph(ostream & os)
|
||||||
{
|
{
|
||||||
os << "digraph \"dfa\" {" << endl;
|
os << "digraph \"dfa\" {" << "\n";
|
||||||
|
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||||
if (*i == nonmatching)
|
if (*i == nonmatching)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
os << "\t\"" << **i << "\" [" << endl;
|
os << "\t\"" << **i << "\" [" << "\n";
|
||||||
if (*i == start) {
|
if (*i == start) {
|
||||||
os << "\t\tstyle=bold" << endl;
|
os << "\t\tstyle=bold" << "\n";
|
||||||
}
|
|
||||||
uint32_t perms = (*i)->accept;
|
|
||||||
if (perms) {
|
|
||||||
os << "\t\tlabel=\"" << **i << "\\n("
|
|
||||||
<< perms << ")\"" << endl;
|
|
||||||
}
|
|
||||||
os << "\t]" << endl;
|
|
||||||
}
|
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
|
||||||
Cases& cases = (*i)->cases;
|
|
||||||
Chars excluded;
|
|
||||||
|
|
||||||
for (Cases::iterator j = cases.begin(); j != cases.end(); j++) {
|
|
||||||
if (j->second == nonmatching)
|
|
||||||
excluded.insert(j->first);
|
|
||||||
else {
|
|
||||||
os << "\t\"" << **i << "\" -> \"";
|
|
||||||
os << j->second << "\" [" << endl;
|
|
||||||
os << "\t\tlabel=\"" << j->first << "\"" << endl;
|
|
||||||
os << "\t]" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cases.otherwise && cases.otherwise != nonmatching) {
|
|
||||||
os << "\t\"" << **i << "\" -> \"" << cases.otherwise
|
|
||||||
<< "\" [" << endl;
|
|
||||||
if (!excluded.empty()) {
|
|
||||||
os << "\t\tlabel=\"[^";
|
|
||||||
for (Chars::iterator i = excluded.begin();
|
|
||||||
i != excluded.end();
|
|
||||||
i++) {
|
|
||||||
os << *i;
|
|
||||||
}
|
}
|
||||||
os << "]\"" << endl;
|
uint32_t perms = (*i)->accept;
|
||||||
}
|
if (perms) {
|
||||||
os << "\t]" << endl;
|
os << "\t\tlabel=\"" << **i << "\\n("
|
||||||
|
<< perms << ")\"" << "\n";
|
||||||
|
}
|
||||||
|
os << "\t]" << "\n";
|
||||||
}
|
}
|
||||||
}
|
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||||
os << '}' << endl;
|
Cases &cases = (*i)->cases;
|
||||||
|
Chars excluded;
|
||||||
|
|
||||||
|
for (Cases::iterator j = cases.begin(); j != cases.end(); j++) {
|
||||||
|
if (j->second == nonmatching)
|
||||||
|
excluded.insert(j->first);
|
||||||
|
else {
|
||||||
|
os << "\t\"" << **i << "\" -> \"" << j->second
|
||||||
|
<< "\" [" << "\n";
|
||||||
|
os << "\t\tlabel=\"" << j-> first << "\"\n";
|
||||||
|
os << "\t]" << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cases.otherwise && cases.otherwise != nonmatching) {
|
||||||
|
os << "\t\"" << **i << "\" -> \"" << cases.otherwise
|
||||||
|
<< "\" [" << "\n";
|
||||||
|
if (!excluded.empty()) {
|
||||||
|
os << "\t\tlabel=\"[^";
|
||||||
|
for (Chars::iterator i = excluded.begin();
|
||||||
|
i != excluded.end(); i++) {
|
||||||
|
os << *i;
|
||||||
|
}
|
||||||
|
os << "]\"" << "\n";
|
||||||
|
}
|
||||||
|
os << "\t]" << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << '}' << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -634,144 +639,137 @@ void DFA::dump_dot_graph(ostream& os)
|
|||||||
*/
|
*/
|
||||||
map<uchar, uchar> DFA::equivalence_classes(dfaflags_t flags)
|
map<uchar, uchar> DFA::equivalence_classes(dfaflags_t flags)
|
||||||
{
|
{
|
||||||
map<uchar, uchar> classes;
|
map<uchar, uchar> classes;
|
||||||
uchar next_class = 1;
|
uchar next_class = 1;
|
||||||
|
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||||
Cases& cases = (*i)->cases;
|
Cases & cases = (*i)->cases;
|
||||||
|
|
||||||
/* Group edges to the same next state together */
|
/* Group edges to the same next state together */
|
||||||
map<const State *, Chars> node_sets;
|
map<const State *, Chars> node_sets;
|
||||||
for (Cases::iterator j = cases.begin(); j != cases.end(); j++)
|
for (Cases::iterator j = cases.begin(); j != cases.end(); j++)
|
||||||
node_sets[j->second].insert(j->first);
|
node_sets[j->second].insert(j->first);
|
||||||
|
|
||||||
for (map<const State *, Chars>::iterator j = node_sets.begin();
|
for (map<const State *, Chars>::iterator j = node_sets.begin();
|
||||||
j != node_sets.end();
|
j != node_sets.end(); j++) {
|
||||||
j++) {
|
/* Group edges to the same next state together by class */
|
||||||
/* Group edges to the same next state together by class */
|
map<uchar, Chars> node_classes;
|
||||||
map<uchar, Chars> node_classes;
|
bool class_used = false;
|
||||||
bool class_used = false;
|
for (Chars::iterator k = j->second.begin();
|
||||||
for (Chars::iterator k = j->second.begin();
|
k != j->second.end(); k++) {
|
||||||
k != j->second.end();
|
pair<map<uchar, uchar>::iterator, bool> x = classes.insert(make_pair(*k, next_class));
|
||||||
k++) {
|
if (x.second)
|
||||||
pair<map<uchar, uchar>::iterator, bool> x =
|
class_used = true;
|
||||||
classes.insert(make_pair(*k, next_class));
|
pair<map<uchar, Chars>::iterator, bool> y = node_classes.insert(make_pair(x.first->second, Chars()));
|
||||||
if (x.second)
|
y.first->second.insert(*k);
|
||||||
class_used = true;
|
}
|
||||||
pair<map<uchar, Chars>::iterator, bool> y =
|
if (class_used) {
|
||||||
node_classes.insert(make_pair(x.first->second, Chars()));
|
next_class++;
|
||||||
y.first->second.insert(*k);
|
class_used = false;
|
||||||
}
|
}
|
||||||
if (class_used) {
|
for (map<uchar, Chars>::iterator k = node_classes.begin();
|
||||||
next_class++;
|
k != node_classes.end(); k++) {
|
||||||
class_used = false;
|
/**
|
||||||
}
|
* If any other characters are in the same class, move
|
||||||
for (map<uchar, Chars>::iterator k = node_classes.begin();
|
* the characters in this class into their own new
|
||||||
k != node_classes.end();
|
* class
|
||||||
k++) {
|
*/
|
||||||
/**
|
map<uchar, uchar>::iterator l;
|
||||||
* If any other characters are in the same class, move
|
for (l = classes.begin(); l != classes.end(); l++) {
|
||||||
* the characters in this class into their own new class
|
if (l->second == k->first &&
|
||||||
*/
|
k->second.find(l->first) == k->second.end()) {
|
||||||
map<uchar, uchar>::iterator l;
|
class_used = true;
|
||||||
for (l = classes.begin(); l != classes.end(); l++) {
|
break;
|
||||||
if (l->second == k->first &&
|
}
|
||||||
k->second.find(l->first) == k->second.end()) {
|
}
|
||||||
class_used = true;
|
if (class_used) {
|
||||||
break;
|
for (Chars::iterator l = k->second.begin();
|
||||||
}
|
l != k->second.end(); l++) {
|
||||||
|
classes[*l] = next_class;
|
||||||
|
}
|
||||||
|
next_class++;
|
||||||
|
class_used = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (class_used) {
|
|
||||||
for (Chars::iterator l = k->second.begin();
|
|
||||||
l != k->second.end();
|
|
||||||
l++) {
|
|
||||||
classes[*l] = next_class;
|
|
||||||
}
|
|
||||||
next_class++;
|
|
||||||
class_used = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & DFA_DUMP_EQUIV_STATS)
|
if (flags & DFA_DUMP_EQUIV_STATS)
|
||||||
fprintf(stderr, "Equiv class reduces to %d classes\n", next_class - 1);
|
fprintf(stderr, "Equiv class reduces to %d classes\n",
|
||||||
return classes;
|
next_class - 1);
|
||||||
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text-dump the equivalence classes (for debugging).
|
* Text-dump the equivalence classes (for debugging).
|
||||||
*/
|
*/
|
||||||
void dump_equivalence_classes(ostream& os, map<uchar, uchar>& eq)
|
void dump_equivalence_classes(ostream &os, map<uchar, uchar> &eq)
|
||||||
{
|
{
|
||||||
map<uchar, Chars> rev;
|
map<uchar, Chars> rev;
|
||||||
|
|
||||||
for (map<uchar, uchar>::iterator i = eq.begin(); i != eq.end(); i++) {
|
for (map<uchar, uchar>::iterator i = eq.begin(); i != eq.end(); i++) {
|
||||||
Chars& chars = rev.insert(make_pair(i->second,
|
Chars &chars = rev.insert(make_pair(i->second, Chars())).first->second;
|
||||||
Chars())).first->second;
|
chars.insert(i->first);
|
||||||
chars.insert(i->first);
|
}
|
||||||
}
|
os << "(eq):" << "\n";
|
||||||
os << "(eq):" << endl;
|
for (map<uchar, Chars>::iterator i = rev.begin(); i != rev.end(); i++) {
|
||||||
for (map<uchar, Chars>::iterator i = rev.begin(); i != rev.end(); i++) {
|
os << (int)i->first << ':';
|
||||||
os << (int)i->first << ':';
|
Chars &chars = i->second;
|
||||||
Chars& chars = i->second;
|
for (Chars::iterator j = chars.begin(); j != chars.end(); j++) {
|
||||||
for (Chars::iterator j = chars.begin(); j != chars.end(); j++) {
|
os << ' ' << *j;
|
||||||
os << ' ' << *j;
|
}
|
||||||
|
os << "\n";
|
||||||
}
|
}
|
||||||
os << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace characters with classes (which are also represented as
|
* Replace characters with classes (which are also represented as
|
||||||
* characters) in the DFA transition table.
|
* characters) in the DFA transition table.
|
||||||
*/
|
*/
|
||||||
void DFA::apply_equivalence_classes(map<uchar, uchar>& eq)
|
void DFA::apply_equivalence_classes(map<uchar, uchar> &eq)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Note: We only transform the transition table; the nodes continue to
|
* Note: We only transform the transition table; the nodes continue to
|
||||||
* contain the original characters.
|
* contain the original characters.
|
||||||
*/
|
*/
|
||||||
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
for (Partition::iterator i = states.begin(); i != states.end(); i++) {
|
||||||
map<uchar, State *> tmp;
|
map<uchar, State *> tmp;
|
||||||
tmp.swap((*i)->cases.cases);
|
tmp.swap((*i)->cases.cases);
|
||||||
for (Cases::iterator j = tmp.begin(); j != tmp.end(); j++)
|
for (Cases::iterator j = tmp.begin(); j != tmp.end(); j++)
|
||||||
(*i)->cases.cases.insert(make_pair(eq[j->first], j->second));
|
(*i)->cases.cases.
|
||||||
}
|
insert(make_pair(eq[j->first], j->second));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
typedef set<ImportantNode *> AcceptNodes;
|
typedef set <ImportantNode *>AcceptNodes;
|
||||||
map<ImportantNode *, AcceptNodes> dominance(DFA& dfa)
|
map<ImportantNode *, AcceptNodes> dominance(DFA & dfa)
|
||||||
{
|
{
|
||||||
map<ImportantNode *, AcceptNodes> is_dominated;
|
map<ImportantNode *, AcceptNodes> is_dominated;
|
||||||
|
|
||||||
for (States::iterator i = dfa.states.begin(); i != dfa.states.end(); i++) {
|
for (States::iterator i = dfa.states.begin(); i != dfa.states.end(); i++) {
|
||||||
AcceptNodes set1;
|
AcceptNodes set1;
|
||||||
for (State::iterator j = (*i)->begin(); j != (*i)->end(); j++) {
|
for (State::iterator j = (*i)->begin(); j != (*i)->end(); j++) {
|
||||||
if (AcceptNode *accept = dynamic_cast<AcceptNode *>(*j))
|
if (AcceptNode * accept = dynamic_cast<AcceptNode *>(*j))
|
||||||
set1.insert(accept);
|
set1.insert(accept);
|
||||||
}
|
}
|
||||||
for (AcceptNodes::iterator j = set1.begin(); j != set1.end(); j++) {
|
for (AcceptNodes::iterator j = set1.begin(); j != set1.end(); j++) {
|
||||||
pair<map<ImportantNode *, AcceptNodes>::iterator, bool> x =
|
pair<map<ImportantNode *, AcceptNodes>::iterator, bool> x = is_dominated.insert(make_pair(*j, set1));
|
||||||
is_dominated.insert(make_pair(*j, set1));
|
if (!x.second) {
|
||||||
if (!x.second) {
|
AcceptNodes & set2(x.first->second), set3;
|
||||||
AcceptNodes &set2(x.first->second), set3;
|
for (AcceptNodes::iterator l = set2.begin();
|
||||||
for (AcceptNodes::iterator l = set2.begin();
|
l != set2.end(); l++) {
|
||||||
l != set2.end();
|
if (set1.find(*l) != set1.end())
|
||||||
l++) {
|
set3.insert(*l);
|
||||||
if (set1.find(*l) != set1.end())
|
}
|
||||||
set3.insert(*l);
|
set3.swap(set2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
set3.swap(set2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
return is_dominated;
|
||||||
return is_dominated;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline int diff_qualifiers(uint32_t perm1, uint32_t perm2)
|
static inline int diff_qualifiers(uint32_t perm1, uint32_t perm2)
|
||||||
{
|
{
|
||||||
return ((perm1 & AA_EXEC_TYPE) && (perm2 & AA_EXEC_TYPE) &&
|
return ((perm1 & AA_EXEC_TYPE) && (perm2 & AA_EXEC_TYPE) &&
|
||||||
@ -785,79 +783,79 @@ static inline int diff_qualifiers(uint32_t perm1, uint32_t perm2)
|
|||||||
*/
|
*/
|
||||||
uint32_t accept_perms(NodeSet *state, uint32_t *audit_ctl, int *error)
|
uint32_t accept_perms(NodeSet *state, uint32_t *audit_ctl, int *error)
|
||||||
{
|
{
|
||||||
uint32_t perms = 0, exact_match_perms = 0, audit = 0, exact_audit = 0,
|
uint32_t perms = 0, exact_match_perms = 0;
|
||||||
quiet = 0, deny = 0;
|
uint32_t audit = 0, exact_audit = 0, quiet = 0, deny = 0;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
*error = 0;
|
*error = 0;
|
||||||
for (NodeSet::iterator i = state->begin(); i != state->end(); i++) {
|
for (NodeSet::iterator i = state->begin(); i != state->end(); i++) {
|
||||||
MatchFlag *match;
|
MatchFlag *match;
|
||||||
if (!(match= dynamic_cast<MatchFlag *>(*i)))
|
if (!(match = dynamic_cast<MatchFlag *>(*i)))
|
||||||
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_perms,
|
if (!is_merged_x_consistent(exact_match_perms,
|
||||||
match->flag) && error)
|
match->flag) && error)
|
||||||
*error = 1;;
|
*error = 1;;
|
||||||
exact_match_perms |= match->flag;
|
exact_match_perms |= match->flag;
|
||||||
exact_audit |= match->audit;
|
exact_audit |= match->audit;
|
||||||
} else if (dynamic_cast<DenyMatchFlag *>(match)) {
|
} else if (dynamic_cast<DenyMatchFlag *>(match)) {
|
||||||
deny |= match->flag;
|
deny |= match->flag;
|
||||||
quiet |= match->audit;
|
quiet |= match->audit;
|
||||||
} else {
|
} else {
|
||||||
if (!is_merged_x_consistent(perms, match->flag) && error)
|
if (!is_merged_x_consistent(perms, match->flag)
|
||||||
*error = 1;
|
&& error)
|
||||||
perms |= match->flag;
|
*error = 1;
|
||||||
audit |= match->audit;
|
perms |= match->flag;
|
||||||
}
|
audit |= match->audit;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//if (audit || quiet)
|
//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, "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);
|
||||||
|
|
||||||
perms |= exact_match_perms &
|
perms |= exact_match_perms & ~(AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE);
|
||||||
~(AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE);
|
|
||||||
|
|
||||||
if (exact_match_perms & AA_USER_EXEC_TYPE) {
|
if (exact_match_perms & AA_USER_EXEC_TYPE) {
|
||||||
perms = (exact_match_perms & AA_USER_EXEC_TYPE) |
|
perms = (exact_match_perms & AA_USER_EXEC_TYPE) |
|
||||||
(perms & ~AA_USER_EXEC_TYPE);
|
(perms & ~AA_USER_EXEC_TYPE);
|
||||||
audit = (exact_audit & AA_USER_EXEC_TYPE) |
|
audit = (exact_audit & AA_USER_EXEC_TYPE) |
|
||||||
(audit & ~ AA_USER_EXEC_TYPE);
|
(audit & ~AA_USER_EXEC_TYPE);
|
||||||
}
|
}
|
||||||
if (exact_match_perms & AA_OTHER_EXEC_TYPE) {
|
if (exact_match_perms & AA_OTHER_EXEC_TYPE) {
|
||||||
perms = (exact_match_perms & AA_OTHER_EXEC_TYPE) |
|
perms = (exact_match_perms & AA_OTHER_EXEC_TYPE) |
|
||||||
(perms & ~AA_OTHER_EXEC_TYPE);
|
(perms & ~AA_OTHER_EXEC_TYPE);
|
||||||
audit = (exact_audit & AA_OTHER_EXEC_TYPE) |
|
audit = (exact_audit & AA_OTHER_EXEC_TYPE) |
|
||||||
(audit & ~AA_OTHER_EXEC_TYPE);
|
(audit & ~AA_OTHER_EXEC_TYPE);
|
||||||
}
|
}
|
||||||
if (perms & AA_USER_EXEC & deny)
|
if (perms & AA_USER_EXEC & deny)
|
||||||
perms &= ~AA_USER_EXEC_TYPE;
|
perms &= ~AA_USER_EXEC_TYPE;
|
||||||
|
|
||||||
if (perms & AA_OTHER_EXEC & deny)
|
if (perms & AA_OTHER_EXEC & deny)
|
||||||
perms &= ~AA_OTHER_EXEC_TYPE;
|
perms &= ~AA_OTHER_EXEC_TYPE;
|
||||||
|
|
||||||
perms &= ~deny;
|
perms &= ~deny;
|
||||||
|
|
||||||
if (audit_ctl)
|
if (audit_ctl)
|
||||||
*audit_ctl = PACK_AUDIT_CTL(audit, quiet & deny);
|
*audit_ctl = PACK_AUDIT_CTL(audit, quiet & deny);
|
||||||
|
|
||||||
// if (perms & AA_ERROR_BIT) {
|
// if (perms & AA_ERROR_BIT) {
|
||||||
// fprintf(stderr, "error bit 0x%x\n", perms);
|
// fprintf(stderr, "error bit 0x%x\n", perms);
|
||||||
// exit(255);
|
// exit(255);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//if (perms & AA_EXEC_BITS)
|
//if (perms & AA_EXEC_BITS)
|
||||||
//fprintf(stderr, "accept perm: 0x%x\n", perms);
|
//fprintf(stderr, "accept perm: 0x%x\n", perms);
|
||||||
/*
|
/*
|
||||||
if (perms & ~AA_VALID_PERMS)
|
if (perms & ~AA_VALID_PERMS)
|
||||||
yyerror(_("Internal error accumulated invalid perm 0x%llx\n"), perms);
|
yyerror(_("Internal error accumulated invalid perm 0x%llx\n"), perms);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//if (perms & AA_CHANGE_HAT)
|
//if (perms & AA_CHANGE_HAT)
|
||||||
// fprintf(stderr, "change_hat 0x%x\n", perms);
|
// fprintf(stderr, "change_hat 0x%x\n", perms);
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
return perms;
|
return perms;
|
||||||
}
|
}
|
||||||
|
@ -46,14 +46,14 @@ typedef struct Cases {
|
|||||||
iterator begin() { return cases.begin(); }
|
iterator begin() { return cases.begin(); }
|
||||||
iterator end() { return cases.end(); }
|
iterator end() { return cases.end(); }
|
||||||
|
|
||||||
Cases() : otherwise(0) { }
|
Cases(): otherwise(0) { }
|
||||||
|
|
||||||
map<uchar, State *> cases;
|
map<uchar, State *> cases;
|
||||||
State *otherwise;
|
State *otherwise;
|
||||||
} Cases;
|
} Cases;
|
||||||
|
|
||||||
typedef list<State *> Partition;
|
typedef list<State *> Partition;
|
||||||
|
|
||||||
|
|
||||||
uint32_t accept_perms(NodeSet *state, uint32_t *audit_ctl, int *error);
|
uint32_t accept_perms(NodeSet *state, uint32_t *audit_ctl, int *error);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -72,9 +72,9 @@ uint32_t accept_perms(NodeSet *state, uint32_t *audit_ctl, int *error);
|
|||||||
*/
|
*/
|
||||||
class State {
|
class State {
|
||||||
public:
|
public:
|
||||||
State() : label (0), audit(0), accept(0), cases(), nodes(NULL) { };
|
State(): label(0), audit(0), accept(0), cases(), nodes(NULL) { };
|
||||||
State(int l): label (l), audit(0), accept(0), cases(), nodes(NULL) { };
|
State(int l): label(l), audit(0), accept(0), cases(), nodes(NULL) { };
|
||||||
State(int l, NodeSet *n) throw (int):
|
State(int l, NodeSet * n) throw(int):
|
||||||
label(l), audit(0), accept(0), cases(), nodes(n)
|
label(l), audit(0), accept(0), cases(), nodes(n)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
@ -82,7 +82,7 @@ public:
|
|||||||
/* Compute permissions associated with the State. */
|
/* Compute permissions associated with the State. */
|
||||||
accept = accept_perms(nodes, &audit, &error);
|
accept = accept_perms(nodes, &audit, &error);
|
||||||
if (error) {
|
if (error) {
|
||||||
//cerr << "Failing on accept perms " << error << "\n";
|
//cerr << "Failing on accept perms " << error << "\n";
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -96,9 +96,9 @@ public:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
ostream& operator<<(ostream& os, const State& state);
|
ostream &operator<<(ostream &os, const State &state);
|
||||||
|
|
||||||
typedef map<pair<unsigned long, NodeSet *>, State *, deref_less_than > NodeMap;
|
typedef map<pair<unsigned long, NodeSet *>, State *, deref_less_than> NodeMap;
|
||||||
/* Transitions in the DFA. */
|
/* Transitions in the DFA. */
|
||||||
|
|
||||||
/* dfa_stats - structure to group various stats about dfa creation
|
/* dfa_stats - structure to group various stats about dfa creation
|
||||||
@ -112,28 +112,32 @@ typedef struct dfa_stats {
|
|||||||
} dfa_stats_t;
|
} dfa_stats_t;
|
||||||
|
|
||||||
class DFA {
|
class DFA {
|
||||||
void dump_node_to_dfa(void);
|
void dump_node_to_dfa(void);
|
||||||
State* add_new_state(NodeMap &nodemap, pair <unsigned long, NodeSet *> index, NodeSet *nodes, dfa_stats_t &stats);
|
State *add_new_state(NodeMap &nodemap,
|
||||||
void update_state_transitions(NodeMap &nodemap, list <State *> &work_queue, State *state, dfa_stats_t &stats);
|
pair<unsigned long, NodeSet *> index,
|
||||||
State *find_target_state(NodeMap &nodemap, list <State *> &work_queue,
|
|
||||||
NodeSet *nodes, dfa_stats_t &stats);
|
NodeSet *nodes, dfa_stats_t &stats);
|
||||||
|
void update_state_transitions(NodeMap &nodemap,
|
||||||
|
list<State *> &work_queue,
|
||||||
|
State *state, dfa_stats_t &stats);
|
||||||
|
State *find_target_state(NodeMap &nodemap, list<State *> &work_queue,
|
||||||
|
NodeSet *nodes, dfa_stats_t &stats);
|
||||||
public:
|
public:
|
||||||
DFA(Node *root, dfaflags_t flags);
|
DFA(Node *root, dfaflags_t flags);
|
||||||
virtual ~DFA();
|
virtual ~DFA();
|
||||||
void remove_unreachable(dfaflags_t flags);
|
void remove_unreachable(dfaflags_t flags);
|
||||||
bool same_mappings(State *s1, State *s2);
|
bool same_mappings(State *s1, State *s2);
|
||||||
size_t hash_trans(State *s);
|
size_t hash_trans(State *s);
|
||||||
void minimize(dfaflags_t flags);
|
void minimize(dfaflags_t flags);
|
||||||
void dump(ostream& os);
|
void dump(ostream &os);
|
||||||
void dump_dot_graph(ostream& os);
|
void dump_dot_graph(ostream &os);
|
||||||
void dump_uniq_perms(const char *s);
|
void dump_uniq_perms(const char *s);
|
||||||
map<uchar, uchar> equivalence_classes(dfaflags_t flags);
|
map<uchar, uchar> equivalence_classes(dfaflags_t flags);
|
||||||
void apply_equivalence_classes(map<uchar, uchar>& eq);
|
void apply_equivalence_classes(map<uchar, uchar> &eq);
|
||||||
Node *root;
|
Node *root;
|
||||||
State *nonmatching, *start;
|
State *nonmatching, *start;
|
||||||
Partition states;
|
Partition states;
|
||||||
};
|
};
|
||||||
|
|
||||||
void dump_equivalence_classes(ostream& os, map<uchar, uchar>& eq);
|
void dump_equivalence_classes(ostream &os, map<uchar, uchar> &eq);
|
||||||
|
|
||||||
#endif /* __LIBAA_RE_HFA_H */
|
#endif /* __LIBAA_RE_HFA_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user