summaryrefslogtreecommitdiffstats
path: root/security/apparmor
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-06-09 08:14:28 -0700
committerJohn Johansen <john.johansen@canonical.com>2017-06-10 17:11:38 -0700
commit637f688dc3dc304a89f441d76f49a0e35bc49c08 (patch)
tree78fee8a7aa212140c4c6b6a9b722bbba61802cab /security/apparmor
parentf1bd904175e8190ce14aedee37e207ab51fe3b30 (diff)
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>
Diffstat (limited to 'security/apparmor')
-rw-r--r--security/apparmor/Makefile2
-rw-r--r--security/apparmor/apparmorfs.c128
-rw-r--r--security/apparmor/audit.c27
-rw-r--r--security/apparmor/context.c87
-rw-r--r--security/apparmor/domain.c77
-rw-r--r--security/apparmor/file.c18
-rw-r--r--security/apparmor/include/apparmor.h5
-rw-r--r--security/apparmor/include/audit.h9
-rw-r--r--security/apparmor/include/context.h158
-rw-r--r--security/apparmor/include/perms.h12
-rw-r--r--security/apparmor/include/policy.h110
-rw-r--r--security/apparmor/include/policy_ns.h4
-rw-r--r--security/apparmor/ipc.c29
-rw-r--r--security/apparmor/lib.c163
-rw-r--r--security/apparmor/lsm.c134
-rw-r--r--security/apparmor/policy.c208
-rw-r--r--security/apparmor/policy_ns.c20
-rw-r--r--security/apparmor/policy_unpack.c12
-rw-r--r--security/apparmor/procattr.c4
-rw-r--r--security/apparmor/resource.c8
20 files changed, 686 insertions, 529 deletions
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index b3e7c04b7e7b..a16b195274de 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
- resource.o secid.o file.o policy_ns.o
+ resource.o secid.o file.o policy_ns.o label.o
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
clean-files := capability_names.h rlim_names.h
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index e2919a0766b0..976af6da45c3 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -405,26 +405,26 @@ 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)
{
- ssize_t error;
struct aa_loaddata *data;
- struct aa_profile *profile;
+ struct aa_label *label;
+ ssize_t error;
- profile = begin_current_profile_crit_section();
+ label = begin_current_label_crit_section();
/* high level check about policy management - fine grained in
* below after unpack
*/
- error = aa_may_manage_policy(profile, ns, mask);
+ error = aa_may_manage_policy(label, ns, mask);
if (error)
return error;
data = aa_simple_write_to_buffer(buf, size, size, pos);
error = PTR_ERR(data);
if (!IS_ERR(data)) {
- error = aa_replace_profiles(ns, profile, mask, data);
+ error = aa_replace_profiles(ns, label, mask, data);
aa_put_loaddata(data);
}
- end_current_profile_crit_section(profile);
+ end_current_label_crit_section(label);
return error;
}
@@ -468,15 +468,15 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
{
struct aa_loaddata *data;
- struct aa_profile *profile;
+ struct aa_label *label;
ssize_t error;
struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
- profile = begin_current_profile_crit_section();
+ label = begin_current_label_crit_section();
/* high level check about policy management - fine grained in
* below after unpack
*/
- error = aa_may_manage_policy(profile, ns, AA_MAY_REMOVE_POLICY);
+ error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY);
if (error)
goto out;
@@ -489,11 +489,11 @@ static ssize_t profile_remove(struct file *f, const char __user *buf,
error = PTR_ERR(data);
if (!IS_ERR(data)) {
data->data[size] = 0;
- error = aa_remove_profiles(ns, profile, data->data, size);
+ error = aa_remove_profiles(ns, label, data->data, size);
aa_put_loaddata(data);
}
out:
- end_current_profile_crit_section(profile);
+ end_current_label_crit_section(label);
aa_put_ns(ns);
return error;
}
@@ -605,7 +605,7 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
struct aa_dfa *dfa;
unsigned int state = 0;
- if (unconfined(profile))
+ if (profile_unconfined(profile))
return;
if (profile->file.dfa && *match_str == AA_CLASS_FILE) {
dfa = profile->file.dfa;
@@ -655,7 +655,7 @@ static ssize_t query_data(char *buf, size_t buf_len,
{
char *out;
const char *key;
- struct aa_profile *profile, *curr;
+ struct aa_label *label, *curr;
struct aa_data *data;
u32 bytes, blocks;
__le32 outle32;
@@ -672,11 +672,11 @@ static ssize_t query_data(char *buf, size_t buf_len,
if (buf_len < sizeof(bytes) + sizeof(blocks))
return -EINVAL; /* not enough space */
- curr = begin_current_profile_crit_section();
- profile = aa_fqlookupn_profile(curr, query, strnlen(query, query_len));
- end_current_profile_crit_section(curr);
- if (!profile)
- return -ENOENT;
+ curr = begin_current_label_crit_section();
+ label = aa_label_parse(curr, query, GFP_KERNEL, false, false);
+ end_current_label_crit_section(curr);
+ if (IS_ERR(label))
+ return PTR_ERR(label);
/* We are going to leave space for two numbers. The first is the total
* number of bytes we are writing after the first number. This is so
@@ -690,13 +690,16 @@ static ssize_t query_data(char *buf, size_t buf_len,
out = buf + sizeof(bytes) + sizeof(blocks);
blocks = 0;
- if (profile->data) {
- data = rhashtable_lookup_fast(profile->data, &key,
- profile->data->p);
+ if (labels_profile(label)->data) {
+ data = rhashtable_lookup_fast(labels_profile(label)->data, &key,
+ labels_profile(label)->data->p);
if (data) {
- if (out + sizeof(outle32) + data->size > buf + buf_len)
+ if (out + sizeof(outle32) + data->size >
+ buf + buf_len) {
+ aa_put_label(label);
return -EINVAL; /* not enough space */
+ }
outle32 = __cpu_to_le32(data->size);
memcpy(out, &outle32, sizeof(outle32));
out += sizeof(outle32);
@@ -705,7 +708,7 @@ static ssize_t query_data(char *buf, size_t buf_len,
blocks++;
}
}
- aa_put_profile(profile);
+ aa_put_label(label);
outle32 = __cpu_to_le32(out - buf - sizeof(bytes));
memcpy(buf, &outle32, sizeof(outle32));
@@ -738,7 +741,7 @@ static ssize_t query_data(char *buf, size_t buf_len,
static ssize_t query_label(char *buf, size_t buf_len,
char *query, size_t query_len, bool view_only)
{
- struct aa_profile *profile, *curr;
+ struct aa_label *label, *curr;
char *label_name, *match_str;
size_t label_name_len, match_len;
struct aa_perms perms;
@@ -760,14 +763,14 @@ static ssize_t query_label(char *buf, size_t buf_len,
match_str = label_name + label_name_len + 1;
match_len = query_len - label_name_len - 1;
- curr = begin_current_profile_crit_section();
- profile = aa_fqlookupn_profile(curr, label_name, label_name_len);
- end_current_profile_crit_section(curr);
- if (!profile)
- return -ENOENT;
+ curr = begin_current_label_crit_section();
+ label = aa_label_parse(curr, label_name, GFP_KERNEL, false, false);
+ end_current_label_crit_section(curr);
+ if (IS_ERR(label))
+ return PTR_ERR(label);
perms = allperms;
- profile_query_cb(profile, &perms, match_str, match_len);
+ profile_query_cb(labels_profile(label), &perms, match_str, match_len);
return scnprintf(buf, buf_len,
"allow 0x%08x\ndeny 0x%08x\naudit 0x%08x\nquiet 0x%08x\n",
@@ -1026,9 +1029,10 @@ static int seq_profile_release(struct inode *inode, struct file *file)
static int seq_profile_name_show(struct seq_file *seq, void *v)
{
struct aa_proxy *proxy = seq->private;
- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
+ struct aa_label *label = aa_get_label_rcu(&proxy->label);
+ struct aa_profile *profile = labels_profile(label);
seq_printf(seq, "%s\n", profile->base.name);
- aa_put_profile(profile);
+ aa_put_label(label);
return 0;
}
@@ -1036,9 +1040,10 @@ static int seq_profile_name_show(struct seq_file *seq, void *v)
static int seq_profile_mode_show(struct seq_file *seq, void *v)
{
struct aa_proxy *proxy = seq->private;
- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
+ struct aa_label *label = aa_get_label_rcu(&proxy->label);
+ struct aa_profile *profile = labels_profile(label);
seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]);
- aa_put_profile(profile);
+ aa_put_label(label);
return 0;
}
@@ -1046,14 +1051,15 @@ static int seq_profile_mode_show(struct seq_file *seq, void *v)
static int seq_profile_attach_show(struct seq_file *seq, void *v)
{
struct aa_proxy *proxy = seq->private;
- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
+ struct aa_label *label = aa_get_label_rcu(&proxy->label);
+ struct aa_profile *profile = labels_profile(label);
if (profile->attach)
seq_printf(seq, "%s\n", profile->attach);
else if (profile->xmatch)
seq_puts(seq, "<unknown>\n");
else
seq_printf(seq, "%s\n", profile->base.name);
- aa_put_profile(profile);
+ aa_put_label(label);
return 0;
}
@@ -1061,7 +1067,8 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v)
static int seq_profile_hash_show(struct seq_file *seq, void *v)
{
struct aa_proxy *proxy = seq->private;
- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
+ struct aa_label *label = aa_get_label_rcu(&proxy->label);
+ struct aa_profile *profile = labels_profile(label);
unsigned int i, size = aa_hash_size();
if (profile->hash) {
@@ -1069,7 +1076,7 @@ static int seq_profile_hash_show(struct seq_file *seq, void *v)
seq_printf(seq, "%.2x", profile->hash[i]);
seq_putc(seq, '\n');
}
- aa_put_profile(profile);
+ aa_put_label(label);
return 0;
}
@@ -1101,22 +1108,22 @@ static const struct file_operations seq_ns_ ##NAME ##_fops = { \
static int seq_ns_level_show(struct seq_file *seq, void *v)
{
- struct aa_profile *profile;
+ struct aa_label *label;
- profile = begin_current_profile_crit_section();
- seq_printf(seq, "%d\n", profile->ns->level);
- end_current_profile_crit_section(profile);
+ label = begin_current_label_crit_section();
+ seq_printf(seq, "%d\n", labels_ns(label)->level);
+ end_current_label_crit_section(label);
return 0;
}
static int seq_ns_name_show(struct seq_file *seq, void *v)
{
- struct aa_profile *profile;
+ struct aa_label *label = begin_current_label_crit_section();
- profile = begin_current_profile_crit_section();
- seq_printf(seq, "%s\n", aa_ns_name(profile->ns, profile->ns, true));
- end_current_profile_crit_section(profile);
+ seq_printf(seq, "%s\n", aa_ns_name(labels_ns(label),
+ labels_ns(label), true));
+ end_current_label_crit_section(label);
return 0;
}
@@ -1380,7 +1387,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->proxy);
+ struct aa_proxy *proxy = aa_get_proxy(profile->label.proxy);
struct dentry *dent;
dent = aafs_create_file(name, S_IFREG | 0444, dir, proxy, fops);
@@ -1541,9 +1548,12 @@ static int ns_mkdir_op(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct aa_ns *ns, *parent;
/* TODO: improve permission check */
- struct aa_profile *profile = begin_current_profile_crit_section();
- int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY);
- end_current_profile_crit_section(profile);
+ struct aa_label *label;
+ int error;
+
+ label = begin_current_label_crit_section();
+ error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
+ end_current_label_crit_section(label);
if (error)
return error;
@@ -1587,13 +1597,16 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry)
{
struct aa_ns *ns, *parent;
/* TODO: improve permission check */
- struct aa_profile *profile = begin_current_profile_crit_section();
- int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY);
- end_current_profile_crit_section(profile);
+ struct aa_label *label;
+ int error;
+
+ label = begin_current_label_crit_section();
+ error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY);
+ end_current_label_crit_section(label);
if (error)
return error;
- parent = aa_get_ns(dir->i_private);
+ parent = aa_get_ns(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.
@@ -1999,10 +2012,9 @@ static int seq_show_profile(struct seq_file *f, void *p)
struct aa_profile *profile = (struct aa_profile *)p;
struct aa_ns *root = f->private;
- if (profile->ns != root)
- seq_printf(f, ":%s://", aa_ns_name(root, profile->ns, true));
- seq_printf(f, "%s (%s)\n", profile->base.hname,
- aa_profile_mode_names[profile->mode]);
+ aa_label_seq_xprint(f, root, &profile->label,
+ FLAG_SHOW_MODE | FLAG_VIEW_SUBNS, GFP_KERNEL);
+ seq_putc(f, '\n');
return 0;
}
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 87f40fa8c431..8f9ecac7f8de 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -77,14 +77,24 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
audit_log_format(ab, " error=%d", aad(sa)->error);
}
- if (aad(sa)->profile) {
- struct aa_profile *profile = aad(sa)->profile;
- if (profile->ns != root_ns) {
- audit_log_format(ab, " namespace=");
- audit_log_untrustedstring(ab, profile->ns->base.hname);
+ if (aad(sa)->label) {
+ struct aa_label *label = aad(sa)->label;
+
+ if (label_isprofile(label)) {
+ struct aa_profile *profile = labels_profile(label);
+
+ if (profile->ns != root_ns) {
+ audit_log_format(ab, " namespace=");
+ audit_log_untrustedstring(ab,
+ profile->ns->base.hname);
+ }
+ audit_log_format(ab, " profile=");
+ audit_log_untrustedstring(ab, profile->base.hname);
+ } else {
+ audit_log_format(ab, " label=");
+ aa_label_xaudit(ab, root_ns, label, FLAG_VIEW_SUBNS,
+ GFP_ATOMIC);
}
- audit_log_format(ab, " profile=");
- audit_log_untrustedstring(ab, profile->base.hname);
}
if (aad(sa)->name) {
@@ -139,8 +149,7 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
type = AUDIT_APPARMOR_KILL;
- if (!unconfined(profile))
- aad(sa)->profile = profile;
+ aad(sa)->label = &profile->label;
aa_audit_msg(type, sa, cb);
diff --git a/security/apparmor/context.c b/security/apparmor/context.c
index 410b9f7f68a1..c95f1ac6190b 100644
--- a/security/apparmor/context.c
+++ b/security/apparmor/context.c
@@ -14,9 +14,9 @@
*
*
* AppArmor sets confinement on every task, via the the aa_task_ctx and
- * the aa_task_ctx.profile, both of which are required and are not allowed
+ * the aa_task_ctx.label, both of which are required and are not allowed
* to be NULL. The aa_task_ctx is not reference counted and is unique
- * to each cred (which is reference count). The profile pointed to by
+ * to each cred (which is reference count). The label pointed to by
* the task_ctx is reference counted.
*
* TODO
@@ -47,9 +47,9 @@ struct aa_task_ctx *aa_alloc_task_context(gfp_t flags)
void aa_free_task_context(struct aa_task_ctx *ctx)
{
if (ctx) {
- aa_put_profile(ctx->profile);
- aa_put_profile(ctx->previous);
- aa_put_profile(ctx->onexec);
+ aa_put_label(ctx->label);
+ aa_put_label(ctx->previous);
+ aa_put_label(ctx->onexec);
kzfree(ctx);
}
@@ -63,41 +63,41 @@ void aa_free_task_context(struct aa_task_ctx *ctx)
void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old)
{
*new = *old;
- aa_get_profile(new->profile);
- aa_get_profile(new->previous);
- aa_get_profile(new->onexec);
+ aa_get_label(new->label);
+ aa_get_label(new->previous);
+ aa_get_label(new->onexec);
}
/**
- * aa_get_task_profile - Get another task's profile
+ * aa_get_task_label - Get another task's label
* @task: task to query (NOT NULL)
*
- * Returns: counted reference to @task's profile
+ * Returns: counted reference to @task's label
*/
-struct aa_profile *aa_get_task_profile(struct task_struct *task)
+struct aa_label *aa_get_task_label(struct task_struct *task)
{
- struct aa_profile *p;
+ struct aa_label *p;
rcu_read_lock();
- p = aa_get_newest_profile(__aa_task_raw_profile(task));
+ p = aa_get_newest_label(__aa_task_raw_label(task));
rcu_read_unlock();
return p;
}
/**
- * aa_replace_current_profile - replace the current tasks profiles
- * @profile: new profile (NOT NULL)
+ * aa_replace_current_label - replace the current tasks label
+ * @label: new label (NOT NULL)
*
* Returns: 0 or error on failure
*/
-int aa_replace_current_profile(struct aa_profile *profile)
+int aa_replace_current_label(struct aa_label *label)
{
struct aa_task_ctx *ctx = current_ctx();
struct cred *new;
- AA_BUG(!profile);
+ AA_BUG(!label);
- if (ctx->profile == profile)
+ if (ctx->label == label)
return 0;
if (current_cred() != current_real_cred())
@@ -108,8 +108,8 @@ int aa_replace_current_profile(struct aa_profile *profile)
return -ENOMEM;
ctx = cred_ctx(new);
- if (unconfined(profile) || (ctx->profile->ns != profile->ns))
- /* if switching to unconfined or a different profile namespace
+ if (unconfined(label) || (labels_ns(ctx->label) != labels_ns(label)))
+ /* if switching to unconfined or a different label namespace
* clear out context state
*/
aa_clear_task_ctx_trans(ctx);
@@ -120,9 +120,9 @@ int aa_replace_current_profile(struct aa_profile *profile)
* keeping @profile valid, so make sure to get its reference before
* dropping the reference on ctx->profile
*/
- aa_get_profile(profile);
- aa_put_profile(ctx->profile);
- ctx->profile = profile;
+ aa_get_label(label);
+ aa_put_label(ctx->label);
+ ctx->label = label;
commit_creds(new);
return 0;
@@ -130,11 +130,11 @@ int aa_replace_current_profile(struct aa_profile *profile)
/**
* aa_set_current_onexec - set the tasks change_profile to happen onexec
- * @profile: system profile to set at exec (MAYBE NULL to clear value)
- *
+ * @label: system label to set at exec (MAYBE NULL to clear value)
+ * @stack: whether stacking should be done
* Returns: 0 or error on failure
*/
-int aa_set_current_onexec(struct aa_profile *profile)
+int aa_set_current_onexec(struct aa_label *label, bool stack)
{
struct aa_task_ctx *ctx;
struct cred *new = prepare_creds();
@@ -142,9 +142,10 @@ int aa_set_current_onexec(struct aa_profile *profile)
return -ENOMEM;
ctx = cred_ctx(new);
- aa_get_profile(profile);
- aa_put_profile(ctx->onexec);
- ctx->onexec = profile;
+ aa_get_label(label);
+ aa_clear_task_ctx_trans(ctx);
+ ctx->onexec = label;
+ ctx->token = stack;
commit_creds(new);
return 0;
@@ -152,7 +153,7 @@ int aa_set_current_onexec(struct aa_profile *profile)
/**
* aa_set_current_hat - set the current tasks hat
- * @profile: profile to set as the current hat (NOT NULL)
+ * @label: label to set as the current hat (NOT NULL)
* @token: token value that must be specified to change from the hat
*
* Do switch of tasks hat. If the task is currently in a hat
@@ -160,29 +161,29 @@ int aa_set_current_onexec(struct aa_profile *profile)
*
* Returns: 0 or error on failure
*/
-int aa_set_current_hat(struct aa_profile *profile, u64 token)
+int aa_set_current_hat(struct aa_label *label, u64 token)
{
struct aa_task_ctx *ctx;
struct cred *new = prepare_creds();
if (!new)
return -ENOMEM;
- AA_BUG(!profile);
+ AA_BUG(!label);
ctx = cred_ctx(new);
if (!ctx->previous) {
/* transfer refcount */
- ctx->previous = ctx->profile;
+ ctx->previous = ctx->label;
ctx->token = token;
} else if (ctx->token == token) {
- aa_put_profile(ctx->profile);
+ aa_put_label(ctx->label);
} else {
/* previous_profile && ctx->token != token */
abort_creds(new);
return -EACCES;
}
- ctx->profile = aa_get_newest_profile(profile);
+ ctx->label = aa_get_newest_label(label);
/* clear exec on switching context */
- aa_put_profile(ctx->onexec);
+ aa_put_label(ctx->onexec);
ctx->onexec = NULL;
commit_creds(new);
@@ -190,15 +191,15 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token)
}
/**
- * aa_restore_previous_profile - exit from hat context restoring the profile
+ * aa_restore_previous_label - exit from hat context restoring previous label
* @token: the token that must be matched to exit hat context
*
- * Attempt to return out of a hat to the previous profile. The token
+ * Attempt to return out of a hat to the previous label. The token
* must match the stored token value.
*
* Returns: 0 or error of failure
*/
-int aa_restore_previous_profile(u64 token)
+int aa_restore_previous_label(u64 token)
{
struct aa_task_ctx *ctx;
struct cred *new = prepare_creds();
@@ -210,15 +211,15 @@ int aa_restore_previous_profile(u64 token)
abort_creds(new);
return -EACCES;
}
- /* ignore restores when there is no saved profile */
+ /* ignore restores when there is no saved label */
if (!ctx->previous) {
abort_creds(new);
return 0;
}
- aa_put_profile(ctx->profile);
- ctx->profile = aa_get_newest_profile(ctx->previous);
- AA_BUG(!ctx->profile);
+ aa_put_label(ctx->label);
+ ctx->label = aa_get_newest_label(ctx->previous);
+ AA_BUG(!ctx->label);
/* clear exec && prev information when restoring to previous context */
aa_clear_task_ctx_trans(ctx);
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 2ec4ae029215..8d6797c849fe 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -61,24 +61,25 @@ void aa_free_domain_entries(struct aa_domain *domain)
static int may_change_ptraced_domain(struct aa_profile *to_profile)
{
struct task_struct *tracer;
- struct aa_profile *tracerp = NULL;
+ struct aa_label *tracerl = NULL;
int error = 0;
rcu_read_lock();
tracer = ptrace_parent(current);
if (tracer)
/* released below */
- tracerp = aa_get_task_profile(tracer);
+ tracerl = aa_get_task_label(tracer);
/* not ptraced */
- if (!tracer || unconfined(tracerp))
+ if (!tracer || unconfined(tracerl))
goto out;
- error = aa_may_ptrace(tracerp, to_profile, PTRACE_MODE_ATTACH);
+ error = aa_may_ptrace(labels_profile(tracerl), to_profile,
+ PTRACE_MODE_ATTACH);
out:
rcu_read_unlock();
- aa_put_profile(tracerp);
+ aa_put_label(tracerl);
return error;
}
@@ -102,7 +103,7 @@ static struct aa_perms change_profile_perms(struct aa_profile *profile,
struct path_cond cond = { };
unsigned int state;
- if (unconfined(profile)) {
+ if (profile_unconfined(profile)) {
perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
perms.audit = perms.quiet = perms.kill = 0;
return perms;
@@ -144,7 +145,7 @@ static struct aa_profile *__attach_match(const char *name,
struct aa_profile *profile, *candidate = NULL;
list_for_each_entry_rcu(profile, head, base.list) {
- if (profile->flags & PFLAG_NULL)
+ if (profile->label.flags & FLAG_NULL)
continue;
if (profile->xmatch && profile->xmatch_len > len) {
unsigned int state = aa_dfa_match(profile->xmatch,
@@ -338,6 +339,7 @@ static struct aa_profile *x_to_profile(struct aa_profile *profile,
int apparmor_bprm_set_creds(struct linux_binprm *bprm)
{
struct aa_task_ctx *ctx;
+ struct aa_label *label;
struct aa_profile *profile, *new_profile = NULL;
struct aa_ns *ns;
char *buffer = NULL;
@@ -356,7 +358,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
ctx = cred_ctx(bprm->cred);
AA_BUG(!ctx);
- profile = aa_get_newest_profile(ctx->profile);
+ label = aa_get_newest_label(ctx->label);
+ profile = labels_profile(label);
/* buffer freed below, name is pointer into buffer */
get_buffers(buffer);
@@ -370,8 +373,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
&name, &info, profile->disconnected);
if (error) {
- if (unconfined(profile) ||
- (profile->flags & PFLAG_IX_ON_NAME_ERROR))
+ if (profile_unconfined(profile) ||
+ (profile->label.flags & FLAG_IX_ON_NAME_ERROR))
error = 0;
name = bprm->filename;
goto audit;
@@ -380,11 +383,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
/* Test for onexec first as onexec directives override other
* x transitions.
*/
- if (unconfined(profile)) {
+ if (profile_unconfined(profile)) {
/* unconfined task */
if (ctx->onexec)
/* change_profile on exec already been granted */
- new_profile = aa_get_profile(ctx->onexec);
+ new_profile = labels_profile(aa_get_label(ctx->onexec));
else
new_profile = find_attach(ns, &ns->base.profiles, name);
if (!new_profile)
@@ -402,7 +405,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
if (ctx->onexec) {
struct aa_perms cp;
info = "change_profile onexec";
- new_profile = aa_get_newest_profile(ctx->onexec);
+ new_profile = labels_profile(aa_get_newest_label(ctx->onexec));
if (!(perms.allow & AA_MAY_ONEXEC))
goto audit;
@@ -411,9 +414,9 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
* exec\0change_profile
*/
state = aa_dfa_null_transition(profile->file.dfa, state);
- cp = change_profile_perms(profile, ctx->onexec->ns,
- ctx->onexec->base.name,
- AA_MAY_ONEXEC, state);
+ cp = change_profile_perms(profile, labels_ns(ctx->onexec),
+ labels_profile(ctx->onexec)->base.name,
+ AA_MAY_ONEXEC, state);
if (!(cp.allow & AA_MAY_ONEXEC))
goto audit;
@@ -501,9 +504,9 @@ apply:
bprm->per_clear |= PER_CLEAR_ON_SETID;
x_clear:
- aa_put_profile(ctx->profile);
+ aa_put_label(ctx->label);
/* transfer new profile reference will be released when ctx is freed */
- ctx->profile = new_profile;
+ ctx->label = &new_profile->label;
new_profile = NULL;
/* clear out all temporary/transitional state from the context */
@@ -516,7 +519,7 @@ audit:
cleanup:
aa_put_profile(new_profile);
- aa_put_profile(profile);
+ aa_put_label(label);
put_buffers(buffer);
return error;
@@ -576,7 +579,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
{
const struct cred *cred;
struct aa_task_ctx *ctx;
- struct aa_profile *profile, *previous_profile, *hat = NULL;
+ struct aa_label *label, *previous_label;
+ struct aa_profile *profile, *hat = NULL;
char *name = NULL;
int i;
struct aa_perms perms = {};
@@ -594,10 +598,11 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
/* released below */
cred = get_current_cred();
ctx = cred_ctx(cred);
- profile = aa_get_newest_cred_profile(cred);
- previous_profile = aa_get_newest_profile(ctx->previous);
+ label = aa_get_newest_cred_label(cred);
+ previous_label = aa_get_newest_label(ctx->previous);
+ profile = labels_profile(label);
- if (unconfined(profile)) {
+ if (unconfined(label)) {
info = "unconfined";
error = -EPERM;
goto audit;
@@ -664,7 +669,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
}
if (!(flags & AA_CHANGE_TEST)) {
- error = aa_set_current_hat(hat, token);
+ error = aa_set_current_hat(&hat->label, token);
if (error == -EACCES)
/* kill task in case of brute force attacks */
perms.kill = AA_MAY_CHANGEHAT;
@@ -672,12 +677,12 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
/* reset error for learning of new hats */
error = -ENOENT;
}
- } else if (previous_profile) {
+ } else if (previous_label) {
/* Return to saved profile. Kill task if restore fails
* to avoid brute force attacks
*/
- target = previous_profile->base.hname;
- error = aa_restore_previous_profile(token);
+ target = previous_label->hname;
+ error = aa_restore_previous_label(token);
perms.kill = AA_MAY_CHANGEHAT;
} else
/* ignore restores when there is no saved profile */
@@ -692,8 +697,8 @@ audit:
out:
aa_put_profile(hat);
kfree(name);
- aa_put_profile(profile);
- aa_put_profile(previous_profile);
+ aa_put_label(label);
+ aa_put_label(previous_label);
put_cred(cred);
return error;
@@ -716,6 +721,7 @@ out:
int aa_change_profile(const char *fqname, int flags)
{
const struct cred *cred;
+ struct aa_label *label;
struct aa_profile *profile, *target = NULL;
struct aa_perms perms = {};
const char *info = NULL, *op;
@@ -736,7 +742,8 @@ int aa_change_profile(const char *fqname, int flags)
}
cred = get_current_cred();
- profile = aa_get_newest_cred_profile(cred);
+ label = aa_get_newest_cred_label(cred);
+ profile = labels_profile(label);
/*
* Fail explicitly requested domain transitions if no_new_privs
@@ -745,12 +752,12 @@ int aa_change_profile(const char *fqname, int flags)
* no_new_privs is set because this aways results in a reduction
* of permissions.
*/
- if (task_no_new_privs(current) && !unconfined(profile)) {
+ if (task_no_new_privs(current) && !profile_unconfined(profile)) {
put_cred(cred);
return -EPERM;
}
- target = aa_fqlookupn_profile(profile, fqname, strlen(fqname));
+ target = aa_fqlookupn_profile(label, fqname, strlen(fqname));
if (!target) {
info = "profile not found";
error = -ENOENT;
@@ -785,9 +792,9 @@ int aa_change_profile(const char *fqname, int flags)
goto audit;
if (flags & AA_CHANGE_ONEXEC)
- error = aa_set_current_onexec(target);
+ error = aa_set_current_onexec(&target->label, 0);
else
- error = aa_replace_current_profile(target);
+ error = aa_replace_current_label(&target->label);
audit:
if (!(flags & AA_CHANGE_TEST))
@@ -795,7 +802,7 @@ audit:
fqname, GLOBAL_ROOT_UID, info, error);
aa_put_profile(target);
- aa_put_profile(profile);
+ aa_put_label(label);
put_cred(cred);
return error;
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index bf508791cc1f..5289c8db832b 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -451,7 +451,7 @@ int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file,
request, &cond);
}
-static void revalidate_tty(struct aa_profile *profile)
+static void revalidate_tty(struct aa_label *label)
{
struct tty_struct *tty;
int drop_tty = 0;
@@ -469,7 +469,7 @@ static void revalidate_tty(struct aa_profile *profile)
struct tty_file_private, list);
file = file_priv->file;
- if (aa_file_perm(OP_INHERIT, profile, file,
+ if (aa_file_perm(OP_INHERIT, labels_profile(label), file,
MAY_READ | MAY_WRITE))
drop_tty = 1;
}
@@ -482,9 +482,9 @@ static void revalidate_tty(struct aa_profile *profile)
static int match_file(const void *p, struct file *file, unsigned int fd)
{
- struct aa_profile *profile = (struct aa_profile *)p;
+ struct aa_label *label = (struct aa_label *)p;
- if (aa_file_perm(OP_INHERIT, profile, file,
+ if (aa_file_perm(OP_INHERIT, labels_profile(label), file,
aa_