[apparmor] [patch 01/21] Convert mount and dbus to be subclasses of a generic rule class

john.johansen at canonical.com john.johansen at canonical.com
Mon Mar 17 23:29:11 UTC 2014


This will simplify add new features as most of the code can reside in
its own class. There are still things to improve but its a start.

Signed-off-by: John Johansen <john.johansen at canonical.com>

---
 parser/Makefile          |   13 -
 parser/dbus.c            |  405 +++++++++++++++++++++++++---------
 parser/dbus.h            |   32 ++
 parser/mount.c           |  551 +++++++++++++++++++++++++++++++++++++----------
 parser/mount.h           |   32 +-
 parser/parser.h          |   22 +
 parser/parser_misc.c     |  101 --------
 parser/parser_policy.c   |   29 --
 parser/parser_regex.c    |  489 -----------------------------------------
 parser/parser_variable.c |   66 +----
 parser/parser_yacc.y     |   51 ++--
 parser/profile.cc        |    6 
 parser/profile.h         |    7 
 parser/rule.c            |   23 +
 parser/rule.h            |   51 ++++
 15 files changed, 940 insertions(+), 938 deletions(-)

--- 2.9-test.orig/parser/Makefile
+++ 2.9-test/parser/Makefile
@@ -79,8 +79,8 @@
 SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
        parser_main.c parser_misc.c parser_merge.c parser_symtab.c \
        parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \
-       parser_alias.c mount.c dbus.c lib.c profile.cc
-HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h
+       parser_alias.c mount.c dbus.c lib.c profile.cc rule.c
+HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h rule.h
 TOOLS = apparmor_parser
 
 OBJECTS = $(SRCS:.c=.o)
@@ -188,7 +188,7 @@
 parser_yacc.c parser_yacc.h: parser_yacc.y parser.h profile.h
 	$(YACC) $(YFLAGS) -o parser_yacc.c parser_yacc.y
 
-parser_lex.c: parser_lex.l parser_yacc.h parser.h profile.h
+parser_lex.c: parser_lex.l parser_yacc.h parser.h profile.h mount.h dbus.h
 	$(LEX) ${LEXFLAGS} -o$@ $<
 
 parser_lex.o: parser_lex.c parser.h parser_yacc.h
@@ -230,18 +230,21 @@
 parser_common.o: parser_common.c parser.h
 	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
 
-mount.o: mount.c mount.h parser.h immunix.h
+mount.o: mount.c mount.h parser.h immunix.h rule.h
 	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
 
 lib.o: lib.c lib.h parser.h
 	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
 
-dbus.o: dbus.c dbus.h parser.h immunix.h parser_yacc.h $(APPARMOR_H)
+dbus.o: dbus.c dbus.h parser.h immunix.h parser_yacc.h rule.h $(APPARMOR_H)
 	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
 
 profile.o: profile.cc profile.h parser.h
 	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
 
+rule.o: rule.c rule.h policydb.h
+	$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
+
 parser_version.h: Makefile
 	@echo \#define PARSER_VERSION \"$(VERSION)\" > .ver
 	@mv -f .ver $@
--- 2.9-test.orig/parser/dbus.c
+++ 2.9-test/parser/dbus.c
@@ -20,23 +20,91 @@
 #include <string.h>
 #include <sys/apparmor.h>
 
+#include <iomanip>
+#include <string>
+#include <iostream>
+#include <sstream>
+
 #include "parser.h"
 #include "profile.h"
 #include "parser_yacc.h"
 #include "dbus.h"
 
-void free_dbus_entry(struct dbus_entry *ent)
+#define _(s) gettext(s)
+
+static int parse_dbus_sub_mode(const char *str_mode, int *result, int fail, const char *mode_desc __unused)
 {
-	if (!ent)
-		return;
-	free(ent->bus);
-	free(ent->name);
-	free(ent->peer_label);
-	free(ent->path);
-	free(ent->interface);
-	free(ent->member);
+	int mode = 0;
+	const char *p;
+
+	PDEBUG("Parsing DBus mode: %s\n", str_mode);
+
+	if (!str_mode)
+		return 0;
+
+	p = str_mode;
+	while (*p) {
+		char current = *p;
+		char lower;
+
+reeval:
+		switch (current) {
+		case COD_READ_CHAR:
+			PDEBUG("Parsing DBus mode: found %s READ\n", mode_desc);
+			mode |= AA_DBUS_RECEIVE;
+			break;
+
+		case COD_WRITE_CHAR:
+			PDEBUG("Parsing DBus mode: found %s WRITE\n",
+			       mode_desc);
+			mode |= AA_DBUS_SEND;
+			break;
+
+		/* error cases */
+
+		default:
+			lower = tolower(current);
+			switch (lower) {
+			case COD_READ_CHAR:
+			case COD_WRITE_CHAR:
+				PDEBUG("Parsing DBus mode: found invalid upper case char %c\n",
+				       current);
+				warn_uppercase();
+				current = lower;
+				goto reeval;
+				break;
+			default:
+				if (fail)
+					yyerror(_("Internal: unexpected DBus mode character '%c' in input"),
+						current);
+				else
+					return 0;
+				break;
+			}
+			break;
+		}
+		p++;
+	}
 
-	free(ent);
+	PDEBUG("Parsed DBus mode: %s 0x%x\n", str_mode, mode);
+
+	*result = mode;
+	return 1;
+}
+
+int parse_dbus_mode(const char *str_mode, int *mode, int fail)
+{
+	*mode = 0;
+	if (!parse_dbus_sub_mode(str_mode, mode, fail, ""))
+		return 0;
+	if (*mode & ~AA_VALID_DBUS_PERMS) {
+		if (fail)
+			yyerror(_("Internal error generated invalid DBus perm 0x%x\n"),
+				  mode);
+		else
+			return 0;
+	}
+	return 1;
 }
 
 static int list_len(struct value_list *v)
@@ -60,7 +128,7 @@
 	cond_ent->vals->value = NULL;
 }
 
-static void move_conditionals(struct dbus_entry *ent, struct cond_entry *conds)
+void dbus_rule::move_conditionals(struct cond_entry *conds)
 {
 	struct cond_entry *cond_ent;
 
@@ -73,17 +141,17 @@
 				cond_ent->name);
 
 		if (strcmp(cond_ent->name, "bus") == 0) {
-			move_conditional_value(&ent->bus, cond_ent);
+			move_conditional_value(&bus, cond_ent);
 		} else if (strcmp(cond_ent->name, "name") == 0) {
-			move_conditional_value(&ent->name, cond_ent);
+			move_conditional_value(&name, cond_ent);
 		} else if (strcmp(cond_ent->name, "label") == 0) {
-			move_conditional_value(&ent->peer_label, cond_ent);
+			move_conditional_value(&peer_label, cond_ent);
 		} else if (strcmp(cond_ent->name, "path") == 0) {
-			move_conditional_value(&ent->path, cond_ent);
+			move_conditional_value(&path, cond_ent);
 		} else if (strcmp(cond_ent->name, "interface") == 0) {
-			move_conditional_value(&ent->interface, cond_ent);
+			move_conditional_value(&interface, cond_ent);
 		} else if (strcmp(cond_ent->name, "member") == 0) {
-			move_conditional_value(&ent->member, cond_ent);
+			move_conditional_value(&member, cond_ent);
 		} else {
 			yyerror("invalid dbus conditional \"%s\"\n",
 				cond_ent->name);
@@ -91,129 +159,252 @@
 	}
 }
 
-struct dbus_entry *new_dbus_entry(int mode, struct cond_entry *conds,
-				  struct cond_entry *peer_conds)
+dbus_rule::dbus_rule(int mode_p, struct cond_entry *conds,
+		     struct cond_entry *peer_conds):
+	bus(NULL), name(NULL), peer_label(NULL), path(NULL), interface(NULL), member(NULL),
+	mode(0), audit(0), deny(0)
 {
-	struct dbus_entry *ent;
 	int name_is_subject_cond = 0, message_rule = 0, service_rule = 0;
 
-	ent = (struct dbus_entry*) calloc(1, sizeof(struct dbus_entry));
-	if (!ent)
-		goto out;
-
 	/* Move the global/subject conditionals over & check the results */
-	move_conditionals(ent, conds);
-	if (ent->name)
+	move_conditionals(conds);
+	if (name)
 		name_is_subject_cond = 1;
-	if (ent->peer_label)
+	if (peer_label)
 		yyerror("dbus \"label\" conditional can only be used inside of the \"peer=()\" grouping\n");
 
 	/* Move the peer conditionals */
-	move_conditionals(ent, peer_conds);
+	move_conditionals(peer_conds);
 
-	if (ent->path || ent->interface || ent->member || ent->peer_label ||
-	    (ent->name && !name_is_subject_cond))
+	if (path || interface || member || peer_label ||
+	    (name && !name_is_subject_cond))
 		message_rule = 1;
 
-	if (ent->name && name_is_subject_cond)
+	if (name && name_is_subject_cond)
 		service_rule = 1;
 
 	if (message_rule && service_rule)
 		yyerror("dbus rule contains message conditionals and service conditionals\n");
 
 	/* Copy mode. If no mode was specified, assign an implied mode. */
-	if (mode) {
-		ent->mode = mode;
-		if (ent->mode & ~AA_VALID_DBUS_PERMS)
+	if (mode_p) {
+		mode = mode_p;
+		if (mode & ~AA_VALID_DBUS_PERMS)
 			yyerror("mode contains unknown dbus accesss\n");
-		else if (message_rule && (ent->mode & AA_DBUS_BIND))
+		else if (message_rule && (mode & AA_DBUS_BIND))
 			yyerror("dbus \"bind\" access cannot be used with message rule conditionals\n");
-		else if (service_rule && (ent->mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)))
+		else if (service_rule && (mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)))
 			yyerror("dbus \"send\" and/or \"receive\" accesses cannot be used with service rule conditionals\n");
-		else if (ent->mode & AA_DBUS_EAVESDROP &&
-			 (ent->path || ent->interface || ent->member ||
-			  ent->peer_label || ent->name)) {
+		else if (mode & AA_DBUS_EAVESDROP &&
+			 (path || interface || member ||
+			  peer_label || name)) {
 			yyerror("dbus \"eavesdrop\" access can only contain a bus conditional\n");
 		}
 	} else {
 		if (message_rule)
-			ent->mode = (AA_DBUS_SEND | AA_DBUS_RECEIVE);
+			mode = (AA_DBUS_SEND | AA_DBUS_RECEIVE);
 		else if (service_rule)
-			ent->mode = (AA_DBUS_BIND);
+			mode = (AA_DBUS_BIND);
 		else
-			ent->mode = AA_VALID_DBUS_PERMS;
+			mode = AA_VALID_DBUS_PERMS;
 	}
 
-out:
 	free_cond_list(conds);
 	free_cond_list(peer_conds);
-	return ent;
 }
 
-struct dbus_entry *dup_dbus_entry(struct dbus_entry *orig)
+ostream &dbus_rule::dump(ostream &os)
+{
+	if (audit)
+		os << "audit ";
+	if (deny)
+		os << "deny ";
+
+	os << "dbus ( ";
+
+	if (mode & AA_DBUS_SEND)
+		os << "send ";
+	if (mode & AA_DBUS_RECEIVE)
+		os << "receive ";
+	if (mode & AA_DBUS_BIND)
+		os << "bind ";
+	if (mode & AA_DBUS_EAVESDROP)
+		os << "eavesdrop ";
+	os << ")";
+
+	if (bus)
+		os << " bus=\"" << bus << "\"";
+	if ((mode & AA_DBUS_BIND) && name)
+		os << " name=\"" << name << "\"";
+	if (path)
+		os << " path=\"" << path << "\"";
+	if (interface)
+		os << " interface=\"" << interface << "\"";
+	if (member)
+		os << " member=\"" << member << os << "\"";
+
+	if (!(mode & AA_DBUS_BIND) && (peer_label || name)) {
+		os << " peer=( ";
+		if (peer_label)
+			os << "label=\"" << peer_label << "\" ";
+		if (name)
+			os << "name=\"" << name << "\" ";
+		os << ")";
+	}
+
+	os << ",\n";
+
+	return os;
+}
+
+int dbus_rule::expand_variables(void)
+{
+	int error = expand_entry_variables(&bus);
+	if (error)
+		return error;
+	error = expand_entry_variables(&name);
+	if (error)
+		return error;
+	error = expand_entry_variables(&peer_label);
+	if (error)
+		return error;
+	error = expand_entry_variables(&path);
+	if (error)
+		return error;
+	error = expand_entry_variables(&interface);
+	if (error)
+		return error;
+	error = expand_entry_variables(&member);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+/* do we want to warn once/profile or just once per compile?? */
+static void warn_once(const char *name)
+{
+	static const char *warned_name = NULL;
+
+	if (warned_name != name) {
+		cerr << "Warning from profile " << name << " (";
+		if (current_filename)
+			cerr << current_filename;
+		else
+			cerr << "stdin";
+		cerr << ") dbus rules not enforced\n";
+		warned_name = name;
+	}
+}
+
+int dbus_rule::gen_policy_re(Profile &prof)
 {
-	struct dbus_entry *ent = NULL;
-	ent = (struct dbus_entry *) calloc(1, sizeof(struct dbus_entry));
-	if (!ent)
-		return NULL;
-
-	DUP_STRING(orig, ent, bus, err);
-	DUP_STRING(orig, ent, name, err);
-	DUP_STRING(orig, ent, peer_label, err);
-	DUP_STRING(orig, ent, path, err);
-	DUP_STRING(orig, ent, interface, err);
-	DUP_STRING(orig, ent, member, err);
-	ent->mode = orig->mode;
-	ent->audit = orig->audit;
-	ent->deny = orig->deny;
-
-	ent->next = orig->next;
-
-	return ent;
-
-err:
-	free_dbus_entry(ent);
-	return NULL;
-}
-
-void print_dbus_entry(struct dbus_entry *ent)
-{
-	if (ent->audit)
-		fprintf(stderr, "audit ");
-	if (ent->deny)
-		fprintf(stderr, "deny ");
-
-	fprintf(stderr, "dbus ( ");
-
-	if (ent->mode & AA_DBUS_SEND)
-		fprintf(stderr, "send ");
-	if (ent->mode & AA_DBUS_RECEIVE)
-		fprintf(stderr, "receive ");
-	if (ent->mode & AA_DBUS_BIND)
-		fprintf(stderr, "bind ");
-	if (ent->mode & AA_DBUS_EAVESDROP)
-		fprintf(stderr, "eavesdrop ");
-	fprintf(stderr, ")");
-
-	if (ent->bus)
-		fprintf(stderr, " bus=\"%s\"", ent->bus);
-	if ((ent->mode & AA_DBUS_BIND) && ent->name)
-		fprintf(stderr, " name=\"%s\"", ent->name);
-	if (ent->path)
-		fprintf(stderr, " path=\"%s\"", ent->path);
-	if (ent->interface)
-		fprintf(stderr, " interface=\"%s\"", ent->interface);
-	if (ent->member)
-		fprintf(stderr, " member=\"%s\"", ent->member);
-
-	if (!(ent->mode & AA_DBUS_BIND) && (ent->peer_label || ent->name)) {
-		fprintf(stderr, " peer=( ");
-		if (ent->peer_label)
-			fprintf(stderr, "label=\"%s\" ", ent->peer_label);
-		if (ent->name)
-			fprintf(stderr, "name=\"%s\" ", ent->name);
-		fprintf(stderr, ")");
+	std::string busbuf;
+	std::string namebuf;
+	std::string peer_labelbuf;
+	std::string pathbuf;
+	std::string ifacebuf;
+	std::string memberbuf;
+	std::ostringstream buffer;
+	const char *vec[6];
+
+	pattern_t ptype;
+	int pos;
+
+	if (!kernel_supports_dbus) {
+		warn_once(prof.name);
+		return RULE_NOT_SUPPORTED;
+	}
+
+	buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_DBUS;
+	busbuf.append(buffer.str());
+
+	if (bus) {
+		ptype = convert_aaregex_to_pcre(bus, 0, busbuf, &pos);
+		if (ptype == ePatternInvalid)
+			goto fail;
+	} else {
+		/* match any char except \000 0 or more times */
+		busbuf.append(default_match_pattern);
 	}
+	vec[0] = busbuf.c_str();
+
+	if (name) {
+		ptype = convert_aaregex_to_pcre(name, 0, namebuf, &pos);
+		if (ptype == ePatternInvalid)
+			goto fail;
+		vec[1] = namebuf.c_str();
+	} else {
+		/* match any char except \000 0 or more times */
+		vec[1] = default_match_pattern;
+	}
+
+	if (peer_label) {
+		ptype = convert_aaregex_to_pcre(peer_label, 0,
+						peer_labelbuf, &pos);
+		if (ptype == ePatternInvalid)
+			goto fail;
+		vec[2] = peer_labelbuf.c_str();
+	} else {
+		/* match any char except \000 0 or more times */
+		vec[2] = default_match_pattern;
+	}
+
+	if (path) {
+		ptype = convert_aaregex_to_pcre(path, 0, pathbuf, &pos);
+		if (ptype == ePatternInvalid)
+			goto fail;
+		vec[3] = pathbuf.c_str();
+	} else {
+		/* match any char except \000 0 or more times */
+		vec[3] = default_match_pattern;
+	}
+
+	if (interface) {
+		ptype = convert_aaregex_to_pcre(interface, 0, ifacebuf, &pos);
+		if (ptype == ePatternInvalid)
+			goto fail;
+		vec[4] = ifacebuf.c_str();
+	} else {
+		/* match any char except \000 0 or more times */
+		vec[4] = default_match_pattern;
+	}
+
+	if (member) {
+		ptype = convert_aaregex_to_pcre(member, 0, memberbuf, &pos);
+		if (ptype == ePatternInvalid)
+			goto fail;
+		vec[5] = memberbuf.c_str();
+	} else {
+		/* match any char except \000 0 or more times */
+		vec[5] = default_match_pattern;
+	}
+
+	if (mode & AA_DBUS_BIND) {
+		if (!aare_add_rule_vec(prof.policy.rules, deny,
+				       mode & AA_DBUS_BIND,
+				       audit & AA_DBUS_BIND,
+				       2, vec, dfaflags))
+			goto fail;
+	}
+	if (mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
+		if (!aare_add_rule_vec(prof.policy.rules, deny,
+				mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
+				audit & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
+				6, vec, dfaflags))
+			goto fail;
+	}
+	if (mode & AA_DBUS_EAVESDROP) {
+		if (!aare_add_rule_vec(prof.policy.rules, deny,
+				mode & AA_DBUS_EAVESDROP,
+				audit & AA_DBUS_EAVESDROP,
+				1, vec, dfaflags))
+			goto fail;
+	}
+
+	prof.policy.count++;
+	return RULE_OK;
 
-	fprintf(stderr, ",\n");
+fail:
+	return RULE_ERROR;
 }
--- 2.9-test.orig/parser/dbus.h
+++ 2.9-test/parser/dbus.h
@@ -20,8 +20,14 @@
 #define __AA_DBUS_H
 
 #include "parser.h"
+#include "rule.h"
+#include "profile.h"
 
-struct dbus_entry {
+extern int parse_dbus_mode(const char *str_mode, int *mode, int fail);
+
+class dbus_rule: public rule_t {
+	void move_conditionals(struct cond_entry *conds);
+public:
 	char *bus;
 	/**
 	 * Be careful! ->name can be the subject or the peer name, depending on
@@ -37,13 +43,23 @@
 	int audit;
 	int deny;
 
-	struct dbus_entry *next;
-};
+	dbus_rule(int mode_p, struct cond_entry *conds,
+		  struct cond_entry *peer_conds);
+	virtual ~dbus_rule() {
+		free(bus);
+		free(name);
+		free(peer_label);
+		free(path);
+		free(interface);
+		free(member);
+	};
+
+	virtual ostream &dump(ostream &os);
+	virtual int expand_variables(void);
+	virtual int gen_policy_re(Profile &prof);
+	virtual void post_process(Profile &prof __unused) { };
 
-void free_dbus_entry(struct dbus_entry *ent);
-struct dbus_entry *new_dbus_entry(int mode, struct cond_entry *conds,
-				  struct cond_entry *peer_conds);
-struct dbus_entry *dup_dbus_entry(struct dbus_entry *ent);
-void print_dbus_entry(struct dbus_entry *ent);
+
+};
 
 #endif /* __AA_DBUS_H */
--- 2.9-test.orig/parser/mount.c
+++ 2.9-test/parser/mount.c
@@ -215,8 +215,12 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <linux/limits.h>
+#include <iostream>
 
 #include "parser.h"
+#include "policydb.h"
+#include "profile.h"
 #include "mount.h"
 
 struct mnt_keyword_table {
@@ -389,146 +393,471 @@
 	return list;
 }
 
-struct mnt_entry *new_mnt_entry(struct cond_entry *src_conds, char *device,
-				struct cond_entry *dst_conds __unused, char *mnt_point,
-				int allow)
+mnt_rule::mnt_rule(struct cond_entry *src_conds, char *device_p,
+		   struct cond_entry *dst_conds __unused, char *mnt_point_p,
+		   int allow_p):
+	mnt_point(mnt_point_p), device(device_p), trans(NULL), opts(NULL),
+	audit(0), deny(0)
 {
 	/* FIXME: dst_conds are ignored atm */
+	aa_class = AA_CLASS_MOUNT;
 
-	struct mnt_entry *ent;
-	ent = (struct mnt_entry *) calloc(1, sizeof(struct mnt_entry));
-	if (ent) {
-		ent->mnt_point = mnt_point;
-		ent->device = device;
-		ent->dev_type = extract_fstype(&src_conds);
-
-		ent->flags = 0;
-		ent->inv_flags = 0;
-
-		if (src_conds) {
-			unsigned int flags = 0, inv_flags = 0;
-			struct value_list *list = extract_options(&src_conds, 0);
-
-			ent->opts = extract_options(&src_conds, 1);
-			if (ent->opts)
-				ent->flags = extract_flags(&ent->opts,
-							   &ent->inv_flags);
-
-			if (list) {
-				flags = extract_flags(&list, &inv_flags);
-				/* these flags are optional so set both */
-				flags |= inv_flags;
-				inv_flags |= flags;
-
-				ent->flags |= flags;
-				ent->inv_flags |= inv_flags;
-
-				if (ent->opts)
-					list_append(ent->opts, list);
-				else if (list)
-					ent->opts = list;
-			}
-		}
+	dev_type = extract_fstype(&src_conds);
 
-		if (allow & AA_DUMMY_REMOUNT) {
-			allow = AA_MAY_MOUNT;
-			ent->flags |= MS_REMOUNT;
-			ent->inv_flags = 0;
-		} else if (!(ent->flags | ent->inv_flags)) {
-			/* no flag options, and not remount, allow everything */
-			ent->flags = MS_ALL_FLAGS;
-			ent->inv_flags = MS_ALL_FLAGS;
-		}
+	if (src_conds) {
+		struct value_list *list = extract_options(&src_conds, 0);
 
-		ent->allow = allow;
+		opts = extract_options(&src_conds, 1);
+		if (opts)
+			flags = extract_flags(&opts, &inv_flags);
 
-		if (src_conds) {
-			PERROR("  unsupported mount conditions\n");
-			exit(1);
+		if (list) {
+			unsigned int tmpflags, tmpinv_flags = 0;
+
+			tmpflags = extract_flags(&list, &tmpinv_flags);
+			/* these flags are optional so set both */
+			tmpflags |= tmpinv_flags;
+			tmpinv_flags |= tmpflags;
+
+			flags |= tmpflags;
+			inv_flags |= tmpinv_flags;
+
+			if (opts)
+				list_append(opts, list);
+			else if (list)
+				opts = list;
 		}
 	}
 
-	return ent;
+	if (allow_p & AA_DUMMY_REMOUNT) {
+		allow_p = AA_MAY_MOUNT;
+		flags |= MS_REMOUNT;
+		inv_flags = 0;
+	} else if (!(flags | inv_flags)) {
+		/* no flag options, and not remount, allow everything */
+		flags = MS_ALL_FLAGS;
+		inv_flags = MS_ALL_FLAGS;
+	}
+
+	allow = allow_p;
+
+	if (src_conds) {
+		PERROR("  unsupported mount conditions\n");
+		exit(1);
+	}
 }
 
-void free_mnt_entry(struct mnt_entry *ent)
+ostream &mnt_rule::dump(ostream &os)
 {
-	if (!ent)
-		return;
+	if (allow & AA_MAY_MOUNT)
+		os << "mount";
+	else if (allow & AA_MAY_UMOUNT)
+		os << "umount";
+	else if (allow & AA_MAY_PIVOTROOT)
+		os << "pivotroot";
+	else
+		os << "error: unknonwn mount perm";
 
-	free_mnt_entry(ent->next);
-	free_value_list(ent->opts);
-	free_value_list(ent->dev_type);
-	free(ent->device);
-	free(ent->mnt_point);
-	free(ent->trans);
+	os << " (0x" << hex << flags << " - 0x" << inv_flags << ") ";
+	if (dev_type) {
+		os << " type=";
+		print_value_list(dev_type);
+	}
+	if (opts) {
+		os << " options=";
+		print_value_list(opts);
+	}
+	if (device)
+		os << " " << device;
+	if (mnt_point)
+		os << " -> " << mnt_point;
+	if (trans)
+		os << " -> " << trans;
+
+	const char *prefix = deny ? "deny" : "";
+	os << " " << prefix << "(0x" << hex << allow << "/0x" << audit << ")";
+	os << ",\n";
 
-	free(ent);
+	return os;
 }
 
-struct mnt_entry *dup_mnt_entry(struct mnt_entry *orig)
+/* does not currently support expansion of vars in options */
+int mnt_rule::expand_variables(void)
 {
-	struct mnt_entry *entry = NULL;
+	int error = 0;
 
-	entry = (struct mnt_entry *) calloc(1, sizeof(struct mnt_entry));
-	if (!entry)
-		return NULL;
+	error = expand_entry_variables(&mnt_point);
+	if (error)
+		return error;
+	error = expand_entry_variables(&device);
+	if (error)
+		return error;
+	error = expand_entry_variables(&trans);
+	if (error)
+		return error;
 
-	DUP_STRING(orig, entry, mnt_point, err);
-	DUP_STRING(orig, entry, device, err);
-	DUP_STRING(orig, entry, trans, err);
+	return 0;
+}
 
-	entry->dev_type = dup_value_list(orig->dev_type);
-	if (orig->dev_type && !(entry->dev_type))
-		goto err;
+static int build_mnt_flags(char *buffer, int size, unsigned int flags,
+			   unsigned int inv_flags)
+{
+	char *p = buffer;
+	int i, len = 0;
 
-	entry->opts = dup_value_list(orig->opts);
-	if (orig->opts && !(entry->opts))
-		goto err;
+	if (flags == MS_ALL_FLAGS) {
+		/* all flags are optional */
+		len = snprintf(p, size, "%s", default_match_pattern);
+		if (len < 0 || len >= size)
+			return FALSE;
+		return TRUE;
+	}
+	for (i = 0; i <= 31; ++i) {
+		if ((flags & inv_flags) & (1 << i))
+			len = snprintf(p, size, "(\\x%02x|)", i + 1);
+		else if (flags & (1 << i))
+			len = snprintf(p, size, "\\x%02x", i + 1);
+		else	/* no entry = not set */
+			continue;
+
+		if (len < 0 || len >= size)
+			return FALSE;
+		p += len;
+		size -= len;
+	}
 
-	entry->flags = orig->flags;
-	entry->inv_flags = orig->inv_flags;
+	/* this needs to go once the backend is updated. */
+	if (buffer == p) {
+		/* match nothing - use impossible 254 as regex parser doesn't
+		 * like the empty string
+		 */
+		if (size < 9)
+			return FALSE;
 
-	entry->allow = orig->allow;
-	entry->audit = orig->audit;
-	entry->deny = orig->deny;
+		strcpy(p, "(\\xfe|)");
+	}
 
-	entry->next = orig->next;
+	return TRUE;
+}
 
-	return entry;
+static int build_mnt_opts(std::string& buffer, struct value_list *opts)
+{
+	struct value_list *ent;
+	pattern_t ptype;
+	int pos;
+
+	if (!opts) {
+		buffer.append(default_match_pattern);
+		return TRUE;
+	}
+
+	list_for_each(opts, ent) {
+		ptype = convert_aaregex_to_pcre(ent->value, 0, buffer, &pos);
+		if (ptype == ePatternInvalid)
+			return FALSE;
+
+		if (ent->next)
+			buffer.append(",");
+	}
 
-err:
-	free_mnt_entry(entry);
-	return NULL;
+	return TRUE;
 }
 
-void print_mnt_entry(struct mnt_entry *entry)
+/* do we want to warn once/profile or just once per compile?? */
+static void warn_once(const char *name)
 {
-	if (entry->allow & AA_MAY_MOUNT)
-		fprintf(stderr, "mount");
-	else if (entry->allow & AA_MAY_UMOUNT)
-		fprintf(stderr, "umount");
-	else if (entry->allow & AA_MAY_PIVOTROOT)
-		fprintf(stderr, "pivotroot");
-	else
-		fprintf(stderr, "error: unknonwn mount perm");
+	static const char *warned_name = NULL;
+
+	if (warned_name != name) {
+		cerr << "Warning from profile " << name << " (";
+		if (current_filename)
+			cerr << current_filename;
+		else
+			cerr << "stdin";
+		cerr << ") mount rules not enforced\n";
+		warned_name = name;
+	}
+}
+
+int mnt_rule::gen_policy_re(Profile &prof)
+{
+	std::string mntbuf;
+	std::string devbuf;
+	std::string typebuf;
+	char flagsbuf[PATH_MAX + 3];
+	std::string optsbuf;
+	char class_mount_hdr[64];
+	const char *vec[5];
+	int count = 0;
+	unsigned int tmpflags, tmpinv_flags;
+
+	if (!kernel_supports_mount) {
+		warn_once(prof.name);
+		return RULE_NOT_SUPPORTED;
+	}
+
+	sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
+
+	/* a single mount rule may result in multiple matching rules being
+	 * created in the backend to cover all the possible choices
+	 */
+
+	if ((allow & AA_MAY_MOUNT) && (flags & MS_REMOUNT)
+	    && !device && !dev_type) {
+		int tmpallow;
+		/* remount can't be conditional on device and type */
+		/* rule class single byte header */
+		mntbuf.assign(class_mount_hdr);
+		if (mnt_point) {
+			/* both device && mnt_point or just mnt_point */
+			if (!convert_entry(mntbuf, mnt_point))
+				goto fail;
+			vec[0] = mntbuf.c_str();
+		} else {
+			if (!convert_entry(mntbuf, device))
+				goto fail;
+			vec[0] = mntbuf.c_str();
+		}
+		/* skip device */
+		vec[1] = default_match_pattern;
+		/* skip type */
+		vec[2] = default_match_pattern;
+
+		tmpflags = flags;
+		tmpinv_flags = inv_flags;
+		if (tmpflags != MS_ALL_FLAGS)
+			tmpflags &= MS_REMOUNT_FLAGS;
+		if (tmpinv_flags != MS_ALL_FLAGS)
+			tmpflags &= MS_REMOUNT_FLAGS;
+		if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+			goto fail;
+		vec[3] = flagsbuf;
+
+		if (opts)
+			tmpallow = AA_MATCH_CONT;
+		else
+			tmpallow = allow;
+
+		/* rule for match without required data || data MATCH_CONT */
+		if (!aare_add_rule_vec(prof.policy.rules, deny, tmpallow,
+				       audit | AA_AUDIT_MNT_DATA, 4,
+				       vec, dfaflags))
+			goto fail;
+		count++;
+
+		if (opts) {
+			/* rule with data match required */
+			optsbuf.clear();
+			if (!build_mnt_opts(optsbuf, opts))
+				goto fail;
+			vec[4] = optsbuf.c_str();
+			if (!aare_add_rule_vec(prof.policy.rules, deny,
+					       allow,
+					       audit | AA_AUDIT_MNT_DATA,
+					       5, vec, dfaflags))
+				goto fail;
+			count++;
+		}
+	}
+	if ((allow & AA_MAY_MOUNT) && (flags & MS_BIND)
+	    && !dev_type && !opts) {
+		/* bind mount rules can't be conditional on dev_type or data */
+		/* rule class single byte header */
+		mntbuf.assign(class_mount_hdr);
+		if (!convert_entry(mntbuf, mnt_point))
+			goto fail;
+		vec[0] = mntbuf.c_str();
+		if (!clear_and_convert_entry(devbuf, device))
+			goto fail;
+		vec[1] = devbuf.c_str();
+		/* skip type */
+		vec[2] = default_match_pattern;
+
+		tmpflags = flags;
+		tmpinv_flags = inv_flags;
+		if (tmpflags != MS_ALL_FLAGS)
+			tmpflags &= MS_BIND_FLAGS;
+		if (tmpinv_flags != MS_ALL_FLAGS)
+			tmpflags &= MS_BIND_FLAGS;
+		if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+			goto fail;
+		vec[3] = flagsbuf;
+		if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+				       audit, 4, vec, dfaflags))
+			goto fail;
+		count++;
+	}
+	if ((allow & AA_MAY_MOUNT) &&
+	    (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED))
+	    && !device && !dev_type && !opts) {
+		/* change type base rules can not be conditional on device,
+		 * device type or data
+		 */
+		/* rule class single byte header */
+		mntbuf.assign(class_mount_hdr);
+		if (!convert_entry(mntbuf, mnt_point))
+			goto fail;
+		vec[0] = mntbuf.c_str();
+		/* skip device and type */
+		vec[1] = default_match_pattern;
+		vec[2] = default_match_pattern;
+
+		tmpflags = flags;
+		tmpinv_flags = inv_flags;
+		if (tmpflags != MS_ALL_FLAGS)
+			tmpflags &= MS_MAKE_FLAGS;
+		if (tmpinv_flags != MS_ALL_FLAGS)
+			tmpflags &= MS_MAKE_FLAGS;
+		if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+			goto fail;
+		vec[3] = flagsbuf;
+		if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+				       audit, 4, vec, dfaflags))
+			goto fail;
+		count++;
+	}
+	if ((allow & AA_MAY_MOUNT) && (flags & MS_MOVE)
+	    && !dev_type && !opts) {
+		/* mount move rules can not be conditional on dev_type,
+		 * or data
+		 */
+		/* rule class single byte header */
+		mntbuf.assign(class_mount_hdr);
+		if (!convert_entry(mntbuf, mnt_point))
+			goto fail;
+		vec[0] = mntbuf.c_str();
+		if (!clear_and_convert_entry(devbuf, device))
+			goto fail;
+		vec[1] = devbuf.c_str();
+		/* skip type */
+		vec[2] = default_match_pattern;
+
+		tmpflags = flags;
+		tmpinv_flags = inv_flags;
+		if (tmpflags != MS_ALL_FLAGS)
+			tmpflags &= MS_MOVE_FLAGS;
+		if (tmpinv_flags != MS_ALL_FLAGS)
+			tmpflags &= MS_MOVE_FLAGS;
+		if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+			goto fail;
+		vec[3] = flagsbuf;
+		if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+				       audit, 4, vec, dfaflags))
+			goto fail;
+		count++;
+	}
+	if ((allow & AA_MAY_MOUNT) &&
+	    (flags | inv_flags) & ~MS_CMDS) {
+		int tmpallow;
+		/* generic mount if flags are set that are not covered by
+		 * above commands
+		 */
+		/* rule class single byte header */
+		mntbuf.assign(class_mount_hdr);
+		if (!convert_entry(mntbuf, mnt_point))
+			goto fail;
+		vec[0] = mntbuf.c_str();
+		if (!clear_and_convert_entry(devbuf, device))
+			goto fail;
+		vec[1] = devbuf.c_str();
+		typebuf.clear();
+		if (!build_list_val_expr(typebuf, dev_type))
+			goto fail;
+		vec[2] = typebuf.c_str();
+
+		tmpflags = flags;
+		tmpinv_flags = inv_flags;
+		if (tmpflags != MS_ALL_FLAGS)
+			tmpflags &= ~MS_CMDS;
+		if (tmpinv_flags != MS_ALL_FLAGS)
+			tmpinv_flags &= ~MS_CMDS;
+		if (!build_mnt_flags(flagsbuf, PATH_MAX, tmpflags, tmpinv_flags))
+			goto fail;
+		vec[3] = flagsbuf;
+
+		if (opts)
+			tmpallow = AA_MATCH_CONT;
+		else
+			tmpallow = allow;
+
+		/* rule for match without required data || data MATCH_CONT */
+		if (!aare_add_rule_vec(prof.policy.rules, deny, tmpallow,
+				       audit | AA_AUDIT_MNT_DATA, 4,
+				       vec, dfaflags))
+			goto fail;
+		count++;
+
+		if (opts) {
+			/* rule with data match required */
+			optsbuf.clear();
+			if (!build_mnt_opts(optsbuf, opts))
+				goto fail;
+			vec[4] = optsbuf.c_str();
+			if (!aare_add_rule_vec(prof.policy.rules, deny,
+					       allow,
+					       audit | AA_AUDIT_MNT_DATA,
+					       5, vec, dfaflags))
+				goto fail;
+			count++;
+		}
+	}
+	if (allow & AA_MAY_UMOUNT) {
+		/* rule class single byte header */
+		mntbuf.assign(class_mount_hdr);
+		if (!convert_entry(mntbuf, mnt_point))
+			goto fail;
+		vec[0] = mntbuf.c_str();
+		if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+				       audit, 1, vec, dfaflags))
+			goto fail;
+		count++;
+	}
+	if (allow & AA_MAY_PIVOTROOT) {
+		/* rule class single byte header */
+		mntbuf.assign(class_mount_hdr);
+		if (!convert_entry(mntbuf, mnt_point))
+			goto fail;
+		vec[0] = mntbuf.c_str();
+		if (!clear_and_convert_entry(devbuf, device))
+			goto fail;
+		vec[1] = devbuf.c_str();
+		if (!aare_add_rule_vec(prof.policy.rules, deny, allow,
+				       audit, 2, vec, dfaflags))
+			goto fail;
+		count++;
+	}
 
-	fprintf(stderr, " (0x%x - 0x%x) ", entry->flags, entry->inv_flags);
-	if (entry->dev_type) {
-		fprintf(stderr, " type=");
-		print_value_list(entry->dev_type);
-	}
-	if (entry->opts) {
-		fprintf(stderr, " options=");
-		print_value_list(entry->opts);
-	}
-	if (entry->device)
-		fprintf(stderr, " %s", entry->device);
-	if (entry->mnt_point)
-		fprintf(stderr, " -> %s", entry->mnt_point);
-	if (entry->trans)
-		fprintf(stderr, " -> %s", entry->trans);
+	if (!count)
+		/* didn't actually encode anything */
+		goto fail;
+
+	prof.policy.count++;
+	return RULE_OK;
+
+fail:
+	PERROR("Enocoding of mount rule failed\n");
+	return RULE_ERROR;
+}
 
-	fprintf(stderr, " %s (0x%x/0x%x)", entry->deny ? "deny" : "", entry->allow, entry->audit); 
-	fprintf(stderr, ",\n");
+void mnt_rule::post_process(Profile &prof)
+{
+	if (trans) {
+		unsigned int mode = 0;
+		int n = add_entry_to_x_table(&prof, trans);
+		if (!n) {
+			PERROR("Profile %s has too many specified profile transitions.\n", prof.name);
+			exit(1);
+		}
+
+		if (allow & AA_USER_EXEC)
+			mode |= SHIFT_MODE(n << 10, AA_USER_SHIFT);
+		if (allow & AA_OTHER_EXEC)
+			mode |= SHIFT_MODE(n << 10, AA_OTHER_SHIFT);
+		allow = ((allow & ~AA_ALL_EXEC_MODIFIERS) |
+				(mode & AA_ALL_EXEC_MODIFIERS));
+
+		trans = NULL;
+	}
 }
+
+
--- 2.9-test.orig/parser/mount.h
+++ 2.9-test/parser/mount.h
@@ -19,7 +19,11 @@
 #ifndef __AA_MOUNT_H
 #define __AA_MOUNT_H
 
+#include <ostream>
+
 #include "parser.h"
+#include "rule.h"
+
 
 #define MS_RDONLY	(1 << 0)
 #define MS_RW		0
@@ -109,7 +113,8 @@
 					 * remapped to a mount option*/
 
 
-struct mnt_entry {
+class mnt_rule: public rule_t {
+public:
 	char *mnt_point;
 	char *device;
 	char *trans;
@@ -120,17 +125,26 @@
 
 	int allow, audit;
 	int deny;
-	struct mnt_entry *next;
-};
 
-void print_mnt_entry(struct mnt_entry *entry);
+	mnt_rule(struct cond_entry *src_conds, char *device_p,
+		   struct cond_entry *dst_conds __unused, char *mnt_point_p,
+		   int allow_p);
+	virtual ~mnt_rule()
+	{
+		free_value_list(opts);
+		free_value_list(dev_type);
+		free(device);
+		free(mnt_point);
+		free(trans);
+	}
+
+	virtual ostream &dump(ostream &os);
+	virtual int expand_variables(void);
+	virtual int gen_policy_re(Profile &prof);
+	virtual void post_process(Profile &prof __unused);
+};
 
 int is_valid_mnt_cond(const char *name, int src);
-struct mnt_entry *new_mnt_entry(struct cond_entry *sconds, char *device,
-				struct cond_entry *dconds, char *mnt_point,
-				int mode);
-struct mnt_entry *dup_mnt_entry(struct mnt_entry *orig);
-void free_mnt_entry(struct mnt_entry *ent);
 
 
 #endif /* __AA_MOUNT_H */
--- 2.9-test.orig/parser/parser.h
+++ 2.9-test/parser/parser.h
@@ -30,12 +30,13 @@
 #include "libapparmor_re/apparmor_re.h"
 #include "libapparmor_re/aare_rules.h"
 
+#include <string>
+
 using namespace std;
 
 #include <set>
 class Profile;
-
-struct mnt_ent;
+class rule_t;
 
 /* Global variable to pass token to lexer.  Will be replaced by parameter
  * when lexer and parser are made reentrant
@@ -256,9 +257,14 @@
 extern const char *basedir;
 
 /* parser_regex.c */
+extern const char *default_match_pattern;
+extern pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
+					 std::string& pcre, int *first_re_pos);
+extern int build_list_val_expr(std::string& buffer, struct value_list *list);
+extern int convert_entry(std::string& buffer, char *entry);
+extern int clear_and_convert_entry(std::string& buffer, char *entry);
 extern int process_regex(Profile *prof);
 extern int post_process_entry(struct cod_entry *entry);
-extern int process_dbus(Profile *prof);
 
 extern void reset_regex(void);
 
@@ -267,11 +273,13 @@
 extern int process_policy_ents(Profile *prof);
 
 /* parser_variable.c */
+int expand_entry_variables(char **name);
 extern int process_variables(Profile *prof);
 extern struct var_string *split_out_var(const char *string);
 extern void free_var_string(struct var_string *var);
 
 /* parser_misc.c */
+extern void warn_uppercase(void);
 extern int is_blacklisted(const char *name, const char *path);
 extern struct value_list *new_value_list(char *value);
 extern struct value_list *dup_value_list(struct value_list *list);
@@ -289,7 +297,6 @@
 extern int get_rlimit(const char *name);
 extern char *process_var(const char *var);
 extern int parse_mode(const char *mode);
-extern int parse_dbus_mode(const char *str_mode, int *mode, int fail);
 extern struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id);
 extern struct aa_network_entry *new_network_ent(unsigned int family,
 						unsigned int type,
@@ -303,15 +310,13 @@
 extern int str_to_boolean(const char* str);
 extern struct cod_entry *copy_cod_entry(struct cod_entry *cod);
 extern void free_cod_entries(struct cod_entry *list);
-extern void free_mnt_entries(struct mnt_entry *list);
-extern void free_dbus_entries(struct dbus_entry *list);
 extern void __debug_capabilities(uint64_t capset, const char *name);
 void __debug_network(unsigned int *array, const char *name);
 void debug_cod_entries(struct cod_entry *list);
 
 
 /* parser_symtab.c */
-struct set_value {;
+struct set_value {
 	char *val;
 	struct set_value *next;
 };
@@ -345,9 +350,10 @@
 /* parser_policy.c */
 extern void add_to_list(Profile *profile);
 extern void add_hat_to_policy(Profile *policy, Profile *hat);
+extern int add_entry_to_x_table(Profile *prof, char *name);
 extern void add_entry_to_policy(Profile *policy, struct cod_entry *entry);
 extern void post_process_file_entries(Profile *prof);
-extern void post_process_mnt_entries(Profile *prof);
+extern void post_process_rule_entries(Profile *prof);
 extern int post_process_policy(int debug_only);
 extern int process_profile_regex(Profile *prof);
 extern int process_profile_variables(Profile *prof);
--- 2.9-test.orig/parser/parser_misc.c
+++ 2.9-test/parser/parser_misc.c
@@ -596,7 +596,7 @@
 
 static int warned_uppercase = 0;
 
-static void warn_uppercase(void)
+void warn_uppercase(void)
 {
 	if (!warned_uppercase) {
 		pwarn(_("Uppercase qualifiers \"RWLIMX\" are deprecated, please convert to lowercase\n"
@@ -792,81 +792,6 @@
 	return mode;
 }
 
-static int parse_dbus_sub_mode(const char *str_mode, int *result, int fail, const char *mode_desc __unused)
-{
-	int mode = 0;
-	const char *p;
-
-	PDEBUG("Parsing DBus mode: %s\n", str_mode);
-
-	if (!str_mode)
-		return 0;
-
-	p = str_mode;
-	while (*p) {
-		char current = *p;
-		char lower;
-
-reeval:
-		switch (current) {
-		case COD_READ_CHAR:
-			PDEBUG("Parsing DBus mode: found %s READ\n", mode_desc);
-			mode |= AA_DBUS_RECEIVE;
-			break;
-
-		case COD_WRITE_CHAR:
-			PDEBUG("Parsing DBus mode: found %s WRITE\n",
-			       mode_desc);
-			mode |= AA_DBUS_SEND;
-			break;
-
-		/* error cases */
-
-		default:
-			lower = tolower(current);
-			switch (lower) {
-			case COD_READ_CHAR:
-			case COD_WRITE_CHAR:
-				PDEBUG("Parsing DBus mode: found invalid upper case char %c\n",
-				       current);
-				warn_uppercase();
-				current = lower;
-				goto reeval;
-				break;
-			default:
-				if (fail)
-					yyerror(_("Internal: unexpected DBus mode character '%c' in input"),
-						current);
-				else
-					return 0;
-				break;
-			}
-			break;
-		}
-		p++;
-	}
-
-	PDEBUG("Parsed DBus mode: %s 0x%x\n", str_mode, mode);
-
-	*result = mode;
-	return 1;
-}
-
-int parse_dbus_mode(const char *str_mode, int *mode, int fail)
-{
-	*mode = 0;
-	if (!parse_dbus_sub_mode(str_mode, mode, fail, ""))
-		return 0;
-	if (*mode & ~AA_VALID_DBUS_PERMS) {
-		if (fail)
-			yyerror(_("Internal error generated invalid DBus perm 0x%x\n"),
-				  mode);
-		else
-			return 0;
-	}
-	return 1;
-}
-
 struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id)
 {
 	struct cod_entry *entry = NULL;
@@ -938,30 +863,6 @@
 	free(list);
 }
 
-void free_mnt_entries(struct mnt_entry *list)
-{
-	if (!list)
-		return;
-	if (list->next)
-		free_mnt_entries(list->next);
-	free(list->mnt_point);
-	free(list->device);
-	free_value_list(list->dev_type);
-	free_value_list(list->opts);
-
-	free(list);
-}
-
-void free_dbus_entries(struct dbus_entry *list)
-{
-	if (!list)
-		return;
-	if (list->next)
-		free_dbus_entries(list->next);
-
-	free_dbus_entry(list);
-}
-
 static void debug_base_perm_mask(int mask)
 {
 	if (HAS_MAY_READ(mask))
--- 2.9-test.orig/parser/parser_policy.c
+++ 2.9-test/parser/parser_policy.c
@@ -32,8 +32,6 @@
 
 #include "parser.h"
 #include "profile.h"
-#include "mount.h"
-#include "dbus.h"
 #include "parser_yacc.h"
 
 /* #define DEBUG */
@@ -70,7 +68,7 @@
 	}
 }
 
-static int add_entry_to_x_table(Profile *prof, char *name)
+int add_entry_to_x_table(Profile *prof, char *name)
 {
 	int i;
 	for (i = (AA_EXEC_LOCAL >> 10) + 1; i < AA_EXEC_COUNT; i++) {
@@ -192,29 +190,10 @@
 	}
 }
 
-void post_process_mnt_entries(Profile *prof)
+void post_process_rule_entries(Profile *prof)
 {
-	struct mnt_entry *entry;
-
-	list_for_each(prof->mnt_ents, entry) {
-		if (entry->trans) {
-			unsigned int mode = 0;
-			int n = add_entry_to_x_table(prof, entry->trans);
-			if (!n) {
-				PERROR("Profile %s has too many specified profile transitions.\n", prof->name);
-				exit(1);
-			}
-
-			if (entry->allow & AA_USER_EXEC)
-				mode |= SHIFT_MODE(n << 10, AA_USER_SHIFT);
-			if (entry->allow & AA_OTHER_EXEC)
-				mode |= SHIFT_MODE(n << 10, AA_OTHER_SHIFT);
-			entry->allow = ((entry->allow & ~AA_ALL_EXEC_MODIFIERS) |
-				       (mode & AA_ALL_EXEC_MODIFIERS));
-
-			entry->trans = NULL;
-		}
-	}
+	for (RuleList::iterator i = prof->rule_ents.begin(); i != prof->rule_ents.end(); i++)
+		(*i)->post_process(*prof);
 }
 
 
--- 2.9-test.orig/parser/parser_regex.c
+++ 2.9-test/parser/parser_regex.c
@@ -35,9 +35,8 @@
 #include "profile.h"
 #include "libapparmor_re/apparmor_re.h"
 #include "libapparmor_re/aare_rules.h"
-#include "mount.h"
-#include "dbus.h"
 #include "policydb.h"
+#include "rule.h"
 
 enum error_type {
 	e_no_error,
@@ -45,7 +44,7 @@
 };
 
 /* match any char except \000 0 or more times */
-static const char *default_match_pattern = "[^\\000]*";
+const char *default_match_pattern = "[^\\000]*";
 
 /* Filters out multiple slashes (except if the first two are slashes,
  * that's a distinct namespace in linux) and trailing slashes.
@@ -90,8 +89,8 @@
 
 /* converts the apparmor regex in aare and appends pcre regex output
  * to pcre string */
-static pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
-					 std::string& pcre, int *first_re_pos)
+pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
+				  std::string& pcre, int *first_re_pos)
 {
 #define update_re_pos(X) if (!(*first_re_pos)) { *first_re_pos = (X); }
 #define MAX_ALT_DEPTH 50
@@ -612,7 +611,7 @@
 	return error;
 }
 
-static int build_list_val_expr(std::string& buffer, struct value_list *list)
+int build_list_val_expr(std::string& buffer, struct value_list *list)
 {
 	struct value_list *ent;
 	pattern_t ptype;
@@ -642,7 +641,7 @@
 	return FALSE;
 }
 
-static int convert_entry(std::string& buffer, char *entry)
+int convert_entry(std::string& buffer, char *entry)
 {
 	pattern_t ptype;
 	int pos;
@@ -658,487 +657,19 @@
 	return TRUE;
 }
 
-static int clear_and_convert_entry(std::string& buffer, char *entry)
+int clear_and_convert_entry(std::string& buffer, char *entry)
 {
 	buffer.clear();
 	return convert_entry(buffer, entry);
 }
 
-static int build_mnt_flags(char *buffer, int size, unsigned int flags,
-			   unsigned int inv_flags)
+int post_process_policydb_ents(Profile *prof)
 {
-	char *p = buffer;
-	int i, len = 0;
-
-	if (flags == MS_ALL_FLAGS) {
-		/* all flags are optional */
-		len = snprintf(p, size, "%s", default_match_pattern);
-		if (len < 0 || len >= size)
-			return FALSE;
-		return TRUE;
-	}
-	for (i = 0; i <= 31; ++i) {
-		if ((flags & inv_flags) & (1 << i))
-			len = snprintf(p, size, "(\\x%02x|)", i + 1);
-		else if (flags & (1 << i))
-			len = snprintf(p, size, "\\x%02x", i + 1);
-		else	/* no entry = not set */
-			continue;
-
-		if (len < 0 || len >= size)
+	for (RuleList::iterator i = prof->rule_ents.begin(); i != prof->rule_ents.end(); i++) {
+		if ((*i)->gen_policy_re(*prof) == RULE_ERROR)
 			return FALSE;
-		p += len;
-		size -= len;
-	}
-
-	/* this needs to go once the backend is updated. */
-	if (buffer == p) {
-		/* match nothing - use impossible 254 as regex parser doesn't
-		 * like the empty string
-		 */
-		if (size < 9)
-			return FALSE;
-
-		strcpy(p, "(\\xfe|)");
-	}
-
-	return TRUE;
-}
-
-static int build_mnt_opts(std::string& buffer, struct value_list *opts)
-{
-	struct value_list *ent;
-	pattern_t ptype;
-	int pos;
-
-	if (!opts) {
-		buffer.append(default_match_pattern);
-		return TRUE;
 	}
 
-	list_for_each(opts, ent) {
-		ptype = convert_aaregex_to_pcre(ent->value, 0, buffer, &pos);
-		if (ptype == ePatternInvalid)
-			return FALSE;
-
-		if (ent->next)
-			buffer.append(",");
-	}
-
-	return TRUE;
-}
-
-static int process_mnt_entry(aare_ruleset_t *dfarules, struct mnt_entry *entry)
-{
-	std::string mntbuf;
-	std::string devbuf;
-	std::string typebuf;
-	char flagsbuf[PATH_MAX + 3];
-	std::string optsbuf;
-	char class_mount_hdr[64];
-	const char *vec[5];
-	int count = 0;
-	unsigned int flags, inv_flags;
-
-	sprintf(class_mount_hdr, "\\x%02x", AA_CLASS_MOUNT);
-
-	/* a single mount rule may result in multiple matching rules being
-	 * created in the backend to cover all the possible choices
-	 */
-
-	if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_REMOUNT)
-	    && !entry->device && !entry->dev_type) {
-		int allow;
-		/* remount can't be conditional on device and type */
-		/* rule class single byte header */
-		mntbuf.assign(class_mount_hdr);
-		if (entry->mnt_point) {
-			/* both device && mnt_point or just mnt_point */
-			if (!convert_entry(mntbuf, entry->mnt_point))
-				goto fail;
-			vec[0] = mntbuf.c_str();
-		} else {
-			if (!convert_entry(mntbuf, entry->device))
-				goto fail;
-			vec[0] = mntbuf.c_str();
-		}
-		/* skip device */
-		vec[1] = default_match_pattern;
-		/* skip type */
-		vec[2] = default_match_pattern;
-
-		flags = entry->flags;
-		inv_flags = entry->inv_flags;
-		if (flags != MS_ALL_FLAGS)
-			flags &= MS_REMOUNT_FLAGS;
-		if (inv_flags != MS_ALL_FLAGS)
-			flags &= MS_REMOUNT_FLAGS;
-		if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
-			goto fail;
-		vec[3] = flagsbuf;
-
-		if (entry->opts)
-			allow = AA_MATCH_CONT;
-		else
-			allow = entry->allow;
-
-		/* rule for match without required data || data MATCH_CONT */
-		if (!aare_add_rule_vec(dfarules, entry->deny, allow,
-				       entry->audit | AA_AUDIT_MNT_DATA, 4,
-				       vec, dfaflags))
-			goto fail;
-		count++;
-
-		if (entry->opts) {
-			/* rule with data match required */
-			optsbuf.clear();
-			if (!build_mnt_opts(optsbuf, entry->opts))
-				goto fail;
-			vec[4] = optsbuf.c_str();
-			if (!aare_add_rule_vec(dfarules, entry->deny,
-					       entry->allow,
-					       entry->audit | AA_AUDIT_MNT_DATA,
-					       5, vec, dfaflags))
-				goto fail;
-			count++;
-		}
-	}
-	if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_BIND)
-	    && !entry->dev_type && !entry->opts) {
-		/* bind mount rules can't be conditional on dev_type or data */
-		/* rule class single byte header */
-		mntbuf.assign(class_mount_hdr);
-		if (!convert_entry(mntbuf, entry->mnt_point))
-			goto fail;
-		vec[0] = mntbuf.c_str();
-		if (!clear_and_convert_entry(devbuf, entry->device))
-			goto fail;
-		vec[1] = devbuf.c_str();
-		/* skip type */
-		vec[2] = default_match_pattern;
-
-		flags = entry->flags;
-		inv_flags = entry->inv_flags;
-		if (flags != MS_ALL_FLAGS)
-			flags &= MS_BIND_FLAGS;
-		if (inv_flags != MS_ALL_FLAGS)
-			flags &= MS_BIND_FLAGS;
-		if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
-			goto fail;
-		vec[3] = flagsbuf;
-		if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
-				       entry->audit, 4, vec, dfaflags))
-			goto fail;
-		count++;
-	}
-	if ((entry->allow & AA_MAY_MOUNT) &&
-	    (entry->flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED))
-	    && !entry->device && !entry->dev_type && !entry->opts) {
-		/* change type base rules can not be conditional on device,
-		 * device type or data
-		 */
-		/* rule class single byte header */
-		mntbuf.assign(class_mount_hdr);
-		if (!convert_entry(mntbuf, entry->mnt_point))
-			goto fail;
-		vec[0] = mntbuf.c_str();
-		/* skip device and type */
-		vec[1] = default_match_pattern;
-		vec[2] = default_match_pattern;
-
-		flags = entry->flags;
-		inv_flags = entry->inv_flags;
-		if (flags != MS_ALL_FLAGS)
-			flags &= MS_MAKE_FLAGS;
-		if (inv_flags != MS_ALL_FLAGS)
-			flags &= MS_MAKE_FLAGS;
-		if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
-			goto fail;
-		vec[3] = flagsbuf;
-		if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
-				       entry->audit, 4, vec, dfaflags))
-			goto fail;
-		count++;
-	}
-	if ((entry->allow & AA_MAY_MOUNT) && (entry->flags & MS_MOVE)
-	    && !entry->dev_type && !entry->opts) {
-		/* mount move rules can not be conditional on dev_type,
-		 * or data
-		 */
-		/* rule class single byte header */
-		mntbuf.assign(class_mount_hdr);
-		if (!convert_entry(mntbuf, entry->mnt_point))
-			goto fail;
-		vec[0] = mntbuf.c_str();
-		if (!clear_and_convert_entry(devbuf, entry->device))
-			goto fail;
-		vec[1] = devbuf.c_str();
-		/* skip type */
-		vec[2] = default_match_pattern;
-
-		flags = entry->flags;
-		inv_flags = entry->inv_flags;
-		if (flags != MS_ALL_FLAGS)
-			flags &= MS_MOVE_FLAGS;
-		if (inv_flags != MS_ALL_FLAGS)
-			flags &= MS_MOVE_FLAGS;
-		if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
-			goto fail;
-		vec[3] = flagsbuf;
-		if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
-				       entry->audit, 4, vec, dfaflags))
-			goto fail;
-		count++;
-	}
-	if ((entry->allow & AA_MAY_MOUNT) &&
-	    (entry->flags | entry->inv_flags) & ~MS_CMDS) {
-		int allow;
-		/* generic mount if flags are set that are not covered by
-		 * above commands
-		 */
-		/* rule class single byte header */
-		mntbuf.assign(class_mount_hdr);
-		if (!convert_entry(mntbuf, entry->mnt_point))
-			goto fail;
-		vec[0] = mntbuf.c_str();
-		if (!clear_and_convert_entry(devbuf, entry->device))
-			goto fail;
-		vec[1] = devbuf.c_str();
-		typebuf.clear();
-		if (!build_list_val_expr(typebuf, entry->dev_type))
-			goto fail;
-		vec[2] = typebuf.c_str();
-
-		flags = entry->flags;
-		inv_flags = entry->inv_flags;
-		if (flags != MS_ALL_FLAGS)
-			flags &= ~MS_CMDS;
-		if (inv_flags != MS_ALL_FLAGS)
-			flags &= ~MS_CMDS;
-		if (!build_mnt_flags(flagsbuf, PATH_MAX, flags, inv_flags))
-			goto fail;
-		vec[3] = flagsbuf;
-
-		if (entry->opts)
-			allow = AA_MATCH_CONT;
-		else
-			allow = entry->allow;
-
-		/* rule for match without required data || data MATCH_CONT */
-		if (!aare_add_rule_vec(dfarules, entry->deny, allow,
-				       entry->audit | AA_AUDIT_MNT_DATA, 4,
-				       vec, dfaflags))
-			goto fail;
-		count++;
-
-		if (entry->opts) {
-			/* rule with data match required */
-			optsbuf.clear();
-			if (!build_mnt_opts(optsbuf, entry->opts))
-				goto fail;
-			vec[4] = optsbuf.c_str();
-			if (!aare_add_rule_vec(dfarules, entry->deny,
-					       entry->allow,
-					       entry->audit | AA_AUDIT_MNT_DATA,
-					       5, vec, dfaflags))
-				goto fail;
-			count++;
-		}
-	}
-	if (entry->allow & AA_MAY_UMOUNT) {
-		/* rule class single byte header */
-		mntbuf.assign(class_mount_hdr);
-		if (!convert_entry(mntbuf, entry->mnt_point))
-			goto fail;
-		vec[0] = mntbuf.c_str();
-		if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
-				       entry->audit, 1, vec, dfaflags))
-			goto fail;
-		count++;
-	}
-	if (entry->allow & AA_MAY_PIVOTROOT) {
-		/* rule class single byte header */
-		mntbuf.assign(class_mount_hdr);
-		if (!convert_entry(mntbuf, entry->mnt_point))
-			goto fail;
-		vec[0] = mntbuf.c_str();
-		if (!clear_and_convert_entry(devbuf, entry->device))
-			goto fail;
-		vec[1] = devbuf.c_str();
-		if (!aare_add_rule_vec(dfarules, entry->deny, entry->allow,
-				       entry->audit, 2, vec, dfaflags))
-			goto fail;
-		count++;
-	}
-
-	if (!count)
-		/* didn't actually encode anything */
-		goto fail;
-
-	return TRUE;
-
-fail:
-	PERROR("Enocoding of mount rule failed\n");
-	return FALSE;
-}
-
-
-static int process_dbus_entry(aare_ruleset_t *dfarules, struct dbus_entry *entry)
-{
-	std::string busbuf;
-	std::string namebuf;
-	std::string peer_labelbuf;
-	std::string pathbuf;
-	std::string ifacebuf;
-	std::string memberbuf;
-	std::ostringstream buffer;
-	const char *vec[6];
-
-	pattern_t ptype;
-	int pos;
-
-	if (!entry) 		/* shouldn't happen */
-		return TRUE;
-
-	buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << AA_CLASS_DBUS;
-	busbuf.append(buffer.str());
-
-	if (entry->bus) {
-		ptype = convert_aaregex_to_pcre(entry->bus, 0, busbuf, &pos);
-		if (ptype == ePatternInvalid)
-			goto fail;
-	} else {
-		/* match any char except \000 0 or more times */
-		busbuf.append(default_match_pattern);
-	}
-	vec[0] = busbuf.c_str();
-
-	if (entry->name) {
-		ptype = convert_aaregex_to_pcre(entry->name, 0, namebuf, &pos);
-		if (ptype == ePatternInvalid)
-			goto fail;
-		vec[1] = namebuf.c_str();
-	} else {
-		/* match any char except \000 0 or more times */
-		vec[1] = default_match_pattern;
-	}
-
-	if (entry->peer_label) {
-		ptype = convert_aaregex_to_pcre(entry->peer_label, 0,
-						peer_labelbuf, &pos);
-		if (ptype == ePatternInvalid)
-			goto fail;
-		vec[2] = peer_labelbuf.c_str();
-	} else {
-		/* match any char except \000 0 or more times */
-		vec[2] = default_match_pattern;
-	}
-
-	if (entry->path) {
-		ptype = convert_aaregex_to_pcre(entry->path, 0, pathbuf, &pos);
-		if (ptype == ePatternInvalid)
-			goto fail;
-		vec[3] = pathbuf.c_str();
-	} else {
-		/* match any char except \000 0 or more times */
-		vec[3] = default_match_pattern;
-	}
-
-	if (entry->interface) {
-		ptype = convert_aaregex_to_pcre(entry->interface, 0, ifacebuf, &pos);
-		if (ptype == ePatternInvalid)
-			goto fail;
-		vec[4] = ifacebuf.c_str();
-	} else {
-		/* match any char except \000 0 or more times */
-		vec[4] = default_match_pattern;
-	}
-
-	if (entry->member) {
-		ptype = convert_aaregex_to_pcre(entry->member, 0, memberbuf, &pos);
-		if (ptype == ePatternInvalid)
-			goto fail;
-		vec[5] = memberbuf.c_str();
-	} else {
-		/* match any char except \000 0 or more times */
-		vec[5] = default_match_pattern;
-	}
-
-	if (entry->mode & AA_DBUS_BIND) {
-		if (!aare_add_rule_vec(dfarules, entry->deny,
-				       entry->mode & AA_DBUS_BIND,
-				       entry->audit & AA_DBUS_BIND,
-				       2, vec, dfaflags))
-			goto fail;
-	}
-	if (entry->mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE)) {
-		if (!aare_add_rule_vec(dfarules, entry->deny,
-				entry->mode & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
-				entry->audit & (AA_DBUS_SEND | AA_DBUS_RECEIVE),
-				6, vec, dfaflags))
-			goto fail;
-	}
-	if (entry->mode & AA_DBUS_EAVESDROP) {
-		if (!aare_add_rule_vec(dfarules, entry->deny,
-				entry->mode & AA_DBUS_EAVESDROP,
-				entry->audit & AA_DBUS_EAVESDROP,
-				1, vec, dfaflags))
-			goto fail;
-	}
-	return TRUE;
-
-fail:
-	return FALSE;
-}
-
-static int post_process_mnt_ents(Profile *prof)
-{
-	int ret = TRUE;
-	int count = 0;
-
-	/* Add fns for rules that should be added to policydb here */
-	if (prof->mnt_ents && kernel_supports_mount) {
-		struct mnt_entry *entry;
-		list_for_each(prof->mnt_ents, entry) {
-			if (!process_mnt_entry(prof->policy.rules, entry))
-				ret = FALSE;
-			count++;
-		}
-	} else if (prof->mnt_ents && !kernel_supports_mount)
-		pwarn("profile %s mount rules not enforced\n", prof->name);
-
-	prof->policy.count += count;
-
-	return ret;
-}
-
-static int post_process_dbus_ents(Profile *prof)
-{
-	int ret = TRUE;
-	int count = 0;
-
-	if (prof->dbus_ents && kernel_supports_dbus) {
-		struct dbus_entry *entry;
-
-		list_for_each(prof->dbus_ents, entry) {
-			if (!process_dbus_entry(prof->policy.rules, entry))
-				ret = FALSE;
-			count++;
-		}
-	} else if (prof->dbus_ents && !kernel_supports_dbus)
-		pwarn("profile %s dbus rules not enforced\n", prof->name);
-
-	prof->policy.count += count;
-	return ret;
-}
-
-int post_process_policydb_ents(Profile *prof)
-{
-	if (!post_process_mnt_ents(prof))
-		return FALSE;
-	if (!post_process_dbus_ents(prof))
-		return FALSE;
-
 	return TRUE;
 }
 
--- 2.9-test.orig/parser/parser_variable.c
+++ 2.9-test/parser/parser_variable.c
@@ -15,6 +15,7 @@
  *   along with this program; if not, contact Novell, Inc.
  */
 
+#include <assert.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -213,13 +214,15 @@
 }
 
 /* doesn't handle variables in options atm */
-static int expand_entry_variables(char **name, void *entry)
+int expand_entry_variables(char **name)
 {
 	struct set_value *valuelist;
 	struct var_string *split_var;
 	int ret;
 
-	if (!entry) 		/* can happen when entry is optional */
+	assert(name);
+
+	if (!*name) 		/* can happen when entry is optional */
 		return 0;
 
 	while ((split_var = split_out_var(*name))) {
@@ -251,7 +254,7 @@
 	struct cod_entry *entry;
 
 	list_for_each(entry_list, entry) {
-		error = expand_entry_variables(&entry->name, entry);
+		error = expand_entry_variables(&entry->name);
 		if (error)
 			return error;
 	}
@@ -259,69 +262,24 @@
 	return 0;
 }
 
-/* does not currently support expansion of vars in options */
-static int process_variables_in_mnt_entries(struct mnt_entry *entry_list)
+static int process_variables_in_rules(Profile &prof)
 {
-	int error = 0;
-	struct mnt_entry *entry;
-
-	list_for_each(entry_list, entry) {
-		error = expand_entry_variables(&entry->mnt_point, entry);
+	for(RuleList::iterator i = prof.rule_ents.begin(); i != prof.rule_ents.end(); i++) {
+	  int error = (*i)->expand_variables();
 		if (error)
 			return error;
-		error = expand_entry_variables(&entry->device, entry);
-		if (error)
-			return error;
-		error = expand_entry_variables(&entry->trans, entry);
-		if (error)
-			return error;
-
 	}
 
 	return 0;
 }
 
-static int process_dbus_variables(struct dbus_entry *entry_list)
-{
-	int error = 0;
-	struct dbus_entry *entry;
-
-	list_for_each(entry_list, entry) {
-		error = expand_entry_variables(&entry->bus, entry);
-		if (error)
-			return error;
-		error = expand_entry_variables(&entry->name, entry);
-		if (error)
-			return error;
-		error = expand_entry_variables(&entry->peer_label, entry);
-		if (error)
-			return error;
-		error = expand_entry_variables(&entry->path, entry);
-		if (error)
-			return error;
-		error = expand_entry_variables(&entry->interface, entry);
-		if (error)
-			return error;
-		error = expand_entry_variables(&entry->member, entry);
-		if (error)
-			return error;
-
-	}
-
-	return 0;
-}
 
 int process_profile_variables(Profile *prof)
 {
 	int error = 0;
-
-	error = process_variables_in_entries(prof->entries);
-
-	if (!error)
-		error = process_variables_in_mnt_entries(prof->mnt_ents);
-
-	if (!error)
-		error = process_dbus_variables(prof->dbus_ents);
+       	error = process_variables_in_entries(prof->entries);
+       	if (!error)
+		error = process_variables_in_rules(*prof);
 
 	return error;
 }
--- 2.9-test.orig/parser/parser_yacc.y
+++ 2.9-test/parser/parser_yacc.y
@@ -72,11 +72,11 @@
 
 struct cod_entry *do_file_rule(char *ns, char *id, int mode,
 			       char *link_id, char *nt);
-struct mnt_entry *do_mnt_rule(struct cond_entry *src_conds, char *src,
-			      struct cond_entry *dst_conds, char *dst,
-			      int mode);
-struct mnt_entry *do_pivot_rule(struct cond_entry *old, char *root,
-				char *transition);
+mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
+		      struct cond_entry *dst_conds, char *dst,
+		      int mode);
+mnt_rule *do_pivot_rule(struct cond_entry *old, char *root,
+			char *transition);
 
 void add_local_entry(Profile *prof);
 
@@ -162,6 +162,12 @@
 /* debug flag values */
 %token TOK_FLAGS
 
+%code requires {
+	#include "profile.h"
+	#include "mount.h"
+	#include "dbus.h"
+}
+
 %union {
 	char *id;
 	char *flag_id;
@@ -170,8 +176,9 @@
 	Profile *prof;
 	struct cod_net_entry *net_entry;
 	struct cod_entry *user_entry;
-	struct mnt_entry *mnt_entry;
-	struct dbus_entry *dbus_entry;
+
+	mnt_rule *mnt_entry;
+	dbus_rule *dbus_entry;
 
 	flagvals flags;
 	int fmode;
@@ -281,7 +288,7 @@
 			prof->flags.complain = 1;
 
 		post_process_file_entries(prof);
-		post_process_mnt_entries(prof);
+		post_process_rule_entries(prof);
 		PDEBUG("%s: flags='%s%s'\n",
 		       $2,
 		       prof->flags.complain ? "complain, " : "",
@@ -667,8 +674,8 @@
 		} else if ($2.audit) {
 			$3->audit = $3->allow;
 		}
-		$3->next = $1->mnt_ents;
-		$1->mnt_ents = $3;
+
+		$1->rule_ents.push_back($3);
 		$$ = $1;
 	}
 
@@ -684,8 +691,7 @@
 		} else if ($2.audit) {
 			$3->audit = $3->mode;
 		}
-		$3->next = $1->dbus_ents;
-		$1->dbus_ents = $3;
+		$1->rule_ents.push_back($3);
 		$$ = $1;
 	}
 
@@ -1196,9 +1202,9 @@
 
 dbus_rule: TOK_DBUS opt_dbus_perm opt_conds opt_cond_list TOK_END_OF_RULE
 	{
-		struct dbus_entry *ent;
+		dbus_rule *ent;
 
-		ent = new_dbus_entry($2, $3, $4);
+		ent = new dbus_rule($2, $3, $4);
 		if (!ent) {
 			yyerror(_("Memory allocation error."));
 		}
@@ -1366,12 +1372,10 @@
 	return error;
 }
 
-struct mnt_entry *do_mnt_rule(struct cond_entry *src_conds, char *src,
-			      struct cond_entry *dst_conds, char *dst,
-			      int mode)
+mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
+		      struct cond_entry *dst_conds, char *dst,
+		      int mode)
 {
-	struct mnt_entry *ent;
-
 	if (verify_mnt_conds(src_conds, MNT_SRC_OPT) != 0)
 		yyerror(_("bad mount rule"));
 
@@ -1382,7 +1386,7 @@
 	if (dst_conds)
 		yyerror(_("mount point conditions not currently supported"));
 
-	ent = new_mnt_entry(src_conds, src, dst_conds, dst, mode);
+	mnt_rule *ent = new mnt_rule(src_conds, src, dst_conds, dst, mode);
 	if (!ent) {
 		yyerror(_("Memory allocation error."));
 	}
@@ -1390,10 +1394,8 @@
 	return ent;
 }
 
-struct mnt_entry *do_pivot_rule(struct cond_entry *old, char *root,
-				char *transition)
+mnt_rule *do_pivot_rule(struct cond_entry *old, char *root, char *transition)
 {
-	struct mnt_entry *ent = NULL;
 	char *device = NULL;
 	if (old) {
 		if (strcmp(old->name, "oldroot") != 0)
@@ -1405,8 +1407,7 @@
 		free_cond_entry(old);
 	}
 
-	ent = new_mnt_entry(NULL, device, NULL, root,
-			    AA_MAY_PIVOTROOT);
+	mnt_rule *ent = new mnt_rule(NULL, device, NULL, root, AA_MAY_PIVOTROOT);
 	ent->trans = transition;
 
 	return ent;
--- 2.9-test.orig/parser/profile.cc
+++ 2.9-test/parser/profile.cc
@@ -13,6 +13,7 @@
  */
 
 #include "profile.h"
+#include "rule.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -62,8 +63,9 @@
 {
 	hat_table.clear();
 	free_cod_entries(entries);
-	free_mnt_entries(mnt_ents);
-	free_dbus_entries(dbus_ents);
+
+	for (RuleList::iterator i = rule_ents.begin(); i != rule_ents.end(); i++)
+		delete *i;
 	if (dfa.rules)
 		aare_delete_ruleset(dfa.rules);
 	if (dfa.dfa)
--- 2.9-test.orig/parser/profile.h
+++ 2.9-test/parser/profile.h
@@ -17,6 +17,7 @@
 #include <set>
 
 #include "parser.h"
+#include "rule.h"
 
 class Profile;
 
@@ -153,8 +154,7 @@
 
 	char *exec_table[AA_EXEC_COUNT];
 	struct cod_entry *entries;
-	struct mnt_entry *mnt_ents;
-	struct dbus_entry *dbus_ents;
+	RuleList rule_ents;
 
 	ProfileList hat_table;
 
@@ -179,9 +179,6 @@
 		std::fill(exec_table, exec_table + AA_EXEC_COUNT, (char *)NULL);
 
 		entries = NULL;
-		mnt_ents = NULL;
-		dbus_ents = NULL;
-
 	};
 
 	virtual ~Profile();
--- /dev/null
+++ 2.9-test/parser/rule.c
@@ -0,0 +1,23 @@
+/*
+ *   Copyright (c) 2014
+ *   Canonical Ltd. (All rights reserved)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, contact Novell, Inc. or Canonical
+ *   Ltd.
+ */
+#include "rule.h"
+
+std::ostream &operator<<(std::ostream &os, rule_t &rule)
+{
+	return rule.dump(os);
+};
--- /dev/null
+++ 2.9-test/parser/rule.h
@@ -0,0 +1,51 @@
+/*
+ *   Copyright (c) 2014
+ *   Canonical Ltd. (All rights reserved)
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of version 2 of the GNU General Public
+ *   License published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, contact Novell, Inc. or Canonical
+ *   Ltd.
+ */
+#ifndef __AA_RULE_H
+#define __AA_RULE_H
+
+#include <list>
+#include <ostream>
+
+#include "policydb.h"
+
+class Profile;
+
+#define RULE_NOT_SUPPORTED 0
+#define RULE_ERROR -1
+#define RULE_OK 1
+
+class rule_t {
+public:
+	int aa_class;
+
+	rule_t(void): aa_class(AA_CLASS_UNKNOWN) { };
+	virtual ~rule_t() { };
+
+	//virtual bool operator<(rule_t const &rhs)const = 0;
+	virtual std::ostream &dump(std::ostream &os) = 0;
+	virtual int expand_variables(void) = 0;
+	virtual int gen_policy_re(Profile &prof) = 0;
+	virtual void post_process(Profile &prof) = 0;
+};
+
+std::ostream &operator<<(std::ostream &os, rule_t &rule);
+
+typedef std::list<rule_t *> RuleList;
+
+#endif /* __AA_RULE_H */
+




More information about the AppArmor mailing list