aboutsummaryrefslogtreecommitdiff
path: root/security/apparmor/lsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/lsm.c')
-rw-r--r--security/apparmor/lsm.c161
1 files changed, 79 insertions, 82 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index b7106f192b7..99810009333 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -22,6 +22,7 @@
#include <linux/ctype.h>
#include <linux/sysctl.h>
#include <linux/audit.h>
+#include <linux/user_namespace.h>
#include <net/sock.h>
#include "include/apparmor.h"
@@ -47,8 +48,8 @@ int apparmor_initialized __initdata;
*/
static void apparmor_cred_free(struct cred *cred)
{
- aa_free_task_context(cred->security);
- cred->security = NULL;
+ aa_free_task_context(cred_cxt(cred));
+ cred_cxt(cred) = NULL;
}
/*
@@ -61,7 +62,7 @@ static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
if (!cxt)
return -ENOMEM;
- cred->security = cxt;
+ cred_cxt(cred) = cxt;
return 0;
}
@@ -76,8 +77,8 @@ static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
if (!cxt)
return -ENOMEM;
- aa_dup_task_context(cxt, old->security);
- new->security = cxt;
+ aa_dup_task_context(cxt, cred_cxt(old));
+ cred_cxt(new) = cxt;
return 0;
}
@@ -86,8 +87,8 @@ static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
*/
static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
{
- const struct aa_task_cxt *old_cxt = old->security;
- struct aa_task_cxt *new_cxt = new->security;
+ const struct aa_task_cxt *old_cxt = cred_cxt(old);
+ struct aa_task_cxt *new_cxt = cred_cxt(new);
aa_dup_task_context(new_cxt, old_cxt);
}
@@ -126,7 +127,7 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
*inheritable = cred->cap_inheritable;
*permitted = cred->cap_permitted;
- if (!unconfined(profile)) {
+ if (!unconfined(profile) && !COMPLAIN_MODE(profile)) {
*effective = cap_intersect(*effective, profile->caps.allow);
*permitted = cap_intersect(*permitted, profile->caps.allow);
}
@@ -135,16 +136,16 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
return 0;
}
-static int apparmor_capable(struct task_struct *task, const struct cred *cred,
+static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
int cap, int audit)
{
struct aa_profile *profile;
/* cap_capable returns 0 on success, else -EPERM */
- int error = cap_capable(task, cred, cap, audit);
+ int error = cap_capable(cred, ns, cap, audit);
if (!error) {
profile = aa_cred_profile(cred);
if (!unconfined(profile))
- error = aa_capable(task, profile, cap, audit);
+ error = aa_capable(profile, cap, audit);
}
return error;
}
@@ -261,7 +262,7 @@ static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
}
static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
- int mode)
+ umode_t mode)
{
return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE,
S_IFDIR);
@@ -273,7 +274,7 @@ static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
}
static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
- int mode, unsigned int dev)
+ umode_t mode, unsigned int dev)
{
return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode);
}
@@ -343,16 +344,15 @@ static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
return error;
}
-static int apparmor_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
- mode_t mode)
+static int apparmor_path_chmod(struct path *path, umode_t mode)
{
- if (!mediated_filesystem(dentry->d_inode))
+ if (!mediated_filesystem(path->dentry->d_inode))
return 0;
- return common_perm_mnt_dentry(OP_CHMOD, mnt, dentry, AA_MAY_CHMOD);
+ return common_perm_mnt_dentry(OP_CHMOD, path->mnt, path->dentry, AA_MAY_CHMOD);
}
-static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid)
+static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
struct path_cond cond = { path->dentry->d_inode->i_uid,
path->dentry->d_inode->i_mode
@@ -373,13 +373,13 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
AA_MAY_META_READ);
}
-static int apparmor_dentry_open(struct file *file, const struct cred *cred)
+static int apparmor_file_open(struct file *file, const struct cred *cred)
{
struct aa_file_cxt *fcxt = file->f_security;
struct aa_profile *profile;
int error = 0;
- if (!mediated_filesystem(file->f_path.dentry->d_inode))
+ if (!mediated_filesystem(file_inode(file)))
return 0;
/* If in exec, permission is handled by bprm hooks.
@@ -394,7 +394,7 @@ static int apparmor_dentry_open(struct file *file, const struct cred *cred)
profile = aa_cred_profile(cred);
if (!unconfined(profile)) {
- struct inode *inode = file->f_path.dentry->d_inode;
+ 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,
@@ -432,7 +432,7 @@ static int common_file_perm(int op, struct file *file, u32 mask)
BUG_ON(!fprofile);
if (!file->f_path.mnt ||
- !mediated_filesystem(file->f_path.dentry->d_inode))
+ !mediated_filesystem(file_inode(file)))
return 0;
profile = __aa_current_profile();
@@ -469,7 +469,6 @@ static int apparmor_file_lock(struct file *file, unsigned int cmd)
static int common_mmap(int op, struct file *file, unsigned long prot,
unsigned long flags)
{
- struct dentry *dentry;
int mask = 0;
if (!file || !file->f_security)
@@ -486,21 +485,12 @@ static int common_mmap(int op, struct file *file, unsigned long prot,
if (prot & PROT_EXEC)
mask |= AA_EXEC_MMAP;
- dentry = file->f_path.dentry;
return common_file_perm(op, file, mask);
}
-static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
- unsigned long prot, unsigned long flags,
- unsigned long addr, unsigned long addr_only)
+static int apparmor_mmap_file(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags)
{
- int rc = 0;
-
- /* do DAC check */
- rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
- if (rc || addr_only)
- return rc;
-
return common_mmap(OP_FMMAP, file, prot, flags);
}
@@ -515,24 +505,24 @@ static int apparmor_getprocattr(struct task_struct *task, char *name,
char **value)
{
int error = -ENOENT;
- struct aa_profile *profile;
/* released below */
const struct cred *cred = get_task_cred(task);
- struct aa_task_cxt *cxt = cred->security;
- profile = aa_cred_profile(cred);
+ struct aa_task_cxt *cxt = cred_cxt(cred);
+ struct aa_profile *profile = NULL;
if (strcmp(name, "current") == 0)
- error = aa_getprocattr(aa_newest_version(cxt->profile),
- value);
+ profile = aa_get_newest_profile(cxt->profile);
else if (strcmp(name, "prev") == 0 && cxt->previous)
- error = aa_getprocattr(aa_newest_version(cxt->previous),
- value);
+ profile = aa_get_newest_profile(cxt->previous);
else if (strcmp(name, "exec") == 0 && cxt->onexec)
- error = aa_getprocattr(aa_newest_version(cxt->onexec),
- value);
+ profile = aa_get_newest_profile(cxt->onexec);
else
error = -EINVAL;
+ if (profile)
+ error = aa_getprocattr(profile, value);
+
+ aa_put_profile(profile);
put_cred(cred);
return error;
@@ -541,6 +531,8 @@ static int apparmor_getprocattr(struct task_struct *task, char *name,
static int apparmor_setprocattr(struct task_struct *task, char *name,
void *value, size_t size)
{
+ struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
char *command, *args = value;
size_t arg_size;
int error;
@@ -584,33 +576,37 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
} else if (strcmp(command, "permprofile") == 0) {
error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
AA_DO_TEST);
- } else if (strcmp(command, "permipc") == 0) {
- error = aa_setprocattr_permipc(args);
- } else {
- struct common_audit_data sa;
- COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = OP_SETPROCATTR;
- sa.aad.info = name;
- sa.aad.error = -EINVAL;
- return aa_audit(AUDIT_APPARMOR_DENIED, NULL, GFP_KERNEL,
- &sa, NULL);
- }
+ } else
+ goto fail;
} else if (strcmp(name, "exec") == 0) {
- error = aa_setprocattr_changeprofile(args, AA_ONEXEC,
- !AA_DO_TEST);
- } else {
+ if (strcmp(command, "exec") == 0)
+ error = aa_setprocattr_changeprofile(args, AA_ONEXEC,
+ !AA_DO_TEST);
+ else
+ goto fail;
+ } else
/* only support the "current" and "exec" process attributes */
return -EINVAL;
- }
+
if (!error)
error = size;
return error;
+
+fail:
+ sa.type = LSM_AUDIT_DATA_NONE;
+ sa.aad = &aad;
+ aad.profile = aa_current_profile();
+ aad.op = OP_SETPROCATTR;
+ aad.info = name;
+ aad.error = -EINVAL;
+ aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL);
+ return -EINVAL;
}
static int apparmor_task_setrlimit(struct task_struct *task,
unsigned int resource, struct rlimit *new_rlim)
{
- struct aa_profile *profile = aa_current_profile();
+ struct aa_profile *profile = __aa_current_profile();
int error = 0;
if (!unconfined(profile))
@@ -637,13 +633,14 @@ static struct security_operations apparmor_ops = {
.path_chmod = apparmor_path_chmod,
.path_chown = apparmor_path_chown,
.path_truncate = apparmor_path_truncate,
- .dentry_open = apparmor_dentry_open,
.inode_getattr = apparmor_inode_getattr,
+ .file_open = apparmor_file_open,
.file_permission = apparmor_file_permission,
.file_alloc_security = apparmor_file_alloc_security,
.file_free_security = apparmor_file_free_security,
- .file_mmap = apparmor_file_mmap,
+ .mmap_file = apparmor_mmap_file,
+ .mmap_addr = cap_mmap_addr,
.file_mprotect = apparmor_file_mprotect,
.file_lock = apparmor_file_lock,
@@ -669,15 +666,16 @@ static struct security_operations apparmor_ops = {
static int param_set_aabool(const char *val, const struct kernel_param *kp);
static int param_get_aabool(char *buffer, const struct kernel_param *kp);
-#define param_check_aabool(name, p) __param_check(name, p, int)
+#define param_check_aabool param_check_bool
static struct kernel_param_ops param_ops_aabool = {
+ .flags = KERNEL_PARAM_FL_NOARG,
.set = param_set_aabool,
.get = param_get_aabool
};
static int param_set_aauint(const char *val, const struct kernel_param *kp);
static int param_get_aauint(char *buffer, const struct kernel_param *kp);
-#define param_check_aauint(name, p) __param_check(name, p, int)
+#define param_check_aauint param_check_uint
static struct kernel_param_ops param_ops_aauint = {
.set = param_set_aauint,
.get = param_get_aauint
@@ -685,19 +683,18 @@ static struct kernel_param_ops param_ops_aauint = {
static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp);
static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp);
-#define param_check_aalockpolicy(name, p) __param_check(name, p, int)
+#define param_check_aalockpolicy param_check_bool
static struct kernel_param_ops param_ops_aalockpolicy = {
+ .flags = KERNEL_PARAM_FL_NOARG,
.set = param_set_aalockpolicy,
.get = param_get_aalockpolicy
};
static int param_set_audit(const char *val, struct kernel_param *kp);
static int param_get_audit(char *buffer, struct kernel_param *kp);
-#define param_check_audit(name, p) __param_check(name, p, int)
static int param_set_mode(const char *val, struct kernel_param *kp);
static int param_get_mode(char *buffer, struct kernel_param *kp);
-#define param_check_mode(name, p) __param_check(name, p, int)
/* Flag values, also controllable via /sys/module/apparmor/parameters
* We define special types as we want to do additional mediation.
@@ -709,7 +706,7 @@ module_param_call(mode, param_set_mode, param_get_mode,
&aa_g_profile_mode, S_IRUSR | S_IWUSR);
/* Debug mode */
-int aa_g_debug;
+bool aa_g_debug;
module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR);
/* Audit mode */
@@ -720,7 +717,7 @@ module_param_call(audit, param_set_audit, param_get_audit,
/* Determines if audit header is included in audited messages. This
* provides more context if the audit daemon is not running
*/
-int aa_g_audit_header = 1;
+bool aa_g_audit_header = 1;
module_param_named(audit_header, aa_g_audit_header, aabool,
S_IRUSR | S_IWUSR);
@@ -728,12 +725,12 @@ module_param_named(audit_header, aa_g_audit_header, aabool,
* TODO: add in at boot loading of policy, which is the only way to
* load policy, if lock_policy is set
*/
-int aa_g_lock_policy;
+bool aa_g_lock_policy;
module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy,
S_IRUSR | S_IWUSR);
/* Syscall logging mode */
-int aa_g_logsyscall;
+bool aa_g_logsyscall;
module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR);
/* Maximum pathname length before accesses will start getting rejected */
@@ -743,18 +740,18 @@ module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR);
/* Determines how paranoid loading of policy is and how much verification
* on the loaded policy is done.
*/
-int aa_g_paranoid_load = 1;
+bool aa_g_paranoid_load = 1;
module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
S_IRUSR | S_IWUSR);
/* Boot time disable flag */
-static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
-module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
+static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+module_param_named(enabled, apparmor_enabled, bool, S_IRUGO);
static int __init apparmor_enabled_setup(char *str)
{
unsigned long enabled;
- int error = strict_strtoul(str, 0, &enabled);
+ int error = kstrtoul(str, 0, &enabled);
if (!error)
apparmor_enabled = enabled ? 1 : 0;
return 1;
@@ -848,7 +845,7 @@ static int param_get_mode(char *buffer, struct kernel_param *kp)
if (!apparmor_enabled)
return -EINVAL;
- return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]);
+ return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]);
}
static int param_set_mode(const char *val, struct kernel_param *kp)
@@ -863,8 +860,8 @@ static int param_set_mode(const char *val, struct kernel_param *kp)
if (!val)
return -EINVAL;
- for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
- if (strcmp(val, profile_mode_names[i]) == 0) {
+ for (i = 0; i < APPARMOR_MODE_NAMES_MAX_INDEX; i++) {
+ if (strcmp(val, aa_profile_mode_names[i]) == 0) {
aa_g_profile_mode = i;
return 0;
}
@@ -892,7 +889,7 @@ static int __init set_init_cxt(void)
return -ENOMEM;
cxt->profile = aa_get_profile(root_ns->unconfined);
- cred->security = cxt;
+ cred_cxt(cred) = cxt;
return 0;
}
@@ -921,8 +918,11 @@ static int __init apparmor_init(void)
error = register_security(&apparmor_ops);
if (error) {
+ struct cred *cred = (struct cred *)current->real_cred;
+ aa_free_task_context(cred_cxt(cred));
+ cred_cxt(cred) = NULL;
AA_ERROR("Unable to register AppArmor\n");
- goto set_init_cxt_out;
+ goto register_security_out;
}
/* Report that AppArmor successfully initialized */
@@ -936,9 +936,6 @@ static int __init apparmor_init(void)
return error;
-set_init_cxt_out:
- aa_free_task_context(current->real_cred->security);
-
register_security_out:
aa_free_root_ns();