summaryrefslogtreecommitdiff
path: root/security/apparmor/include
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/include')
-rw-r--r--security/apparmor/include/label.h16
-rw-r--r--security/apparmor/include/lib.h12
-rw-r--r--security/apparmor/include/match.h1
-rw-r--r--security/apparmor/include/policy.h10
-rw-r--r--security/apparmor/include/policy_ns.h2
-rw-r--r--security/apparmor/include/policy_unpack.h75
6 files changed, 73 insertions, 43 deletions
diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
index c0812dbc1b5b..335f21930702 100644
--- a/security/apparmor/include/label.h
+++ b/security/apparmor/include/label.h
@@ -102,7 +102,7 @@ enum label_flags {
struct aa_label;
struct aa_proxy {
- struct kref count;
+ struct aa_common_ref count;
struct aa_label __rcu *label;
};
@@ -125,7 +125,7 @@ struct label_it {
* vec: vector of profiles comprising the compound label
*/
struct aa_label {
- struct kref count;
+ struct aa_common_ref count;
struct rb_node node;
struct rcu_head rcu;
struct aa_proxy *proxy;
@@ -357,7 +357,7 @@ int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules,
*/
static inline struct aa_label *__aa_get_label(struct aa_label *l)
{
- if (l && kref_get_unless_zero(&l->count))
+ if (l && kref_get_unless_zero(&l->count.count))
return l;
return NULL;
@@ -366,7 +366,7 @@ static inline struct aa_label *__aa_get_label(struct aa_label *l)
static inline struct aa_label *aa_get_label(struct aa_label *l)
{
if (l)
- kref_get(&(l->count));
+ kref_get(&(l->count.count));
return l;
}
@@ -386,7 +386,7 @@ static inline struct aa_label *aa_get_label_rcu(struct aa_label __rcu **l)
rcu_read_lock();
do {
c = rcu_dereference(*l);
- } while (c && !kref_get_unless_zero(&c->count));
+ } while (c && !kref_get_unless_zero(&c->count.count));
rcu_read_unlock();
return c;
@@ -426,7 +426,7 @@ static inline struct aa_label *aa_get_newest_label(struct aa_label *l)
static inline void aa_put_label(struct aa_label *l)
{
if (l)
- kref_put(&l->count, aa_label_kref);
+ kref_put(&l->count.count, aa_label_kref);
}
/* wrapper fn to indicate semantics of the check */
@@ -443,7 +443,7 @@ void aa_proxy_kref(struct kref *kref);
static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *proxy)
{
if (proxy)
- kref_get(&(proxy->count));
+ kref_get(&(proxy->count.count));
return proxy;
}
@@ -451,7 +451,7 @@ static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *proxy)
static inline void aa_put_proxy(struct aa_proxy *proxy)
{
if (proxy)
- kref_put(&proxy->count, aa_proxy_kref);
+ kref_put(&proxy->count.count, aa_proxy_kref);
}
void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new);
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h
index 1c5d1f60f6a7..8c6ce8484552 100644
--- a/security/apparmor/include/lib.h
+++ b/security/apparmor/include/lib.h
@@ -102,6 +102,18 @@ void aa_info_message(const char *str);
/* Security blob offsets */
extern struct lsm_blob_sizes apparmor_blob_sizes;
+enum reftype {
+ REF_NS,
+ REF_PROXY,
+ REF_RAWDATA,
+};
+
+/* common reference count used by data the shows up in aafs */
+struct aa_common_ref {
+ struct kref count;
+ enum reftype reftype;
+};
+
/**
* aa_strneq - compare null terminated @str to a non null terminated substring
* @str: a null terminated string
diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
index 0dde8eda3d1a..7accb1c39849 100644
--- a/security/apparmor/include/match.h
+++ b/security/apparmor/include/match.h
@@ -185,6 +185,7 @@ static inline void aa_put_dfa(struct aa_dfa *dfa)
#define MATCH_FLAG_DIFF_ENCODE 0x80000000
#define MARK_DIFF_ENCODE 0x40000000
#define MATCH_FLAG_OOB_TRANSITION 0x20000000
+#define MARK_DIFF_ENCODE_VERIFIED 0x10000000
#define MATCH_FLAGS_MASK 0xff000000
#define MATCH_FLAGS_VALID (MATCH_FLAG_DIFF_ENCODE | MATCH_FLAG_OOB_TRANSITION)
#define MATCH_FLAGS_INVALID (MATCH_FLAGS_MASK & ~MATCH_FLAGS_VALID)
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index 5115ebae2661..3895f8774a3f 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -379,7 +379,7 @@ static inline bool profile_mediates_safe(struct aa_profile *profile,
static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
{
if (p)
- kref_get(&(p->label.count));
+ kref_get(&(p->label.count.count));
return p;
}
@@ -393,7 +393,7 @@ static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
*/
static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p)
{
- if (p && kref_get_unless_zero(&p->label.count))
+ if (p && kref_get_unless_zero(&p->label.count.count))
return p;
return NULL;
@@ -413,7 +413,7 @@ static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p)
rcu_read_lock();
do {
c = rcu_dereference(*p);
- } while (c && !kref_get_unless_zero(&c->label.count));
+ } while (c && !kref_get_unless_zero(&c->label.count.count));
rcu_read_unlock();
return c;
@@ -426,7 +426,7 @@ static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p)
static inline void aa_put_profile(struct aa_profile *p)
{
if (p)
- kref_put(&p->label.count, aa_label_kref);
+ kref_put(&p->label.count.count, aa_label_kref);
}
static inline int AUDIT_MODE(struct aa_profile *profile)
@@ -443,7 +443,7 @@ bool aa_policy_admin_capable(const struct cred *subj_cred,
struct aa_label *label, struct aa_ns *ns);
int aa_may_manage_policy(const struct cred *subj_cred,
struct aa_label *label, struct aa_ns *ns,
- u32 mask);
+ const struct cred *ocred, u32 mask);
bool aa_current_policy_view_capable(struct aa_ns *ns);
bool aa_current_policy_admin_capable(struct aa_ns *ns);
diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h
index d646070fd966..cc6e84151812 100644
--- a/security/apparmor/include/policy_ns.h
+++ b/security/apparmor/include/policy_ns.h
@@ -18,6 +18,8 @@
#include "label.h"
#include "policy.h"
+/* Match max depth of user namespaces */
+#define MAX_NS_DEPTH 32
/* struct aa_ns_acct - accounting of profiles in namespace
* @max_size: maximum space allowed for all profiles in namespace
diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
index a6f4611ee50c..e5a95dc4da1f 100644
--- a/security/apparmor/include/policy_unpack.h
+++ b/security/apparmor/include/policy_unpack.h
@@ -87,17 +87,29 @@ struct aa_ext {
u32 version;
};
-/*
- * struct aa_loaddata - buffer of policy raw_data set
+/* struct aa_loaddata - buffer of policy raw_data set
+ * @count: inode/filesystem refcount - use aa_get_i_loaddata()
+ * @pcount: profile refcount - use aa_get_profile_loaddata()
+ * @list: list the loaddata is on
+ * @work: used to do a delayed cleanup
+ * @dents: refs to dents created in aafs
+ * @ns: the namespace this loaddata was loaded into
+ * @name:
+ * @size: the size of the data that was loaded
+ * @compressed_size: the size of the data when it is compressed
+ * @revision: unique revision count that this data was loaded as
+ * @abi: the abi number the loaddata uses
+ * @hash: a hash of the loaddata, used to help dedup data
*
- * there is no loaddata ref for being on ns list, nor a ref from
- * d_inode(@dentry) when grab a ref from these, @ns->lock must be held
- * && __aa_get_loaddata() needs to be used, and the return value
- * checked, if NULL the loaddata is already being reaped and should be
- * considered dead.
+ * There is no loaddata ref for being on ns->rawdata_list, so
+ * @ns->lock must be held when walking the list. Dentries and
+ * inode opens hold refs on @count; profiles hold refs on @pcount.
+ * When the last @pcount drops, do_ploaddata_rmfs() removes the
+ * fs entries and drops the associated @count ref.
*/
struct aa_loaddata {
- struct kref count;
+ struct aa_common_ref count;
+ struct kref pcount;
struct list_head list;
struct work_struct work;
struct dentry *dents[AAFS_LOADDATA_NDENTS];
@@ -119,50 +131,53 @@ struct aa_loaddata {
int aa_unpack(struct aa_loaddata *udata, struct list_head *lh, const char **ns);
/**
- * __aa_get_loaddata - get a reference count to uncounted data reference
+ * aa_get_loaddata - get a reference count from a counted data reference
* @data: reference to get a count on
*
- * Returns: pointer to reference OR NULL if race is lost and reference is
- * being repeated.
- * Requires: @data->ns->lock held, and the return code MUST be checked
- *
- * Use only from inode->i_private and @data->list found references
+ * Returns: pointer to reference
+ * Requires: @data to have a valid reference count on it. It is a bug
+ * if the race to reap can be encountered when it is used.
*/
static inline struct aa_loaddata *
-__aa_get_loaddata(struct aa_loaddata *data)
+aa_get_i_loaddata(struct aa_loaddata *data)
{
- if (data && kref_get_unless_zero(&(data->count)))
- return data;
- return NULL;
+ if (data)
+ kref_get(&(data->count.count));
+ return data;
}
+
/**
- * aa_get_loaddata - get a reference count from a counted data reference
+ * aa_get_profile_loaddata - get a profile reference count on loaddata
* @data: reference to get a count on
*
- * Returns: point to reference
- * Requires: @data to have a valid reference count on it. It is a bug
- * if the race to reap can be encountered when it is used.
+ * Returns: pointer to reference
+ * Requires: @data to have a valid reference count on it.
*/
static inline struct aa_loaddata *
-aa_get_loaddata(struct aa_loaddata *data)
+aa_get_profile_loaddata(struct aa_loaddata *data)
{
- struct aa_loaddata *tmp = __aa_get_loaddata(data);
-
- AA_BUG(data && !tmp);
-
- return tmp;
+ if (data)
+ kref_get(&(data->pcount));
+ return data;
}
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);
+void aa_ploaddata_kref(struct kref *kref);
struct aa_loaddata *aa_loaddata_alloc(size_t size);
-static inline void aa_put_loaddata(struct aa_loaddata *data)
+static inline void aa_put_i_loaddata(struct aa_loaddata *data)
+{
+ if (data)
+ kref_put(&data->count.count, aa_loaddata_kref);
+}
+
+static inline void aa_put_profile_loaddata(struct aa_loaddata *data)
{
if (data)
- kref_put(&data->count, aa_loaddata_kref);
+ kref_put(&data->pcount, aa_ploaddata_kref);
}
#if IS_ENABLED(CONFIG_KUNIT)