summary refs log tree commit diff
path: root/security/apparmor/include
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-06-09 16:55:04 -0700
committerJohn Johansen <john.johansen@canonical.com>2017-06-10 17:11:46 -0700
commit93c98a484c4900f0d2c65c16466d45f90ea5b175 (patch)
treedc4795a3e0c86eed799ccc33666a613bbede06e4 /security/apparmor/include
parent5379a3312024a8befe7728238fc50ed05d2938ac (diff)
downloadlinux-93c98a484c4900f0d2c65c16466d45f90ea5b175.tar.gz
apparmor: move exec domain mediation to using labels
Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security/apparmor/include')
-rw-r--r--security/apparmor/include/lib.h87
1 files changed, 86 insertions, 1 deletions
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h
index 593877d38088..436b3a722357 100644
--- a/security/apparmor/include/lib.h
+++ b/security/apparmor/include/lib.h
@@ -211,4 +211,89 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix,
 		    const char *name, gfp_t gfp);
 void aa_policy_destroy(struct aa_policy *policy);
 
-#endif /* AA_LIB_H */
+
+/*
+ * fn_label_build - abstract out the build of a label transition
+ * @L: label the transition is being computed for
+ * @P: profile parameter derived from L by this macro, can be passed to FN
+ * @GFP: memory allocation type to use
+ * @FN: fn to call for each profile transition. @P is set to the profile
+ *
+ * Returns: new label on success
+ *          ERR_PTR if build @FN fails
+ *          NULL if label_build fails due to low memory conditions
+ *
+ * @FN must return a label or ERR_PTR on failure. NULL is not allowed
+ */
+#define fn_label_build(L, P, GFP, FN)					\
+({									\
+	__label__ __cleanup, __done;					\
+	struct aa_label *__new_;					\
+									\
+	if ((L)->size > 1) {						\
+		/* TODO: add cache of transitions already done */	\
+		struct label_it __i;					\
+		int __j, __k, __count;					\
+		DEFINE_VEC(label, __lvec);				\
+		DEFINE_VEC(profile, __pvec);				\
+		if (vec_setup(label, __lvec, (L)->size, (GFP)))	{	\
+			__new_ = NULL;					\
+			goto __done;					\
+		}							\
+		__j = 0;						\
+		label_for_each(__i, (L), (P)) {				\
+			__new_ = (FN);					\
+			AA_BUG(!__new_);				\
+			if (IS_ERR(__new_))				\
+				goto __cleanup;				\
+			__lvec[__j++] = __new_;				\
+		}							\
+		for (__j = __count = 0; __j < (L)->size; __j++)		\
+			__count += __lvec[__j]->size;			\
+		if (!vec_setup(profile, __pvec, __count, (GFP))) {	\
+			for (__j = __k = 0; __j < (L)->size; __j++) {	\
+				label_for_each(__i, __lvec[__j], (P))	\
+					__pvec[__k++] = aa_get_profile(P); \
+			}						\
+			__count -= aa_vec_unique(__pvec, __count, 0);	\
+			if (__count > 1) {				\
+				__new_ = aa_vec_find_or_create_label(__pvec,\
+						     __count, (GFP));	\
+				/* only fails if out of Mem */		\
+				if (!__new_)				\
+					__new_ = NULL;			\
+			} else						\
+				__new_ = aa_get_label(&__pvec[0]->label); \
+			vec_cleanup(profile, __pvec, __count);		\
+		} else							\
+			__new_ = NULL;					\
+__cleanup:								\
+		vec_cleanup(label, __lvec, (L)->size);			\
+	} else {							\
+		(P) = labels_profile(L);				\
+		__new_ = (FN);						\
+	}								\
+__done:									\
+	if (!__new_)							\
+		AA_DEBUG("label build failed\n");			\
+	(__new_);							\
+})
+
+
+#define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN)			\
+({									\
+	struct aa_label *__new;						\
+	if ((P)->ns != (NS))						\
+		__new = (OTHER_FN);					\
+	else								\
+		__new = (NS_FN);					\
+	(__new);							\
+})
+
+#define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN)		\
+({									\
+	fn_label_build((L), (P), (GFP),					\
+		__fn_build_in_ns(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \
+})
+
+#endif /* __AA_LIB_H */