Commit 281f36d4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'apparmor-pr-mainline-2026-03-09' of...

Merge tag 'apparmor-pr-mainline-2026-03-09' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor

Pull AppArmor fixes from John Johansen:
 - fix race between freeing data and fs accessing it
 - fix race on unreferenced rawdata dereference
 - fix differential encoding verification
 - fix unconfined unprivileged local user can do privileged policy management
 - Fix double free of ns_name in aa_replace_profiles()
 - fix missing bounds check on DEFAULT table in verify_dfa()
 - fix side-effect bug in match_char() macro usage
 - fix: limit the number of levels of policy namespaces
 - replace recursive profile removal with iterative approach
 - fix memory leak in verify_header
 - validate DFA start states are in bounds in unpack_pdb

* tag 'apparmor-pr-mainline-2026-03-09' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
  apparmor: fix race between freeing data and fs accessing it
  apparmor: fix race on rawdata dereference
  apparmor: fix differential encoding verification
  apparmor: fix unprivileged local user can do privileged policy management
  apparmor: Fix double free of ns_name in aa_replace_profiles()
  apparmor: fix missing bounds check on DEFAULT table in verify_dfa()
  apparmor: fix side-effect bug in match_char() macro usage
  apparmor: fix: limit the number of levels of policy namespaces
  apparmor: replace recursive profile removal with iterative approach
  apparmor: fix memory leak in verify_header
  apparmor: validate DFA start states are in bounds in unpack_pdb
parents 80234b5a 8e135b8a
Loading
Loading
Loading
Loading
+134 −91
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include "include/crypto.h"
#include "include/ipc.h"
#include "include/label.h"
#include "include/lib.h"
#include "include/policy.h"
#include "include/policy_ns.h"
#include "include/resource.h"
@@ -62,6 +63,7 @@
 * securityfs and apparmorfs filesystems.
 */

#define IREF_POISON 101

/*
 * support fns
@@ -79,7 +81,7 @@ static void rawdata_f_data_free(struct rawdata_f_data *private)
	if (!private)
		return;

	aa_put_loaddata(private->loaddata);
	aa_put_i_loaddata(private->loaddata);
	kvfree(private);
}

@@ -153,6 +155,71 @@ static int aafs_show_path(struct seq_file *seq, struct dentry *dentry)
	return 0;
}

static struct aa_ns *get_ns_common_ref(struct aa_common_ref *ref)
{
	if (ref) {
		struct aa_label *reflabel = container_of(ref, struct aa_label,
							 count);
		return aa_get_ns(labels_ns(reflabel));
	}

	return NULL;
}

static struct aa_proxy *get_proxy_common_ref(struct aa_common_ref *ref)
{
	if (ref)
		return aa_get_proxy(container_of(ref, struct aa_proxy, count));

	return NULL;
}

static struct aa_loaddata *get_loaddata_common_ref(struct aa_common_ref *ref)
{
	if (ref)
		return aa_get_i_loaddata(container_of(ref, struct aa_loaddata,
						      count));
	return NULL;
}

static void aa_put_common_ref(struct aa_common_ref *ref)
{
	if (!ref)
		return;

	switch (ref->reftype) {
	case REF_RAWDATA:
		aa_put_i_loaddata(container_of(ref, struct aa_loaddata,
					       count));
		break;
	case REF_PROXY:
		aa_put_proxy(container_of(ref, struct aa_proxy,
					  count));
		break;
	case REF_NS:
		/* ns count is held on its unconfined label */
		aa_put_ns(labels_ns(container_of(ref, struct aa_label, count)));
		break;
	default:
		AA_BUG(true, "unknown refcount type");
		break;
	}
}

static void aa_get_common_ref(struct aa_common_ref *ref)
{
	kref_get(&ref->count);
}

static void aafs_evict(struct inode *inode)
{
	struct aa_common_ref *ref = inode->i_private;

	clear_inode(inode);
	aa_put_common_ref(ref);
	inode->i_private = (void *) IREF_POISON;
}

static void aafs_free_inode(struct inode *inode)
{
	if (S_ISLNK(inode->i_mode))
@@ -162,6 +229,7 @@ static void aafs_free_inode(struct inode *inode)

static const struct super_operations aafs_super_ops = {
	.statfs = simple_statfs,
	.evict_inode = aafs_evict,
	.free_inode = aafs_free_inode,
	.show_path = aafs_show_path,
};
@@ -262,7 +330,8 @@ static int __aafs_setup_d_inode(struct inode *dir, struct dentry *dentry,
 * aafs_remove(). Will return ERR_PTR on failure.
 */
static struct dentry *aafs_create(const char *name, umode_t mode,
				  struct dentry *parent, void *data, void *link,
				  struct dentry *parent,
				  struct aa_common_ref *data, void *link,
				  const struct file_operations *fops,
				  const struct inode_operations *iops)
{
@@ -299,6 +368,9 @@ static struct dentry *aafs_create(const char *name, umode_t mode,
		goto fail_dentry;
	inode_unlock(dir);

	if (data)
		aa_get_common_ref(data);

	return dentry;

fail_dentry:
@@ -323,7 +395,8 @@ static struct dentry *aafs_create(const char *name, umode_t mode,
 * see aafs_create
 */
static struct dentry *aafs_create_file(const char *name, umode_t mode,
				       struct dentry *parent, void *data,
				       struct dentry *parent,
				       struct aa_common_ref *data,
				       const struct file_operations *fops)
{
	return aafs_create(name, mode, parent, data, NULL, fops, NULL);
@@ -409,7 +482,8 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,

	data->size = copy_size;
	if (copy_from_user(data->data, userbuf, copy_size)) {
		aa_put_loaddata(data);
		/* trigger free - don't need to put pcount */
		aa_put_i_loaddata(data);
		return ERR_PTR(-EFAULT);
	}

@@ -417,7 +491,8 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,
}

static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
			     loff_t *pos, struct aa_ns *ns)
			     loff_t *pos, struct aa_ns *ns,
			     const struct cred *ocred)
{
	struct aa_loaddata *data;
	struct aa_label *label;
@@ -428,7 +503,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
	/* high level check about policy management - fine grained in
	 * below after unpack
	 */
	error = aa_may_manage_policy(current_cred(), label, ns, mask);
	error = aa_may_manage_policy(current_cred(), label, ns, ocred, mask);
	if (error)
		goto end_section;

@@ -436,7 +511,10 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
	error = PTR_ERR(data);
	if (!IS_ERR(data)) {
		error = aa_replace_profiles(ns, label, mask, data);
		aa_put_loaddata(data);
		/* put pcount, which will put count and free if no
		 * profiles referencing it.
		 */
		aa_put_profile_loaddata(data);
	}
end_section:
	end_current_label_crit_section(label);
@@ -448,8 +526,9 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size,
static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
			    loff_t *pos)
{
	struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
	int error = policy_update(AA_MAY_LOAD_POLICY, buf, size, pos, ns);
	struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private);
	int error = policy_update(AA_MAY_LOAD_POLICY, buf, size, pos, ns,
				  f->f_cred);

	aa_put_ns(ns);

@@ -465,9 +544,9 @@ static const struct file_operations aa_fs_profile_load = {
static ssize_t profile_replace(struct file *f, const char __user *buf,
			       size_t size, loff_t *pos)
{
	struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
	struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private);
	int error = policy_update(AA_MAY_LOAD_POLICY | AA_MAY_REPLACE_POLICY,
				  buf, size, pos, ns);
				  buf, size, pos, ns, f->f_cred);
	aa_put_ns(ns);

	return error;
@@ -485,14 +564,14 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
	struct aa_loaddata *data;
	struct aa_label *label;
	ssize_t error;
	struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
	struct aa_ns *ns = get_ns_common_ref(f->f_inode->i_private);

	label = begin_current_label_crit_section();
	/* high level check about policy management - fine grained in
	 * below after unpack
	 */
	error = aa_may_manage_policy(current_cred(), label, ns,
				     AA_MAY_REMOVE_POLICY);
				     f->f_cred, AA_MAY_REMOVE_POLICY);
	if (error)
		goto out;

@@ -506,7 +585,7 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
	if (!IS_ERR(data)) {
		data->data[size] = 0;
		error = aa_remove_profiles(ns, label, data->data, size);
		aa_put_loaddata(data);
		aa_put_profile_loaddata(data);
	}
 out:
	end_current_label_crit_section(label);
@@ -575,7 +654,7 @@ static int ns_revision_open(struct inode *inode, struct file *file)
	if (!rev)
		return -ENOMEM;

	rev->ns = aa_get_ns(inode->i_private);
	rev->ns = get_ns_common_ref(inode->i_private);
	if (!rev->ns)
		rev->ns = aa_get_current_ns();
	file->private_data = rev;
@@ -1061,7 +1140,7 @@ static const struct file_operations seq_profile_ ##NAME ##_fops = { \
static int seq_profile_open(struct inode *inode, struct file *file,
			    int (*show)(struct seq_file *, void *))
{
	struct aa_proxy *proxy = aa_get_proxy(inode->i_private);
	struct aa_proxy *proxy = get_proxy_common_ref(inode->i_private);
	int error = single_open(file, show, proxy);

	if (error) {
@@ -1253,18 +1332,17 @@ static const struct file_operations seq_rawdata_ ##NAME ##_fops = { \
static int seq_rawdata_open(struct inode *inode, struct file *file,
			    int (*show)(struct seq_file *, void *))
{
	struct aa_loaddata *data = __aa_get_loaddata(inode->i_private);
	struct aa_loaddata *data = get_loaddata_common_ref(inode->i_private);
	int error;

	if (!data)
		/* lost race this ent is being reaped */
		return -ENOENT;

	error = single_open(file, show, data);
	if (error) {
		AA_BUG(file->private_data &&
		       ((struct seq_file *)file->private_data)->private);
		aa_put_loaddata(data);
		aa_put_i_loaddata(data);
	}

	return error;
@@ -1275,7 +1353,7 @@ static int seq_rawdata_release(struct inode *inode, struct file *file)
	struct seq_file *seq = (struct seq_file *) file->private_data;

	if (seq)
		aa_put_loaddata(seq->private);
		aa_put_i_loaddata(seq->private);

	return single_release(inode, file);
}
@@ -1387,9 +1465,8 @@ static int rawdata_open(struct inode *inode, struct file *file)
	if (!aa_current_policy_view_capable(NULL))
		return -EACCES;

	loaddata = __aa_get_loaddata(inode->i_private);
	loaddata = get_loaddata_common_ref(inode->i_private);
	if (!loaddata)
		/* lost race: this entry is being reaped */
		return -ENOENT;

	private = rawdata_f_data_alloc(loaddata->size);
@@ -1414,7 +1491,7 @@ static int rawdata_open(struct inode *inode, struct file *file)
	return error;

fail_private_alloc:
	aa_put_loaddata(loaddata);
	aa_put_i_loaddata(loaddata);
	return error;
}

@@ -1431,7 +1508,6 @@ static void remove_rawdata_dents(struct aa_loaddata *rawdata)

	for (i = 0; i < AAFS_LOADDATA_NDENTS; i++) {
		if (!IS_ERR_OR_NULL(rawdata->dents[i])) {
			/* no refcounts on i_private */
			aafs_remove(rawdata->dents[i]);
			rawdata->dents[i] = NULL;
		}
@@ -1474,13 +1550,14 @@ int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata)
		return PTR_ERR(dir);
	rawdata->dents[AAFS_LOADDATA_DIR] = dir;

	dent = aafs_create_file("abi", S_IFREG | 0444, dir, rawdata,
	dent = aafs_create_file("abi", S_IFREG | 0444, dir, &rawdata->count,
				      &seq_rawdata_abi_fops);
	if (IS_ERR(dent))
		goto fail;
	rawdata->dents[AAFS_LOADDATA_ABI] = dent;

	dent = aafs_create_file("revision", S_IFREG | 0444, dir, rawdata,
	dent = aafs_create_file("revision", S_IFREG | 0444, dir,
				&rawdata->count,
				&seq_rawdata_revision_fops);
	if (IS_ERR(dent))
		goto fail;
@@ -1488,21 +1565,22 @@ int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata)

	if (aa_g_hash_policy) {
		dent = aafs_create_file("sha256", S_IFREG | 0444, dir,
					      rawdata, &seq_rawdata_hash_fops);
					&rawdata->count,
					&seq_rawdata_hash_fops);
		if (IS_ERR(dent))
			goto fail;
		rawdata->dents[AAFS_LOADDATA_HASH] = dent;
	}

	dent = aafs_create_file("compressed_size", S_IFREG | 0444, dir,
				rawdata,
				&rawdata->count,
				&seq_rawdata_compressed_size_fops);
	if (IS_ERR(dent))
		goto fail;
	rawdata->dents[AAFS_LOADDATA_COMPRESSED_SIZE] = dent;

	dent = aafs_create_file("raw_data", S_IFREG | 0444,
				      dir, rawdata, &rawdata_fops);
	dent = aafs_create_file("raw_data", S_IFREG | 0444, dir,
				&rawdata->count, &rawdata_fops);
	if (IS_ERR(dent))
		goto fail;
	rawdata->dents[AAFS_LOADDATA_DATA] = dent;
@@ -1510,13 +1588,11 @@ int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata)

	rawdata->ns = aa_get_ns(ns);
	list_add(&rawdata->list, &ns->rawdata_list);
	/* no refcount on inode rawdata */

	return 0;

fail:
	remove_rawdata_dents(rawdata);

	return PTR_ERR(dent);
}
#endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */
@@ -1540,13 +1616,10 @@ void __aafs_profile_rmdir(struct aa_profile *profile)
		__aafs_profile_rmdir(child);

	for (i = AAFS_PROF_SIZEOF - 1; i >= 0; --i) {
		struct aa_proxy *proxy;
		if (!profile->dents[i])
			continue;

		proxy = d_inode(profile->dents[i])->i_private;
		aafs_remove(profile->dents[i]);
		aa_put_proxy(proxy);
		profile->dents[i] = NULL;
	}
}
@@ -1580,14 +1653,7 @@ static struct dentry *create_profile_file(struct dentry *dir, const char *name,
					  struct aa_profile *profile,
					  const struct file_operations *fops)
{
	struct aa_proxy *proxy = aa_get_proxy(profile->label.proxy);
	struct dentry *dent;

	dent = aafs_create_file(name, S_IFREG | 0444, dir, proxy, fops);
	if (IS_ERR(dent))
		aa_put_proxy(proxy);

	return dent;
	return aafs_create_file(name, S_IFREG | 0444, dir, &profile->label.proxy->count, fops);
}

#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
@@ -1637,7 +1703,8 @@ static const char *rawdata_get_link_base(struct dentry *dentry,
					 struct delayed_call *done,
					 const char *name)
{
	struct aa_proxy *proxy = inode->i_private;
	struct aa_common_ref *ref = inode->i_private;
	struct aa_proxy *proxy = container_of(ref, struct aa_proxy, count);
	struct aa_label *label;
	struct aa_profile *profile;
	char *target;
@@ -1779,27 +1846,24 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
	if (profile->rawdata) {
		if (aa_g_hash_policy) {
			dent = aafs_create("raw_sha256", S_IFLNK | 0444, dir,
					   profile->label.proxy, NULL, NULL,
					   &rawdata_link_sha256_iops);
					   &profile->label.proxy->count, NULL,
					   NULL, &rawdata_link_sha256_iops);
			if (IS_ERR(dent))
				goto fail;
			aa_get_proxy(profile->label.proxy);
			profile->dents[AAFS_PROF_RAW_HASH] = dent;
		}
		dent = aafs_create("raw_abi", S_IFLNK | 0444, dir,
				   profile->label.proxy, NULL, NULL,
				   &profile->label.proxy->count, NULL, NULL,
				   &rawdata_link_abi_iops);
		if (IS_ERR(dent))
			goto fail;
		aa_get_proxy(profile->label.proxy);
		profile->dents[AAFS_PROF_RAW_ABI] = dent;

		dent = aafs_create("raw_data", S_IFLNK | 0444, dir,
				   profile->label.proxy, NULL, NULL,
				   &profile->label.proxy->count, NULL, NULL,
				   &rawdata_link_data_iops);
		if (IS_ERR(dent))
			goto fail;
		aa_get_proxy(profile->label.proxy);
		profile->dents[AAFS_PROF_RAW_DATA] = dent;
	}
#endif /*CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */
@@ -1830,13 +1894,13 @@ static struct dentry *ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir,
	int error;

	label = begin_current_label_crit_section();
	error = aa_may_manage_policy(current_cred(), label, NULL,
	error = aa_may_manage_policy(current_cred(), label, NULL, NULL,
				     AA_MAY_LOAD_POLICY);
	end_current_label_crit_section(label);
	if (error)
		return ERR_PTR(error);

	parent = aa_get_ns(dir->i_private);
	parent = get_ns_common_ref(dir->i_private);
	AA_BUG(d_inode(ns_subns_dir(parent)) != dir);

	/* we have to unlock and then relock to get locking order right
@@ -1880,13 +1944,13 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
	int error;

	label = begin_current_label_crit_section();
	error = aa_may_manage_policy(current_cred(), label, NULL,
	error = aa_may_manage_policy(current_cred(), label, NULL, NULL,
				     AA_MAY_LOAD_POLICY);
	end_current_label_crit_section(label);
	if (error)
		return error;

	parent = aa_get_ns(dir->i_private);
	parent = get_ns_common_ref(dir->i_private);
	/* rmdir calls the generic securityfs functions to remove files
	 * from the apparmor dir. It is up to the apparmor ns locking
	 * to avoid races.
@@ -1956,27 +2020,6 @@ void __aafs_ns_rmdir(struct aa_ns *ns)

	__aa_fs_list_remove_rawdata(ns);

	if (ns_subns_dir(ns)) {
		sub = d_inode(ns_subns_dir(ns))->i_private;
		aa_put_ns(sub);
	}
	if (ns_subload(ns)) {
		sub = d_inode(ns_subload(ns))->i_private;
		aa_put_ns(sub);
	}
	if (ns_subreplace(ns)) {
		sub = d_inode(ns_subreplace(ns))->i_private;
		aa_put_ns(sub);
	}
	if (ns_subremove(ns)) {
		sub = d_inode(ns_subremove(ns))->i_private;
		aa_put_ns(sub);
	}
	if (ns_subrevision(ns)) {
		sub = d_inode(ns_subrevision(ns))->i_private;
		aa_put_ns(sub);
	}

	for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) {
		aafs_remove(ns->dents[i]);
		ns->dents[i] = NULL;
@@ -2001,40 +2044,40 @@ static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir)
		return PTR_ERR(dent);
	ns_subdata_dir(ns) = dent;

	dent = aafs_create_file("revision", 0444, dir, ns,
	dent = aafs_create_file("revision", 0444, dir,
				&ns->unconfined->label.count,
				&aa_fs_ns_revision_fops);
	if (IS_ERR(dent))
		return PTR_ERR(dent);
	aa_get_ns(ns);
	ns_subrevision(ns) = dent;

	dent = aafs_create_file(".load", 0640, dir, ns,
	dent = aafs_create_file(".load", 0640, dir,
				&ns->unconfined->label.count,
				&aa_fs_profile_load);
	if (IS_ERR(dent))
		return PTR_ERR(dent);
	aa_get_ns(ns);
	ns_subload(ns) = dent;

	dent = aafs_create_file(".replace", 0640, dir, ns,
	dent = aafs_create_file(".replace", 0640, dir,
				&ns->unconfined->label.count,
				&aa_fs_profile_replace);
	if (IS_ERR(dent))
		return PTR_ERR(dent);
	aa_get_ns(ns);
	ns_subreplace(ns) = dent;

	dent = aafs_create_file(".remove", 0640, dir, ns,
	dent = aafs_create_file(".remove", 0640, dir,
				&ns->unconfined->label.count,
				&aa_fs_profile_remove);
	if (IS_ERR(dent))
		return PTR_ERR(dent);
	aa_get_ns(ns);
	ns_subremove(ns) = dent;

	  /* use create_dentry so we can supply private data */
	dent = aafs_create("namespaces", S_IFDIR | 0755, dir, ns, NULL, NULL,
			   &ns_dir_inode_operations);
	dent = aafs_create("namespaces", S_IFDIR | 0755, dir,
			   &ns->unconfined->label.count,
			   NULL, NULL, &ns_dir_inode_operations);
	if (IS_ERR(dent))
		return PTR_ERR(dent);
	aa_get_ns(ns);
	ns_subns_dir(ns) = dent;

	return 0;
+8 −8
Original line number Diff line number Diff line
@@ -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);
+12 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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)
+5 −5
Original line number Diff line number Diff line
@@ -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);

Loading