diff options
author | John Johansen <john.johansen@canonical.com> | 2017-06-09 08:14:28 -0700 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2017-06-10 17:11:38 -0700 |
commit | 637f688dc3dc304a89f441d76f49a0e35bc49c08 (patch) | |
tree | 78fee8a7aa212140c4c6b6a9b722bbba61802cab | |
parent | f1bd904175e8190ce14aedee37e207ab51fe3b30 (diff) | |
download | linux-637f688dc3dc304a89f441d76f49a0e35bc49c08.tar.gz linux-637f688dc3dc304a89f441d76f49a0e35bc49c08.tar.bz2 linux-637f688dc3dc304a89f441d76f49a0e35bc49c08.zip |
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>
-rw-r--r-- | security/apparmor/Makefile | 2 | ||||
-rw-r--r-- | security/apparmor/apparmorfs.c | 128 | ||||
-rw-r--r-- | security/apparmor/audit.c | 27 | ||||
-rw-r--r-- | security/apparmor/context.c | 87 | ||||
-rw-r--r-- | security/apparmor/domain.c | 77 | ||||
-rw-r--r-- | security/apparmor/file.c | 18 | ||||
-rw-r--r-- | security/apparmor/include/apparmor.h | 5 | ||||
-rw-r--r-- | security/apparmor/include/audit.h | 9 | ||||
-rw-r--r-- | security/apparmor/include/context.h | 158 | ||||
-rw-r--r-- | security/apparmor/include/perms.h | 12 | ||||
-rw-r--r-- | security/apparmor/include/policy.h | 110 | ||||
-rw-r--r-- | security/apparmor/include/policy_ns.h | 4 | ||||
-rw-r--r-- | security/apparmor/ipc.c | 29 | ||||
-rw-r--r-- | security/apparmor/lib.c | 163 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 134 | ||||
-rw-r--r-- | security/apparmor/policy.c | 208 | ||||
-rw-r--r-- | security/apparmor/policy_ns.c | 20 | ||||
-rw-r--r-- | security/apparmor/policy_unpack.c | 12 | ||||
-rw-r--r-- | security/apparmor/procattr.c | 4 | ||||
-rw-r--r-- | security/apparmor/resource.c | 8 |
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, |