summaryrefslogtreecommitdiff
path: root/security/apparmor/lsm.c
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-06-09 18:14:28 +0300
committerJohn Johansen <john.johansen@canonical.com>2017-06-11 03:11:38 +0300
commit637f688dc3dc304a89f441d76f49a0e35bc49c08 (patch)
tree78fee8a7aa212140c4c6b6a9b722bbba61802cab /security/apparmor/lsm.c
parentf1bd904175e8190ce14aedee37e207ab51fe3b30 (diff)
downloadlinux-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.c134
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;