summaryrefslogtreecommitdiff
path: root/security/apparmor/include
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/include')
-rw-r--r--security/apparmor/include/apparmorfs.h12
-rw-r--r--security/apparmor/include/label.h32
-rw-r--r--security/apparmor/include/lib.h21
-rw-r--r--security/apparmor/include/policy_unpack.h21
4 files changed, 76 insertions, 10 deletions
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index dd580594dfb7..33243d11fd10 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -120,6 +120,8 @@ struct aa_loaddata;
#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata);
int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata);
+void __aa_remove_rawdata_symlink_dents(struct aa_profile *profile);
+int __aa_create_rawdata_symlink_dents(struct aa_profile *profile);
#else
static inline void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata)
{
@@ -131,6 +133,16 @@ static inline int __aa_fs_create_rawdata(struct aa_ns *ns,
{
return 0;
}
+
+static inline void __aa_remove_rawdata_symlink_dents(struct aa_profile *profile)
+{
+ /* empty stub */
+}
+
+static inline int __aa_create_rawdata_symlink_dents(struct aa_profile *profile)
+{
+ return 0;
+}
#endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */
#endif /* __AA_APPARMORFS_H */
diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
index 335f21930702..b5a722a47fd2 100644
--- a/security/apparmor/include/label.h
+++ b/security/apparmor/include/label.h
@@ -423,6 +423,38 @@ static inline struct aa_label *aa_get_newest_label(struct aa_label *l)
return aa_get_label(l);
}
+/**
+ * aa_get_newest_label_condref - find the newest version of @l
+ * @l: the label to check for newer versions of
+ * @needput: returns whether the reference needs put
+ *
+ * Returns: refcounted newest version of @l taking into account
+ * replacement, renames and removals
+ * return @l.
+ */
+static inline struct aa_label *aa_get_newest_label_condref(struct aa_label *l,
+ bool *needput)
+{
+ if (l && unlikely(label_is_stale(l))) {
+ struct aa_label *tmp;
+
+ AA_BUG(!l->proxy);
+ AA_BUG(!l->proxy->label);
+ /* BUG: only way this can happen is @l ref count and its
+ * replacement count have gone to 0 and are on their way
+ * to destruction. ie. we have a refcounting error
+ */
+ tmp = aa_get_label_rcu(&l->proxy->label);
+ AA_BUG(!tmp);
+
+ *needput = true;
+ return tmp;
+ }
+
+ *needput = false;
+ return l;
+}
+
static inline void aa_put_label(struct aa_label *l)
{
if (l)
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h
index 8c6ce8484552..e3c8cb044a90 100644
--- a/security/apparmor/include/lib.h
+++ b/security/apparmor/include/lib.h
@@ -281,15 +281,15 @@ void aa_policy_destroy(struct aa_policy *policy);
* @FN: fn to call for each profile transition. @P is set to the profile
*
* Returns: new label on success
+ * NULL if all callbacks decline to specify a transition
* 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
+ * @FN must return a label or ERR_PTR on failure.
*/
#define fn_label_build(L, P, GFP, FN) \
({ \
__label__ __do_cleanup, __done; \
- struct aa_label *__new_; \
+ struct aa_label *__new_ = NULL; \
\
if ((L)->size > 1) { \
/* TODO: add cache of transitions already done */ \
@@ -298,17 +298,21 @@ void aa_policy_destroy(struct aa_policy *policy);
DEFINE_VEC(label, __lvec); \
DEFINE_VEC(profile, __pvec); \
if (vec_setup(label, __lvec, (L)->size, (GFP))) { \
- __new_ = NULL; \
+ __new_ = ERR_PTR(-ENOMEM); \
goto __done; \
} \
__j = 0; \
label_for_each(__i, (L), (P)) { \
__new_ = (FN); \
- AA_BUG(!__new_); \
+ if (!__new_) \
+ continue; \
if (IS_ERR(__new_)) \
goto __do_cleanup; \
__lvec[__j++] = __new_; \
} \
+ if (__j == 0) \
+ /* no components adding to build */ \
+ goto __do_cleanup; \
for (__j = __count = 0; __j < (L)->size; __j++) \
__count += __lvec[__j]->size; \
if (!vec_setup(profile, __pvec, __count, (GFP))) { \
@@ -320,14 +324,13 @@ void aa_policy_destroy(struct aa_policy *policy);
if (__count > 1) { \
__new_ = aa_vec_find_or_create_label(__pvec,\
__count, (GFP)); \
- /* only fails if out of Mem */ \
if (!__new_) \
- __new_ = NULL; \
+ __new_ = ERR_PTR(-ENOMEM); \
} else \
__new_ = aa_get_label(&__pvec[0]->label); \
vec_cleanup(profile, __pvec, __count); \
} else \
- __new_ = NULL; \
+ __new_ = ERR_PTR(-ENOMEM); \
__do_cleanup: \
vec_cleanup(label, __lvec, (L)->size); \
} else { \
@@ -335,7 +338,7 @@ __do_cleanup: \
__new_ = (FN); \
} \
__done: \
- if (!__new_) \
+ if (PTR_ERR(__new_)) \
AA_DEBUG(DEBUG_LABEL, "label build failed\n"); \
(__new_); \
})
diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
index e5a95dc4da1f..4ea9b6479a3e 100644
--- a/security/apparmor/include/policy_unpack.h
+++ b/security/apparmor/include/policy_unpack.h
@@ -131,7 +131,7 @@ struct aa_loaddata {
int aa_unpack(struct aa_loaddata *udata, struct list_head *lh, const char **ns);
/**
- * aa_get_loaddata - get a reference count from a counted data reference
+ * aa_get_i_loaddata - get a reference count from a counted data reference
* @data: reference to get a count on
*
* Returns: pointer to reference
@@ -163,6 +163,25 @@ aa_get_profile_loaddata(struct aa_loaddata *data)
return data;
}
+/**
+ * aa_get_profile_loaddata_not0 - get a profile reference count if not zero
+ * @data: reference to get a count on
+ *
+ * Like aa_get_profile_loaddata(), but safe to call on an entry that may
+ * be on a list (e.g. ns->rawdata_list) where the last pcount has already
+ * dropped and the deferred cleanup has not yet run.
+ *
+ * Returns: pointer to reference, or %NULL if @data is NULL or its
+ * profile refcount has already reached zero.
+ */
+static inline struct aa_loaddata *
+aa_get_profile_loaddata_not0(struct aa_loaddata *data)
+{
+ if (data && kref_get_unless_zero(&data->pcount))
+ return data;
+ return NULL;
+}
+
void __aa_loaddata_update(struct aa_loaddata *data, long revision);
bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r);
void aa_loaddata_kref(struct kref *kref);