apparmor: convert xmatch to using the new shared policydb struct

continue permission unification by converting xmatch to use the
policydb struct that is used by the other profile dfas.

Signed-off-by: John Johansen <john.johansen@canonical.com>
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 1625fee..a2d12b8 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -1095,7 +1095,7 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v)
 	struct aa_profile *profile = labels_profile(label);
 	if (profile->attach)
 		seq_printf(seq, "%s\n", profile->attach);
-	else if (profile->xmatch)
+	else if (profile->xmatch.dfa)
 		seq_puts(seq, "<unknown>\n");
 	else
 		seq_printf(seq, "%s\n", profile->base.name);
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 819b782..0df17fb 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -321,7 +321,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm,
 	might_sleep();
 
 	/* transition from exec match to xattr set */
-	state = aa_dfa_outofband_transition(profile->xmatch, state);
+	state = aa_dfa_outofband_transition(profile->xmatch.dfa, state);
 	d = bprm->file->f_path.dentry;
 
 	for (i = 0; i < profile->xattr_count; i++) {
@@ -335,18 +335,19 @@ static int aa_xattrs_match(const struct linux_binprm *bprm,
 			 * that not present xattr can be distinguished from a 0
 			 * length value or rule that matches any value
 			 */
-			state = aa_dfa_null_transition(profile->xmatch, state);
+			state = aa_dfa_null_transition(profile->xmatch.dfa,
+						       state);
 			/* Check xattr value */
-			state = aa_dfa_match_len(profile->xmatch, state, value,
-						 size);
-			perm = profile->xmatch_perms[state].allow;
+			state = aa_dfa_match_len(profile->xmatch.dfa, state,
+						 value, size);
+			perm = profile->xmatch.perms[state].allow;
 			if (!(perm & MAY_EXEC)) {
 				ret = -EINVAL;
 				goto out;
 			}
 		}
 		/* transition to next element */
-		state = aa_dfa_outofband_transition(profile->xmatch, state);
+		state = aa_dfa_outofband_transition(profile->xmatch.dfa, state);
 		if (size < 0) {
 			/*
 			 * No xattr match, so verify if transition to
@@ -413,13 +414,14 @@ static struct aa_label *find_attach(const struct linux_binprm *bprm,
 		 * as another profile, signal a conflict and refuse to
 		 * match.
 		 */
-		if (profile->xmatch) {
+		if (profile->xmatch.dfa) {
 			unsigned int state, count;
 			u32 perm;
 
-			state = aa_dfa_leftmatch(profile->xmatch, DFA_START,
-						 name, &count);
-			perm = profile->xmatch_perms[state].allow;
+			state = aa_dfa_leftmatch(profile->xmatch.dfa,
+					profile->xmatch.start[AA_CLASS_XMATCH],
+					name, &count);
+			perm = profile->xmatch.perms[state].allow;
 			/* any accepting state means a valid match. */
 			if (perm & MAY_EXEC) {
 				int ret = 0;
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index dd2c131..8fd66a4 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -26,6 +26,7 @@
 #define AA_CLASS_MOUNT		7
 #define AA_CLASS_PTRACE		9
 #define AA_CLASS_SIGNAL		10
+#define AA_CLASS_XMATCH		11
 #define AA_CLASS_NET		14
 #define AA_CLASS_LABEL		16
 #define AA_CLASS_POSIX_MQUEUE	17
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index 9bafeb3..44d8cbb 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -113,7 +113,6 @@ struct aa_data {
  * @attach: human readable attachment string
  * @xmatch: optional extended matching for unconfined executables names
  * @xmatch_len: xmatch prefix len, used to determine xmatch priority
- * @xmatch_perms: precomputed permissions for the xmatch DFA indexed by state
  * @audit: the auditing mode of the profile
  * @mode: the enforcement mode of the profile
  * @path_flags: flags controlling path generation behavior
@@ -148,9 +147,8 @@ struct aa_profile {
 	const char *rename;
 
 	const char *attach;
-	struct aa_dfa *xmatch;
+	struct aa_policydb xmatch;
 	unsigned int xmatch_len;
-	struct aa_perms *xmatch_perms;
 
 	enum audit_mode audit;
 	long mode;
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 0814ee5..cdcf26c 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -230,8 +230,7 @@ void aa_free_profile(struct aa_profile *profile)
 		kfree_sensitive(profile->secmark[i].label);
 	kfree_sensitive(profile->secmark);
 	kfree_sensitive(profile->dirname);
-	aa_put_dfa(profile->xmatch);
-	kvfree(profile->xmatch_perms);
+	aa_destroy_policydb(&profile->xmatch);
 	aa_destroy_policydb(&profile->policy);
 	if (profile->data) {
 		rht = profile->data;
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 726fa02..f2a0759 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -771,7 +771,7 @@ static struct aa_perms *compute_fperms(struct aa_dfa *dfa)
 
 static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch)
 {
-	struct aa_perms *perms_table;
+	struct aa_perms *perms;
 	int state;
 	int state_count;
 
@@ -779,14 +779,13 @@ static struct aa_perms *compute_xmatch_perms(struct aa_dfa *xmatch)
 
 	state_count = xmatch->tables[YYTD_ID_BASE]->td_lolen;
 	/* DFAs are restricted from having a state_count of less than 2 */
-	  perms_table = kvcalloc(state_count, sizeof(struct aa_perms),
-			       GFP_KERNEL);
+	perms = kvcalloc(state_count, sizeof(struct aa_perms), GFP_KERNEL);
 
 	/* zero init so skip the trap state (state == 0) */
 	for (state = 1; state < state_count; state++)
-		perms_table[state].allow = dfa_user_allow(xmatch, state);
+		perms[state].allow = dfa_user_allow(xmatch, state);
 
-	return perms_table;
+	return perms;
 }
 
 static u32 map_other(u32 x)
@@ -888,23 +887,23 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
 	(void) unpack_str(e, &profile->attach, "attach");
 
 	/* xmatch is optional and may be NULL */
-	profile->xmatch = unpack_dfa(e);
-	if (IS_ERR(profile->xmatch)) {
-		error = PTR_ERR(profile->xmatch);
-		profile->xmatch = NULL;
+	profile->xmatch.dfa = unpack_dfa(e);
+	if (IS_ERR(profile->xmatch.dfa)) {
+		error = PTR_ERR(profile->xmatch.dfa);
+		profile->xmatch.dfa = NULL;
 		info = "bad xmatch";
 		goto fail;
 	}
 	/* neither xmatch_len not xmatch_perms are optional if xmatch is set */
-	if (profile->xmatch) {
+	if (profile->xmatch.dfa) {
 		if (!unpack_u32(e, &tmp, NULL)) {
 			info = "missing xmatch len";
 			goto fail;
 		}
 		profile->xmatch_len = tmp;
-
-		profile->xmatch_perms = compute_xmatch_perms(profile->xmatch);
-		if (!profile->xmatch_perms) {
+		profile->xmatch.start[AA_CLASS_XMATCH] = DFA_START;
+		profile->xmatch.perms = compute_xmatch_perms(profile->xmatch.dfa);
+		if (!profile->xmatch.perms) {
 			info = "failed to convert xmatch permission table";
 			goto fail;
 		}