Below is a mostly complete patch for 
https://bugs.launchpad.net/apparmor/+bug/888077

It is currently missing support for link and mount rules. This patch is
done against the 2.8 branch, and the question is, is this something we
want in 2.8.2/3. It is rather large, and I want to rework it some before
it goes to the 2.9/3.0 branch. So the two branch will differ on this
point if we pull it into 2.8

---

diff --git a/parser/libapparmor_re/aare_rules.cc 
b/parser/libapparmor_re/aare_rules.cc
index 45664c0..5e6d652 100644
--- a/parser/libapparmor_re/aare_rules.cc
+++ b/parser/libapparmor_re/aare_rules.cc
@@ -76,6 +76,9 @@ DenyMatchFlag *deny_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE];
 MatchFlag *exec_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE];       /* mods 
+ unsafe + ix + pux * u::o */
 ExactMatchFlag *exact_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE]; /* mods 
+ unsafe + ix + pux *u::o */
 
+typedef map<pair<const char *, const char *>, AliasToNode *> AliasMap;
+AliasMap alias_map;
+
 extern "C" void aare_reset_matchflags(void)
 {
        uint32_t i, j;
@@ -92,6 +95,42 @@ extern "C" void aare_reset_matchflags(void)
        RESET_FLAGS(exec_match_flags, EXEC_MATCH_FLAGS_SIZE);
        RESET_FLAGS(exact_match_flags, EXEC_MATCH_FLAGS_SIZE);
 #undef RESET_FLAGS
+       alias_map.clear();
+}
+
+extern "C" int aare_add_alias(aare_ruleset_t *rules, const char *from,
+                             const char *to)
+{
+       Node *tree_from = NULL, *tree_to = NULL;
+       AliasToNode *node = NULL;
+
+       AliasMap::iterator i = alias_map.find(make_pair(from, to));
+       if (i == alias_map.end()) {
+               node = new AliasToNode();
+               alias_map.insert(make_pair(make_pair(from, to), node));
+       } else {
+               node = i->second;
+       }
+
+       if (regex_parse(&tree_from, from))
+               return 0;
+       if (rules->reverse)
+               flip_tree(tree_from);
+       if (rules->root)
+               rules->root = new AltNode(rules->root, new CatNode(tree_from, 
&node->from));
+       else
+               rules->root = new CatNode(tree_from, &node->from);
+
+       if (regex_parse(&tree_to, to))
+               return 0;
+       if (rules->reverse)
+               flip_tree(tree_to);
+       if (rules->root)
+               rules->root = new AltNode(rules->root, new CatNode(tree_to, 
node));
+       else
+               rules->root = new CatNode(tree_to, node);
+
+       return 1;
 }
 
 extern "C" int aare_add_rule_vec(aare_ruleset_t *rules, int deny,
diff --git a/parser/libapparmor_re/aare_rules.h 
b/parser/libapparmor_re/aare_rules.h
index 33e554c..c053530 100644
--- a/parser/libapparmor_re/aare_rules.h
+++ b/parser/libapparmor_re/aare_rules.h
@@ -40,6 +40,7 @@ int aare_add_rule(aare_ruleset_t *rules, char *rule, int 
deny, uint32_t perms,
 int aare_add_rule_vec(aare_ruleset_t *rules, int deny, uint32_t perms,
                      uint32_t audit, int count, char **rulev,
                      dfaflags_t flags);
+int aare_add_alias(aare_ruleset_t *rules, const char *from, const char *to);
 void *aare_create_dfa(aare_ruleset_t *rules, size_t *size, dfaflags_t flags);
 void aare_reset_matchflags(void);
 
diff --git a/parser/libapparmor_re/apparmor_re.h 
b/parser/libapparmor_re/apparmor_re.h
index 186899c..1fdb915 100644
--- a/parser/libapparmor_re/apparmor_re.h
+++ b/parser/libapparmor_re/apparmor_re.h
@@ -30,6 +30,10 @@ typedef enum dfaflags {
   DFA_CONTROL_REMOVE_UNREACHABLE =     1 << 7,
   DFA_CONTROL_TRANS_HIGH =     1 << 8,
 
+  DFA_COMPAT_OLD_ALIAS =       1 << 10,
+
+  DFA_DUMP_ALIAS_INFO =                1 << 11,
+  DFA_DUMP_PRE_ALIAS =         1 << 12,
   DFA_DUMP_MIN_PARTS =         1 << 13,
   DFA_DUMP_UNIQ_PERMS =                1 << 14,
   DFA_DUMP_MIN_UNIQ_PERMS =    1 << 15,
diff --git a/parser/libapparmor_re/expr-tree.h 
b/parser/libapparmor_re/expr-tree.h
index 29c2ded..651a02d 100644
--- a/parser/libapparmor_re/expr-tree.h
+++ b/parser/libapparmor_re/expr-tree.h
@@ -205,6 +205,7 @@ public:
        void compute_lastpos() { lastpos.insert(this); }
        virtual void follow(Cases &cases) = 0;
        virtual int is_accept(void) = 0;
+       virtual int is_postprocess(void) = 0;
 };
 
 /* common base class for all the different classes that contain
@@ -214,6 +215,7 @@ class CNode: public ImportantNode {
 public:
        CNode(): ImportantNode() { }
        int is_accept(void) { return false; }
+       int is_postprocess(void) { return false; }
 };
 
 /* Match one specific character (/c/). */
@@ -358,35 +360,6 @@ public:
        ostream &dump(ostream &os) { return os << "."; }
 };
 
-/**
- * Indicate that a regular expression matches. An AcceptNode itself
- * doesn't match anything, so it will never generate any transitions.
- */
-class AcceptNode: public ImportantNode {
-public:
-       AcceptNode() { }
-       int is_accept(void) { return true; }
-       void release(void)
-       {
-               /* don't delete AcceptNode via release as they are shared, and
-                * will be deleted when the table the are stored in is deleted
-                */
-       }
-
-       void follow(Cases &cases __attribute__ ((unused)))
-       {
-               /* Nothing to follow. */
-       }
-
-       /* requires accept nodes to be common by pointer */
-       int eq(Node *other)
-       {
-               if (dynamic_cast<AcceptNode *>(other))
-                       return (this == other);
-               return 0;
-       }
-};
-
 /* Match a node zero or more times. (This is a unary operator.) */
 class StarNode: public OneChildNode {
 public:
@@ -523,6 +496,55 @@ public:
        }
 };
 
+class SharedNode: public ImportantNode {
+public:
+       SharedNode() { }
+       void release(void)
+       {
+               /* don't delete SharedNodes via release as they are shared, and
+                * will be deleted when the table they are stored in is deleted
+                */
+       }
+
+       void follow(Cases &cases __attribute__ ((unused)))
+       {
+               /* Nothing to follow. */
+       }
+
+       /* requires shared nodes to be common by pointer */
+       int eq(Node *other) { return (this == other); }
+};
+
+/**
+ * Indicate that a regular expression matches. An AcceptNode itself
+ * doesn't match anything, so it will never generate any transitions.
+ */
+class AcceptNode: public SharedNode {
+public:
+       AcceptNode() { }
+       int is_accept(void) { return true; }
+       int is_postprocess(void) { return false; }
+};
+
+class MatchFlag: public AcceptNode {
+public:
+       MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit) { }
+       ostream &dump(ostream &os) { return os << '<' << flag << '>'; }
+
+       uint32_t flag;
+       uint32_t audit;
+};
+
+class ExactMatchFlag: public MatchFlag {
+public:
+       ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit) {}
+};
+
+class DenyMatchFlag: public MatchFlag {
+public:
+       DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet) {}
+};
+
 /* Traverse the syntax tree depth-first in an iterator-like manner. */
 class depth_first_traversal {
        stack<Node *>pos;
@@ -574,24 +596,4 @@ void label_nodes(Node *root);
 unsigned long hash_NodeSet(NodeSet *ns);
 void flip_tree(Node *node);
 
-
-class MatchFlag: public AcceptNode {
-public:
-       MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit) { }
-       ostream &dump(ostream &os) { return os << '<' << flag << '>'; }
-
-       uint32_t flag;
-       uint32_t audit;
-};
-
-class ExactMatchFlag: public MatchFlag {
-public:
-       ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit) {}
-};
-
-class DenyMatchFlag: public MatchFlag {
-public:
-       DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet) {}
-};
-
 #endif /* __LIBAA_RE_EXPR */
diff --git a/parser/libapparmor_re/hfa.cc b/parser/libapparmor_re/hfa.cc
index e779dd3..34a18d9 100644
--- a/parser/libapparmor_re/hfa.cc
+++ b/parser/libapparmor_re/hfa.cc
@@ -73,10 +73,13 @@ ostream &operator<<(ostream &os, const State &state)
        return os;
 }
 
-static void split_node_types(NodeSet *nodes, NodeSet **anodes, NodeSet **nnodes
-)
+typedef set<PostProcessNode *> PostNodeSet;
+
+static void split_node_types(NodeSet *nodes, NodeSet **anodes, NodeSet 
**nnodes,
+                            PostNodeSet **postnodes)
 {
        *anodes = *nnodes = NULL;
+       *postnodes = NULL;
        for (NodeSet::iterator i = nodes->begin(); i != nodes->end(); ) {
                if ((*i)->is_accept()) {
                        if (!*anodes)
@@ -84,20 +87,21 @@ static void split_node_types(NodeSet *nodes, NodeSet 
**anodes, NodeSet **nnodes
                        (*anodes)->insert(*i);
                        NodeSet::iterator k = i++;
                        nodes->erase(k);
+               } else if ((*i)->is_postprocess()) {
+                       if (!*postnodes)
+                               *postnodes = new PostNodeSet;
+                       (*postnodes)->insert((PostProcessNode *) *i);
+                       NodeSet::iterator k = i++;
+                       nodes->erase(k);
                } else
                        i++;
        }
        *nnodes = nodes;
 }
 
-State *DFA::add_new_state(NodeSet *nodes, State *other)
+State *DFA::add_new_state(NodeSet *anodes, NodeSet *nnodes, State *other)
 {
-       /* The splitting of nodes should probably get pushed down into
-        * follow(), ie. put in separate lists from the start
-        */
-       NodeSet *anodes, *nnodes;
        hashedNodeVec *nnodev;
-       split_node_types(nodes, &anodes, &nnodes);
        nnodev = nnodes_cache.insert(nnodes);
        anodes = anodes_cache.insert(anodes);
 
@@ -115,6 +119,30 @@ State *DFA::add_new_state(NodeSet *nodes, State *other)
        return x.first->second;
 }
 
+State *DFA::add_new_state(NodeSet *nodes, State *other)
+{
+       /* The splitting of nodes should probably get pushed down into
+        * follow(), ie. put in separate lists from the start
+        */
+       NodeSet *anodes, *nnodes;
+       PostNodeSet *postnodes;
+       split_node_types(nodes, &anodes, &nnodes, &postnodes);
+
+       State *state = add_new_state(anodes, nnodes, other);
+
+       /* add state to each unique post process node */
+       if (postnodes && state != nonmatching) {
+               for (PostNodeSet::iterator i = postnodes->begin();
+                    i != postnodes->end(); i++) {
+//cerr << "adding state " << *state << " to postnode " << *i << "\n";
+                       (*i)->states.insert(state);
+               }
+               dfa_postnodes.insert(postnodes->begin(), postnodes->end());
+       }
+
+       return state;
+}
+
 void DFA::update_state_transitions(State *state)
 {
        /* Compute possible transitions for state->nodes.  This is done by
@@ -169,13 +197,138 @@ void DFA::dump_node_to_dfa(void)
                cerr << "  " << (*i)->label << " <= " << (*i)->proto << "\n";
 }
 
+class NodeSetPair {
+public:
+       NodeSet *anodes;
+       NodeSet *nnodes;
+
+       NodeSetPair(void) { anodes = nnodes = NULL; }
+       NodeSetPair(NodeSet *a, NodeSet *n) { anodes = a; nnodes = n; }
+
+       void insert(ProtoState &proto) {
+               if (proto.nnodes) {
+                       if (!nnodes)
+                               nnodes = new NodeSet();
+                       nnodes->insert(proto.nnodes->begin(), 
proto.nnodes->end());
+               }
+               if (proto.anodes) {
+                       if (!anodes)
+                               anodes = new NodeSet();
+                       anodes->insert(proto.anodes->begin(), 
proto.anodes->end());
+               }
+       }
+};
+//typedef pair<NodeSet *, NodeSet *> NodeSetPair;
+typedef map<uchar, NodeSetPair> NodeSetPairMap;
+
+
+void alias_add_transitions(State &state, NodeSetPair &otherwise,
+                          NodeSetPairMap &trans)
+{
+       otherwise.insert(state.otherwise->proto);
+
+       for (StateTrans::iterator k = state.trans.begin(); k != 
state.trans.end(); k++) {
+               trans[k->first].insert(k->second->proto);
+       }
+}
+
+void DFA::update_state_for_alias(State &state, set<State *> &from,
+                                dfaflags_t flags)
+{
+       NodeSetPairMap trans;
+       NodeSetPair otherwise(NULL, NULL);
+       State *target;
+
+       if (flags & DFA_DUMP_ALIAS_INFO) {
+               cerr << "Updating state " << state << " for alias from ";
+               for (set<State *>::iterator i = from.begin(); i != from.end(); 
i++) {
+                       if ((*i) == nonmatching)
+                               continue;
+                       cerr << (**i) << " ";
+               }
+               cerr << "\n";
+       }
+
+       alias_add_transitions(state, otherwise, trans);
+       for (set<State *>::iterator i = from.begin(); i != from.end(); i++) {
+               if ((*i) == nonmatching)
+                       continue;
+               alias_add_transitions(**i, otherwise, trans);
+       }
+
+       /* now update state transitions, to the updated transitions */
+       if (otherwise.nnodes || otherwise.anodes) {
+               target = add_new_state(otherwise.anodes, otherwise.nnodes, 
nonmatching);
+               if (target != state.otherwise) {
+                       if (flags & DFA_DUMP_ALIAS_INFO) {
+                               cerr << "  updating trans otherwise from ";
+                               if (state.otherwise)
+                                       cerr << *state.otherwise;
+                               else
+                                       cerr << "<null>";
+                               cerr << " to " << *target << "\n";
+                       }
+                       state.otherwise = target;
+               }
+       }
+
+       for (NodeSetPairMap::iterator i = trans.begin(); i != trans.end(); i++) 
{
+               target = add_new_state(i->second.anodes, i->second.nnodes, 
nonmatching);
+               if (target == state.otherwise) {
+                       if (flags & DFA_DUMP_ALIAS_INFO) {
+                               cerr << "  removing trans " << i->first << " to 
";
+                               if (state.trans[i->first])
+                                       cerr << state.trans[i->first];
+                               else
+                                       cerr << "<null>";
+                               cerr << "\n";
+                       }
+                       state.trans.erase(i->first);
+               } else if (target != state.trans[i->first]) {
+                       if (flags & DFA_DUMP_ALIAS_INFO) {
+                               cerr << "  updating trans " << i->first << " 
from ";
+                               if (state.trans[i->first])
+                                       cerr << *state.trans[i->first];
+                               else
+                                       cerr << "<null>";
+                               cerr << " to " << *target << "\n";
+                       }
+                       state.trans[i->first] = target;
+               }
+       }
+}
+
+void DFA::process_work_queue(const char *header, dfaflags_t flags)
+{
+       int i = 0;
+
+       while (!work_queue.empty()) {
+               if (i % 1000 == 0 && (flags & DFA_DUMP_PROGRESS)) {
+                       cerr << "\033[2K" << header << ": queue "
+                            << work_queue.size()
+                            << "\tstates "
+                            << states.size()
+                            << "\teliminated duplicates "
+                            << node_map.dup
+                            << "\r";
+               }
+               i++;
+
+               State *from = work_queue.front();
+               work_queue.pop_front();
+
+               /* Update 'from's transitions, and if it transitions to any
+                * unknown State create it and add it to the work_queue
+                */
+               update_state_transitions(from);
+       }  /* while (!work_queue.empty()) */
+}
+
 /**
  * Construct a DFA from a syntax tree.
  */
 DFA::DFA(Node *root, dfaflags_t flags): root(root)
 {
-       int i = 0;
-
        if (flags & DFA_DUMP_PROGRESS)
                fprintf(stderr, "Creating dfa:\r");
 
@@ -205,28 +358,28 @@ DFA::DFA(Node *root, dfaflags_t flags): root(root)
         *       work_queue at any given time, thus reducing peak memory use.
         */
        work_queue.push_back(start);
+       process_work_queue("Creating dfa", flags);
 
-       while (!work_queue.empty()) {
-               if (i % 1000 == 0 && (flags & DFA_DUMP_PROGRESS)) {
-                       cerr << "\033[2KCreating dfa: queue "
-                            << work_queue.size()
-                            << "\tstates "
-                            << states.size()
-                            << "\teliminated duplicates "
-                            << node_map.dup
-                            << "\r";
-               }
-               i++;
+       /* apply post process nodes before minimization. This lets us remove
+        * nodes/states in minimization that are made no longer reachable
+        * by post processing
+        */
 
-               State *from = work_queue.front();
-               work_queue.pop_front();
+       if (!dfa_postnodes.empty()) {
+               if (flags & DFA_DUMP_PRE_ALIAS) {
+                       cerr << "DFA before alias rewrite\n";
+                       this->dump(cerr);
+               }
+               for (set<PostProcessNode *>::iterator i = dfa_postnodes.begin();
+                    i != dfa_postnodes.end(); i++) {
+                       (*i)->apply(*this, flags);
+               }
 
-               /* Update 'from's transitions, and if it transitions to any
-                * unknown State create it and add it to the work_queue
+               /* post processing could have added new states that need
+                * transitions created. So reprocess work_queue
                 */
-               update_state_transitions(from);
-
-       }  /* while (!work_queue.empty()) */
+               process_work_queue("Postprocessing dfa", flags);
+       }
 
        /* cleanup Sets of nodes used computing the DFA as they are no longer
         * needed.
@@ -256,6 +409,7 @@ DFA::DFA(Node *root, dfaflags_t flags): root(root)
         * Do not clear out uniq_anodes, as we need them for minimizations
         * diffs, unions, ...
         */
+       dfa_postnodes.clear();
        nnodes_cache.clear();
        node_map.clear();
 }
@@ -264,6 +418,7 @@ DFA::~DFA()
 {
        anodes_cache.clear();
        nnodes_cache.clear();
+       dfa_postnodes.clear();
 
        for (Partition::iterator i = states.begin(); i != states.end(); i++)
                delete *i;
diff --git a/parser/libapparmor_re/hfa.h b/parser/libapparmor_re/hfa.h
index cbcb46f..f73dca8 100644
--- a/parser/libapparmor_re/hfa.h
+++ b/parser/libapparmor_re/hfa.h
@@ -429,18 +429,23 @@ public:
        }
 };
 
+class PostProcessNode;
+
 /* Transitions in the DFA. */
 
 class DFA {
        void dump_node_to_dfa(void);
        State *add_new_state(NodeSet *nodes, State *other);
+       State *add_new_state(NodeSet *anodes, NodeSet *nnodes, State *other);
        void update_state_transitions(State *state);
+       void process_work_queue(const char *header, dfaflags_t);
 
        /* temporary values used during computations */
        NodeCache anodes_cache;
        NodeVecCache nnodes_cache;
        NodeMap node_map;
        list<State *> work_queue;
+       set<PostProcessNode *> dfa_postnodes;
 
 public:
        DFA(Node *root, dfaflags_t flags);
@@ -460,6 +465,8 @@ public:
        void dump_uniq_perms(const char *s);
        map<uchar, uchar> equivalence_classes(dfaflags_t flags);
        void apply_equivalence_classes(map<uchar, uchar> &eq);
+       void update_state_for_alias(State &state, set<State *> &from,
+                                   dfaflags_t flags);
        Node *root;
        State *nonmatching, *start;
        Partition states;
@@ -467,4 +474,47 @@ public:
 
 void dump_equivalence_classes(ostream &os, map<uchar, uchar> &eq);
 
+
+/* special post dfa construction nodes that can rewrite parts of the dfa
+ * and or cause more dfa construction. These nodes are removed as they
+ * are processed.  We use these for operations like alias and set operations
+ * on regular expressions.
+ */
+
+class PostProcessNode: public SharedNode {
+public:
+       PostProcessNode(): states() { }
+       int is_accept(void) { return false; }
+       int is_postprocess(void) { return true; }
+       virtual void apply(DFA &dfa, dfaflags_t flags) = 0;
+       ostream &dump(ostream &os) { return os << "<<" << this << ">>"; }
+
+       set<State *> states;
+};
+
+/* Alias does nothing but store a list of states that it tags, is always
+ * paired with an AliasToNode
+ */
+class AliasFromNode: public PostProcessNode {
+public:
+       AliasFromNode(): PostProcessNode() { }
+       virtual void apply(DFA &dfa, dfaflags_t flags) { }
+};
+
+/* Handle actual processing of an alias */
+class AliasToNode: public PostProcessNode {
+public:
+       AliasToNode(): PostProcessNode() { }
+       virtual void apply(DFA &dfa, dfaflags_t flags)
+       {
+               /* For each alias_to state update its transitions */
+               for (set<State *>::iterator i = states.begin();
+                    i != states.end(); i++) {
+                       dfa.update_state_for_alias(**i, from.states, flags);
+               }
+       }
+
+       AliasFromNode from;
+};
+
 #endif /* __LIBAA_RE_HFA_H */
diff --git a/parser/parser.h b/parser/parser.h
index 8199f43..38198f2 100644
--- a/parser/parser.h
+++ b/parser/parser.h
@@ -362,7 +362,8 @@ void free_symtabs(void);
 
 /* parser_alias.c */
 extern int new_alias(const char *from, const char *to);
-extern void replace_aliases(struct codomain *cod);
+extern void setup_name_aliases(struct codomain *cod);
+extern void replace_aliases(aare_ruleset_t *rules, struct codomain *cod);
 extern void free_aliases(void);
 
 /* parser_merge.c */
diff --git a/parser/parser_alias.c b/parser/parser_alias.c
index 00a4ced..d7d0c5c 100644
--- a/parser/parser_alias.c
+++ b/parser/parser_alias.c
@@ -152,7 +152,6 @@ static void process_entries(const void *nodep, VISIT value, 
int __unused level)
        }
 }
 
-static struct codomain *target_cod;
 static void process_name(const void *nodep, VISIT value, int __unused level)
 {
        struct alias_rule **t = (struct alias_rule **) nodep;
@@ -185,15 +184,42 @@ static void process_name(const void *nodep, VISIT value, 
int __unused level)
        }
 }
 
-void replace_aliases(struct codomain *cod)
+static aare_ruleset_t *target_rules;
+static void process_new_alias(const void *nodep, VISIT value, int __unused 
level)
+{
+       struct alias_rule **t = (struct alias_rule **) nodep;
+
+       if (!aare_add_alias(target_rules, (*t)->from, (*t)->to))
+               return;
+
+       return;
+}
+
+void setup_name_aliases(struct codomain *cod)
 {
        target_cod = cod;
        twalk(alias_table, process_name);
+}
 
-       if (cod->entries) {
-               target_list = cod->entries;
-               target_cod = cod;
-               twalk(alias_table, process_entries);
+void replace_aliases(aare_ruleset_t *rules, struct codomain *cod)
+{
+       target_cod = cod;
+       if (!(dfaflags & DFA_COMPAT_OLD_ALIAS)) {
+               /* forces creation of xmatch dfa if it finds an alias
+                * this does not catch all alias possibilities but
+                * the dfa alias handling in process_profile_name_xmatch
+                * handles all cases taht are missing.
+                * Probably should go to always just having an xmatch
+                */
+
+               target_rules = rules;
+               twalk(alias_table, process_new_alias);
+       } else {
+               if (cod->entries) {
+                       target_list = cod->entries;
+                       target_cod = cod;
+                       twalk(alias_table, process_entries);
+               }
        }
 }
 
diff --git a/parser/parser_main.c b/parser/parser_main.c
index 9cbfccf..6ac25f9 100644
--- a/parser/parser_main.c
+++ b/parser/parser_main.c
@@ -219,6 +219,9 @@ optflag_table_t dumpflag_table[] = {
        { 1, "equiv-stats", "Dump equivance class stats",
          DFA_DUMP_EQUIV_STATS },
        { 1, "equiv", "Dump equivance class", DFA_DUMP_EQUIV },
+       { 1, "dfa-prealias", "Dump dfa before alias rewrite",
+         DFA_DUMP_PRE_ALIAS },
+       { 1, "alias-info", "Dump alias info", DFA_DUMP_ALIAS_INFO },
        { 0, NULL, NULL, 0 },
 };
 
@@ -248,6 +251,7 @@ optflag_table_t optflag_table[] = {
          DFA_CONTROL_TRANS_HIGH },
        { 2, "compress-fast", "do faster dfa transition table compression",
          DFA_CONTROL_TRANS_HIGH },
+       { 0, "old-alias", "use old alias processesing", DFA_COMPAT_OLD_ALIAS },
        { 0, NULL, NULL, 0 },
 };
 
diff --git a/parser/parser_policy.c b/parser/parser_policy.c
index dce1b0d..4f5bb54 100644
--- a/parser/parser_policy.c
+++ b/parser/parser_policy.c
@@ -328,7 +328,6 @@ static void __process_regex(const void *nodep, const VISIT 
value,
 
        if (value == preorder || value == endorder)
                return;
-
        if (process_regex(*t) != 0) {
                PERROR(_("ERROR processing regexs for profile %s, failed to 
load\n"),
                       (*t)->name);
@@ -411,7 +410,7 @@ static void __process_alias(const void *nodep, const VISIT 
value,
        if (value == preorder || value == endorder)
                return;
 
-       replace_aliases((*t));
+       replace_aliases(NULL, (*t));
 
        if ((*t)->hat_table)
                twalk((*t)->hat_table, __process_alias);
@@ -764,11 +763,14 @@ int post_process_policy(int debug_only)
                return retval;
        }
 
-       retval = post_process_alias();
-       if (retval != 0) {
-               PERROR(_("%s: Errors found during postprocess.  Aborting.\n"),
-                      progname);
-               return retval;
+       /* only use old alias technique if new aliasing is disabled */
+       if (dfaflags & DFA_COMPAT_OLD_ALIAS) {
+               retval = post_process_alias();
+               if (retval != 0) {
+                       PERROR(_("%s: Errors found during postprocess.  
Aborting.\n"),
+                              progname);
+                       return retval;
+               }
        }
 
        retval = post_merge_rules();
diff --git a/parser/parser_regex.c b/parser/parser_regex.c
index 0ba8114..77be150 100644
--- a/parser/parser_regex.c
+++ b/parser/parser_regex.c
@@ -389,6 +389,8 @@ static int process_profile_name_xmatch(struct codomain *cod)
        pattern_t ptype;
        const char *name;
 
+       setup_name_aliases(cod);
+
        /* don't filter_slashes for profile names */
        if (cod->attachment)
                name = cod->attachment;
@@ -434,6 +436,12 @@ static int process_profile_name_xmatch(struct codomain 
*cod)
                                }
                        }
                }
+
+               /* create aliases if there is an xmatch - alias ensures */
+               if (!(dfaflags & DFA_COMPAT_OLD_ALIAS)) {
+                       replace_aliases(rule, cod);
+               }
+
                cod->xmatch = aare_create_dfa(rule, &cod->xmatch_size,
                                              dfaflags);
                aare_delete_ruleset(rule);
@@ -570,14 +578,20 @@ int process_regex(struct codomain *cod)
 {
        int error = -1;
 
-       if (regex_type == AARE_DFA) {
-               if (!process_profile_name_xmatch(cod))
-                       goto out;
+       if (!process_profile_name_xmatch(cod))
+               goto out;
 
+       if (regex_type == AARE_DFA) {
                cod->dfarules = aare_new_ruleset(0);
                if (!cod->dfarules)
                        goto out;
        }
+
+       if (!(dfaflags & DFA_COMPAT_OLD_ALIAS)) {
+               replace_aliases(cod->dfarules, cod);
+/* TODO: alias for link rules*/
+       }
+
        if (!post_process_entries(cod))
                goto out;
 
@@ -1075,6 +1089,8 @@ int process_policydb(struct codomain *cod)
        if (!post_process_policydb_ents(cod))
                goto out;
 
+       /* TODO: alias processing for mount rules */
+
        if (regex_type == AARE_DFA && cod->policy_rule_count > 0) {
                cod->policy_dfa = aare_create_dfa(cod->policy_rules,
                                                  &cod->policy_dfa_size,

-- 
AppArmor mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to