diff options
author | John Johansen <john.johansen@canonical.com> | 2017-06-09 18:14:28 +0300 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2017-06-11 03:11:38 +0300 |
commit | 637f688dc3dc304a89f441d76f49a0e35bc49c08 (patch) | |
tree | 78fee8a7aa212140c4c6b6a9b722bbba61802cab /security/apparmor/lsm.c | |
parent | f1bd904175e8190ce14aedee37e207ab51fe3b30 (diff) | |
download | linux-637f688dc3dc304a89f441d76f49a0e35bc49c08.tar.xz |
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/lsm.c')
-rw-r--r-- | security/apparmor/lsm.c | 134 |
1 files changed, 72 insertions, 62 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 7ba43c18687a..3ba08530c92e 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -34,6 +34,7 @@ #include "include/file.h" #include "include/ipc.h" #include "include/path.h" +#include "include/label.h" #include "include/policy.h" #include "include/policy_ns.h" #include "include/procattr.h" @@ -49,7 +50,7 @@ DEFINE_PER_CPU(struct aa_buffers, aa_buffers); */ /* - * free the associated aa_task_ctx and put its profiles + * free the associated aa_task_ctx and put its labels */ static void apparmor_cred_free(struct cred *cred) { @@ -115,23 +116,24 @@ static int apparmor_ptrace_traceme(struct task_struct *parent) static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { + struct aa_label *label; struct aa_profile *profile; const struct cred *cred; rcu_read_lock(); cred = __task_cred(target); - profile = aa_get_newest_cred_profile(cred); - + label = aa_get_newest_cred_label(cred); + profile = labels_profile(label); /* * cap_capget is stacked ahead of this and will * initialize effective and permitted. */ - if (!unconfined(profile) && !COMPLAIN_MODE(profile)) { + if (!profile_unconfined(profile) && !COMPLAIN_MODE(profile)) { *effective = cap_intersect(*effective, profile->caps.allow); *permitted = cap_intersect(*permitted, profile->caps.allow); } rcu_read_unlock(); - aa_put_profile(profile); + aa_put_label(label); return 0; } @@ -139,13 +141,13 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit) { - struct aa_profile *profile; + struct aa_label *label; int error = 0; - profile = aa_get_newest_cred_profile(cred); - if (!unconfined(profile)) - error = aa_capable(profile, cap, audit); - aa_put_profile(profile); + label = aa_get_newest_cred_label(cred); + if (!unconfined(label)) + error = aa_capable(labels_profile(label), cap, audit); + aa_put_label(label); return error; } @@ -162,13 +164,14 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, static int common_perm(const char *op, const struct path *path, u32 mask, struct path_cond *cond) { - struct aa_profile *profile; + struct aa_label *label; int error = 0; - profile = __begin_current_profile_crit_section(); - if (!unconfined(profile)) - error = aa_path_perm(op, profile, path, 0, mask, cond); - __end_current_profile_crit_section(profile); + label = __begin_current_label_crit_section(); + if (!unconfined(label)) + error = aa_path_perm(op, labels_profile(label), path, 0, mask, + cond); + __end_current_label_crit_section(label); return error; } @@ -295,16 +298,17 @@ static int apparmor_path_symlink(const struct path *dir, struct dentry *dentry, static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { - struct aa_profile *profile; + struct aa_label *label; int error = 0; if (!path_mediated_fs(old_dentry)) return 0; - profile = begin_current_profile_crit_section(); - if (!unconfined(profile)) - error = aa_path_link(profile, old_dentry, new_dir, new_dentry); - end_current_profile_crit_section(profile); + label = begin_current_label_crit_section(); + if (!unconfined(label)) + error = aa_path_link(labels_profile(label), old_dentry, new_dir, + new_dentry); + end_current_label_crit_section(label); return error; } @@ -312,14 +316,14 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { - struct aa_profile *profile; + struct aa_label *label; int error = 0; if (!path_mediated_fs(old_dentry)) return 0; - profile = begin_current_profile_crit_section(); - if (!unconfined(profile)) { + label = begin_current_label_crit_section(); + if (!unconfined(label)) { struct path old_path = { .mnt = old_dir->mnt, .dentry = old_dentry }; struct path new_path = { .mnt = new_dir->mnt, @@ -328,17 +332,20 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d d_backing_inode(old_dentry)->i_mode }; - error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0, + error = aa_path_perm(OP_RENAME_SRC, labels_profile(label), + &old_path, 0, MAY_READ | AA_MAY_GETATTR | MAY_WRITE | AA_MAY_SETATTR | AA_MAY_DELETE, &cond); if (!error) - error = aa_path_perm(OP_RENAME_DEST, profile, &new_path, + error = aa_path_perm(OP_RENAME_DEST, + labels_profile(label), + &new_path, 0, MAY_WRITE | AA_MAY_SETATTR | AA_MAY_CREATE, &cond); } - end_current_profile_crit_section(profile); + end_current_label_crit_section(label); return error; } @@ -360,8 +367,8 @@ static int apparmor_inode_getattr(const struct path *path) static int apparmor_file_open(struct file *file, const struct cred *cred) { - struct aa_file_ctx *fctx = file->f_security; - struct aa_profile *profile; + struct aa_file_ctx *fctx = file_ctx(file); + struct aa_label *label; int error = 0; if (!path_mediated_fs(file->f_path.dentry)) @@ -377,17 +384,18 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) return 0; } - profile = aa_get_newest_cred_profile(cred); - if (!unconfined(profile)) { + label = aa_get_newest_cred_label(cred); + if (!unconfined(label)) { struct inode *inode = file_inode(file); struct path_cond cond = { inode->i_uid, inode->i_mode }; - error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0, + error = aa_path_perm(OP_OPEN, labels_profile(label), + &file->f_path, 0, aa_map_file_to_perms(file), &cond); /* todo cache full allowed permissions set and state */ fctx->allow = aa_map_file_to_perms(file); } - aa_put_profile(profile); + aa_put_label(label); return error; } @@ -397,11 +405,11 @@ static int apparmor_file_alloc_security(struct file *file) int error = 0; /* freed by apparmor_file_free_security */ - struct aa_profile *profile = begin_current_profile_crit_section(); + struct aa_label *label = begin_current_label_crit_section(); file->f_security = aa_alloc_file_ctx(GFP_KERNEL); if (!file_ctx(file)) error = -ENOMEM; - end_current_profile_crit_section(profile); + end_current_label_crit_section(label); return error; } @@ -414,21 +422,21 @@ static void apparmor_file_free_security(struct file *file) static int common_file_perm(const char *op, struct file *file, u32 mask) { struct aa_file_ctx *fctx = file->f_security; - struct aa_profile *profile, *fprofile; + struct aa_label *label, *flabel; int error = 0; /* don't reaudit files closed during inheritance */ if (file->f_path.dentry == aa_null.dentry) return -EACCES; - fprofile = aa_cred_raw_profile(file->f_cred); - AA_BUG(!fprofile); + flabel = aa_cred_raw_label(file->f_cred); + AA_BUG(!flabel); if (!file->f_path.mnt || !path_mediated_fs(file->f_path.dentry)) return 0; - profile = __begin_current_profile_crit_section(); + label = __begin_current_label_crit_section(); /* revalidate access, if task is unconfined, or the cached cred * doesn't match or if the request is for more permissions than @@ -437,10 +445,10 @@ static int common_file_perm(const char *op, struct file *file, u32 mask) * Note: the test for !unconfined(fprofile) is to handle file * delegation from unconfined tasks */ - if (!unconfined(profile) && !unconfined(fprofile) && - ((fprofile != profile) || (mask & ~fctx->allow))) - error = aa_file_perm(op, profile, file, mask); - __end_current_profile_crit_section(profile); + if (!unconfined(label) && !unconfined(flabel) && + ((flabel != label) || (mask & ~fctx->allow))) + error = aa_file_perm(op, labels_profile(label), file, mask); + __end_current_label_crit_section(label); return error; } @@ -465,7 +473,7 @@ static int common_mmap(const char *op, struct file *file, unsigned long prot, { int mask = 0; - if (!file || !file->f_security) + if (!file || !file_ctx(file)) return 0; if (prot & PROT_READ) @@ -502,21 +510,21 @@ static int apparmor_getprocattr(struct task_struct *task, char *name, /* released below */ const struct cred *cred = get_task_cred(task); struct aa_task_ctx *ctx = cred_ctx(cred); - struct aa_profile *profile = NULL; + struct aa_label *label = NULL; if (strcmp(name, "current") == 0) - profile = aa_get_newest_profile(ctx->profile); + label = aa_get_newest_label(ctx->label); else if (strcmp(name, "prev") == 0 && ctx->previous) - profile = aa_get_newest_profile(ctx->previous); + label = aa_get_newest_label(ctx->previous); else if (strcmp(name, "exec") == 0 && ctx->onexec) - profile = aa_get_newest_profile(ctx->onexec); + label = aa_get_newest_label(ctx->onexec); else error = -EINVAL; - if (profile) - error = aa_getprocattr(profile, value); + if (label) + error = aa_getprocattr(labels_profile(label), value); - aa_put_profile(profile); + aa_put_label(label); put_cred(cred); return error; @@ -582,11 +590,11 @@ out: return error; fail: - aad(&sa)->profile = begin_current_profile_crit_section(); + aad(&sa)->label = begin_current_label_crit_section(); aad(&sa)->info = name; aad(&sa)->error = error = -EINVAL; aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); - end_current_profile_crit_section(aad(&sa)->profile); + end_current_label_crit_section(aad(&sa)->label); goto out; } @@ -596,20 +604,21 @@ fail: */ static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) { - struct aa_profile *profile = aa_current_raw_profile(); + struct aa_label *label = aa_current_raw_label(); struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); /* bail out if unconfined or not changing profile */ - if ((new_ctx->profile == profile) || - (unconfined(new_ctx->profile))) + if ((new_ctx->label->proxy == label->proxy) || + (unconfined(new_ctx->label))) return; aa_inherit_files(bprm->cred, current->files); current->pdeath_signal = 0; - /* reset soft limits and set hard limits for the new profile */ - __aa_transition_rlimits(profile, new_ctx->profile); + /* reset soft limits and set hard limits for the new label */ + __aa_transition_rlimits(labels_profile(label), + labels_profile(new_ctx->label)); } /** @@ -625,12 +634,13 @@ static void apparmor_bprm_committed_creds(struct linux_binprm *bprm) static int apparmor_task_setrlimit(struct task_struct *task, unsigned int resource, struct rlimit *new_rlim) { - struct aa_profile *profile = __begin_current_profile_crit_section(); + struct aa_label *label = __begin_current_label_crit_section(); int error = 0; - if (!unconfined(profile)) - error = aa_task_setrlimit(profile, task, resource, new_rlim); - __end_current_profile_crit_section(profile); + if (!unconfined(label)) + error = aa_task_setrlimit(labels_profile(label), task, + resource, new_rlim); + __end_current_label_crit_section(label); return error; } @@ -924,7 +934,7 @@ static int __init set_init_ctx(void) if (!ctx) return -ENOMEM; - ctx->profile = aa_get_profile(root_ns->unconfined); + ctx->label = aa_get_label(ns_unconfined(root_ns)); cred_ctx(cred) = ctx; return 0; |