apparmor: switch from profiles to using labels on contexts

Begin the actual switch to using domain labels by storing them on
the context and converting the label to a singular profile where
possible.

Signed-off-by: John Johansen <john.johansen@canonical.com>
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index d93f475..17fe41a 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -29,6 +29,7 @@
 #include "domain.h"
 #include "file.h"
 #include "lib.h"
+#include "label.h"
 #include "perms.h"
 #include "resource.h"
 
@@ -48,9 +49,9 @@
 
 #define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL)
 
-#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT)
+#define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT)
 
-#define profile_is_stale(_profile) ((_profile)->flags & PFLAG_STALE)
+#define profile_is_stale(_profile) (label_is_stale(&(_profile)->label))
 
 #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)
 
@@ -67,22 +68,6 @@
 	APPARMOR_UNCONFINED,	/* profile set to unconfined */
 };
 
-enum profile_flags {
-	PFLAG_HAT = 1,			/* profile is a hat */
-	PFLAG_NULL = 4,			/* profile is null learning profile */
-	PFLAG_IX_ON_NAME_ERROR = 8,	/* fallback to ix on name lookup fail */
-	PFLAG_IMMUTABLE = 0x10,		/* don't allow changes/replacement */
-	PFLAG_USER_DEFINED = 0x20,	/* user based profile - lower privs */
-	PFLAG_NO_LIST_REF = 0x40,	/* list doesn't keep profile ref */
-	PFLAG_OLD_NULL_TRANS = 0x100,	/* use // as the null transition */
-	PFLAG_STALE = 0x200,		/* profile replaced/removed */
-	PFLAG_NS_COUNT = 0x400,		/* carries NS ref count */
-
-	/* These flags must correspond with PATH_flags */
-	PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
-};
-
-struct aa_profile;
 
 /* struct aa_policydb - match engine for a policy
  * dfa: dfa pattern match
@@ -95,11 +80,6 @@
 
 };
 
-struct aa_proxy {
-	struct kref count;
-	struct aa_profile __rcu *profile;
-};
-
 /* struct aa_data - generic data structure
  * key: name for retrieving this data
  * size: size of data in bytes
@@ -116,18 +96,15 @@
 
 /* struct aa_profile - basic confinement data
  * @base - base components of the profile (name, refcount, lists, lock ...)
- * @count: reference count of the obj
- * @rcu: rcu head used when removing from @list
+ * @label - label this profile is an extension of
  * @parent: parent of profile
  * @ns: namespace the profile is in
- * @proxy: is set to the profile that replaced this profile
  * @rename: optional profile name that this profile renamed
  * @attach: human readable attachment string
  * @xmatch: optional extended matching for unconfined executables names
  * @xmatch_len: xmatch prefix len, used to determine xmatch priority
  * @audit: the auditing mode of the profile
  * @mode: the enforcement mode of the profile
- * @flags: flags controlling profile behavior
  * @path_flags: flags controlling path generation behavior
  * @disconnected: what to prepend if attach_disconnected is specified
  * @size: the memory consumed by this profiles rules
@@ -145,8 +122,6 @@
  * used to determine profile attachment against unconfined tasks.  All other
  * attachments are determined by profile X transition rules.
  *
- * The @proxy struct is write protected by the profile lock.
- *
  * Profiles have a hierarchy where hats and children profiles keep
  * a reference to their parent.
  *
@@ -156,12 +131,9 @@
  */
 struct aa_profile {
 	struct aa_policy base;
-	struct kref count;
-	struct rcu_head rcu;
 	struct aa_profile __rcu *parent;
 
 	struct aa_ns *ns;
-	struct aa_proxy *proxy;
 	const char *rename;
 
 	const char *attach;
@@ -169,7 +141,6 @@
 	int xmatch_len;
 	enum audit_mode audit;
 	long mode;
-	long flags;
 	u32 path_flags;
 	const char *disconnected;
 	int size;
@@ -184,6 +155,7 @@
 	char *dirname;
 	struct dentry *dents[AAFS_PROF_SIZEOF];
 	struct rhashtable *data;
+	struct aa_label label;
 };
 
 extern enum profile_mode aa_g_profile_mode;
@@ -192,13 +164,15 @@
 #define AA_MAY_REPLACE_POLICY	AA_MAY_WRITE
 #define AA_MAY_REMOVE_POLICY	AA_MAY_DELETE
 
-void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new);
+#define profiles_ns(P) ((P)->ns)
+#define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname)
 
 void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
 
 
 void aa_free_proxy_kref(struct kref *kref);
-struct aa_profile *aa_alloc_profile(const char *name, gfp_t gfp);
+struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy,
+				    gfp_t gfp);
 struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
 				       const char *base, gfp_t gfp);
 void aa_free_profile(struct aa_profile *profile);
@@ -207,20 +181,33 @@
 struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
 				      size_t n);
 struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name);
-struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base,
+struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
 					const char *fqname, size_t n);
 struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name);
 
-ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile,
+ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label,
 			    u32 mask, struct aa_loaddata *udata);
-ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile,
-			    char *name, size_t size);
+ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label,
+			   char *name, size_t size);
 void __aa_profile_list_release(struct list_head *head);
 
 #define PROF_ADD 1
 #define PROF_REPLACE 0
 
-#define unconfined(X) ((X)->mode == APPARMOR_UNCONFINED)
+#define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED)
+
+/**
+ * aa_get_newest_profile - simple wrapper fn to wrap the label version
+ * @p: profile (NOT NULL)
+ *
+ * Returns refcount to newest version of the profile (maybe @p)
+ *
+ * Requires: @p must be held with a valid refcount
+ */
+static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
+{
+	return labels_profile(aa_get_newest_label(&p->label));
+}
 
 #define PROFILE_MEDIATES(P, T)  ((P)->policy.start[(T)])
 /* safe version of POLICY_MEDIATES for full range input */
@@ -243,7 +230,7 @@
 static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
 {
 	if (p)
-		kref_get(&(p->count));
+		kref_get(&(p->label.count));
 
 	return p;
 }
@@ -257,7 +244,7 @@
  */
 static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p)
 {
-	if (p && kref_get_unless_zero(&p->count))
+	if (p && kref_get_unless_zero(&p->label.count))
 		return p;
 
 	return NULL;
@@ -277,53 +264,20 @@
 	rcu_read_lock();
 	do {
 		c = rcu_dereference(*p);
-	} while (c && !kref_get_unless_zero(&c->count));
+	} while (c && !kref_get_unless_zero(&c->label.count));
 	rcu_read_unlock();
 
 	return c;
 }
 
 /**
- * aa_get_newest_profile - find the newest version of @profile
- * @profile: the profile to check for newer versions of
- *
- * Returns: refcounted newest version of @profile taking into account
- *          replacement, renames and removals
- *          return @profile.
- */
-static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
-{
-	if (!p)
-		return NULL;
-
-	if (profile_is_stale(p))
-		return aa_get_profile_rcu(&p->proxy->profile);
-
-	return aa_get_profile(p);
-}
-
-/**
  * aa_put_profile - decrement refcount on profile @p
  * @p: profile  (MAYBE NULL)
  */
 static inline void aa_put_profile(struct aa_profile *p)
 {
 	if (p)
-		kref_put(&p->count, aa_free_profile_kref);
-}
-
-static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *p)
-{
-	if (p)
-		kref_get(&(p->count));
-
-	return p;
-}
-
-static inline void aa_put_proxy(struct aa_proxy *p)
-{
-	if (p)
-		kref_put(&p->count, aa_free_proxy_kref);
+		kref_put(&p->label.count, aa_label_kref);
 }
 
 static inline int AUDIT_MODE(struct aa_profile *profile)
@@ -336,7 +290,7 @@
 
 bool policy_view_capable(struct aa_ns *ns);
 bool policy_admin_capable(struct aa_ns *ns);
-int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns,
+int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns,
 			 u32 mask);
 
 #endif /* __AA_POLICY_H */