summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-10 16:52:55 +0100
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-10 17:14:49 +0100
commit9edd576d89a5b6d3e136d7dcab654d887c0d25b7 (patch)
treed19670de2256f8187321de3a41fa4a10d3c8e402 /security
parente21af88d39796c907c38648c824be3d646ffbe35 (diff)
parent28a4d5675857f6386930a324317281cb8ed1e5d0 (diff)
Merge remote-tracking branch 'airlied/drm-fixes' into drm-intel-next-queued
Back-merge from drm-fixes into drm-intel-next to sort out two things: - interlaced support: -fixes contains a bugfix to correctly clear interlaced configuration bits in case the bios sets up an interlaced mode and we want to set up the progressive mode (current kernels don't support interlaced). The actual feature work to support interlaced depends upon (and conflicts with) this bugfix. - forcewake voodoo to workaround missed IRQ issues: -fixes only enabled this for ivybridge, but some recent bug reports indicate that we need this on Sandybridge, too. But in a slightly different flavour and with other fixes and reworks on top. Additionally there are some forcewake cleanup patches heading to -next that would conflict with currrent -fixes. Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/apparmorfs.c2
-rw-r--r--security/apparmor/audit.c2
-rw-r--r--security/apparmor/include/apparmor.h10
-rw-r--r--security/apparmor/lsm.c37
-rw-r--r--security/apparmor/path.c1
-rw-r--r--security/capability.c14
-rw-r--r--security/commoncap.c24
-rw-r--r--security/device_cgroup.c7
-rw-r--r--security/inode.c193
-rw-r--r--security/integrity/Kconfig14
-rw-r--r--security/integrity/Makefile1
-rw-r--r--security/integrity/digsig.c48
-rw-r--r--security/integrity/evm/evm.h12
-rw-r--r--security/integrity/evm/evm_crypto.c81
-rw-r--r--security/integrity/evm/evm_main.c94
-rw-r--r--security/integrity/ima/ima_api.c4
-rw-r--r--security/integrity/ima/ima_audit.c8
-rw-r--r--security/integrity/ima/ima_policy.c3
-rw-r--r--security/integrity/ima/ima_queue.c17
-rw-r--r--security/integrity/integrity.h21
-rw-r--r--security/keys/encrypted-keys/encrypted.c6
-rw-r--r--security/keys/encrypted-keys/masterkey_trusted.c4
-rw-r--r--security/keys/gc.c4
-rw-r--r--security/keys/internal.h1
-rw-r--r--security/keys/key.c4
-rw-r--r--security/keys/keyring.c22
-rw-r--r--security/keys/trusted.c4
-rw-r--r--security/keys/user_defined.c43
-rw-r--r--security/lsm_audit.c34
-rw-r--r--security/security.c54
-rw-r--r--security/selinux/hooks.c65
-rw-r--r--security/selinux/netnode.c2
-rw-r--r--security/selinux/netport.c4
-rw-r--r--security/selinux/selinuxfs.c14
-rw-r--r--security/selinux/ss/conditional.c2
-rw-r--r--security/smack/smack_lsm.c4
-rw-r--r--security/tomoyo/.gitignore2
-rw-r--r--security/tomoyo/audit.c4
-rw-r--r--security/tomoyo/common.h4
-rw-r--r--security/tomoyo/realpath.c9
-rw-r--r--security/tomoyo/securityfs_if.c2
-rw-r--r--security/tomoyo/tomoyo.c15
-rw-r--r--security/tomoyo/util.c6
43 files changed, 506 insertions, 396 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 69ddb47787b..e39df6d4377 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -165,7 +165,7 @@ static void __init aafs_remove(const char *name)
*
* Used aafs_remove to remove entries created with this fn.
*/
-static int __init aafs_create(const char *name, int mask,
+static int __init aafs_create(const char *name, umode_t mask,
const struct file_operations *fops)
{
struct dentry *dentry;
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 96502b22b26..f3fafedd798 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -133,7 +133,7 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
struct aa_profile *profile = sa->aad.profile;
pid_t pid;
rcu_read_lock();
- pid = tsk->real_parent->pid;
+ pid = rcu_dereference(tsk->real_parent)->pid;
rcu_read_unlock();
audit_log_format(ab, " parent=%d", pid);
if (profile->ns != root_ns) {
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 38ccaea0820..df364956081 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -21,11 +21,11 @@
/* Control parameters settable through module/boot flags */
extern enum audit_mode aa_g_audit;
-extern int aa_g_audit_header;
-extern int aa_g_debug;
-extern int aa_g_lock_policy;
-extern int aa_g_logsyscall;
-extern int aa_g_paranoid_load;
+extern bool aa_g_audit_header;
+extern bool aa_g_debug;
+extern bool aa_g_lock_policy;
+extern bool aa_g_logsyscall;
+extern bool aa_g_paranoid_load;
extern unsigned int aa_g_path_max;
/*
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 37832026e58..97ce8fae49b 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -136,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,
- struct user_namespace *ns, int cap, int audit)
+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, ns, 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(current, profile, cap, audit);
}
return error;
}
@@ -262,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);
@@ -274,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);
}
@@ -344,13 +344,12 @@ 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)
@@ -671,7 +670,7 @@ 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 = {
.set = param_set_aabool,
.get = param_get_aabool
@@ -679,7 +678,7 @@ static struct kernel_param_ops param_ops_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
@@ -687,7 +686,7 @@ 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 = {
.set = param_set_aalockpolicy,
.get = param_get_aalockpolicy
@@ -709,7 +708,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 +719,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 +727,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,12 +742,12 @@ 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;
+static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
static int __init apparmor_enabled_setup(char *str)
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index b566eba4a65..9d070a7c3ff 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -13,7 +13,6 @@
*/
#include <linux/magic.h>
-#include <linux/mnt_namespace.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/nsproxy.h>
diff --git a/security/capability.c b/security/capability.c
index 2984ea4f776..2f680eb02b5 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -125,7 +125,7 @@ static int cap_inode_init_security(struct inode *inode, struct inode *dir,
}
static int cap_inode_create(struct inode *inode, struct dentry *dentry,
- int mask)
+ umode_t mask)
{
return 0;
}
@@ -148,7 +148,7 @@ static int cap_inode_symlink(struct inode *inode, struct dentry *dentry,
}
static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry,
- int mask)
+ umode_t mask)
{
return 0;
}
@@ -159,7 +159,7 @@ static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry)
}
static int cap_inode_mknod(struct inode *inode, struct dentry *dentry,
- int mode, dev_t dev)
+ umode_t mode, dev_t dev)
{
return 0;
}
@@ -235,13 +235,13 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
}
#ifdef CONFIG_SECURITY_PATH
-static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode,
+static int cap_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
unsigned int dev)
{
return 0;
}
-static int cap_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
+static int cap_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
{
return 0;
}
@@ -279,8 +279,7 @@ static int cap_path_truncate(struct path *path)
return 0;
}
-static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
- mode_t mode)
+static int cap_path_chmod(struct path *path, umode_t mode)
{
return 0;
}
@@ -999,7 +998,6 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, sem_semctl);
set_to_cap_if_null(ops, sem_semop);
set_to_cap_if_null(ops, netlink_send);
- set_to_cap_if_null(ops, netlink_recv);
set_to_cap_if_null(ops, d_instantiate);
set_to_cap_if_null(ops, getprocattr);
set_to_cap_if_null(ops, setprocattr);
diff --git a/security/commoncap.c b/security/commoncap.c
index ee4f8486e5f..7ce191ea29a 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -56,17 +56,8 @@ int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
return 0;
}
-int cap_netlink_recv(struct sk_buff *skb, int cap)
-{
- if (!cap_raised(current_cap(), cap))
- return -EPERM;
- return 0;
-}
-EXPORT_SYMBOL(cap_netlink_recv);
-
/**
* cap_capable - Determine whether a task has a particular effective capability
- * @tsk: The task to query
* @cred: The credentials to use
* @ns: The user namespace in which we need the capability
* @cap: The capability to check for
@@ -80,8 +71,8 @@ EXPORT_SYMBOL(cap_netlink_recv);
* cap_has_capability() returns 0 when a task has a capability, but the
* kernel's capable() and has_capability() returns 1 for this case.
*/
-int cap_capable(struct task_struct *tsk, const struct cred *cred,
- struct user_namespace *targ_ns, int cap, int audit)
+int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
+ int cap, int audit)
{
for (;;) {
/* The creator of the user namespace has all caps. */
@@ -222,9 +213,8 @@ static inline int cap_inh_is_capped(void)
/* they are so limited unless the current task has the CAP_SETPCAP
* capability
*/
- if (cap_capable(current, current_cred(),
- current_cred()->user->user_ns, CAP_SETPCAP,
- SECURITY_CAP_AUDIT) == 0)
+ if (cap_capable(current_cred(), current_cred()->user->user_ns,
+ CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0)
return 0;
return 1;
}
@@ -874,7 +864,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
& (new->securebits ^ arg2)) /*[1]*/
|| ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/
|| (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
- || (cap_capable(current, current_cred(),
+ || (cap_capable(current_cred(),
current_cred()->user->user_ns, CAP_SETPCAP,
SECURITY_CAP_AUDIT) != 0) /*[4]*/
/*
@@ -940,7 +930,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
{
int cap_sys_admin = 0;
- if (cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_ADMIN,
+ if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
SECURITY_CAP_NOAUDIT) == 0)
cap_sys_admin = 1;
return __vm_enough_memory(mm, pages, cap_sys_admin);
@@ -967,7 +957,7 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
int ret = 0;
if (addr < dac_mmap_min_addr) {
- ret = cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_RAWIO,
+ ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
SECURITY_CAP_AUDIT);
/* set PF_SUPERPRIV if it turns out we allow the low mmap */
if (ret == 0)
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 4450fbeec41..8b5b5d8612c 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -62,11 +62,12 @@ static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
struct cgroup_subsys devices_subsys;
static int devcgroup_can_attach(struct cgroup_subsys *ss,
- struct cgroup *new_cgroup, struct task_struct *task)
+ struct cgroup *new_cgrp, struct cgroup_taskset *set)
{
- if (current != task && !capable(CAP_SYS_ADMIN))
- return -EPERM;
+ struct task_struct *task = cgroup_taskset_first(set);
+ if (current != task && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
return 0;
}
diff --git a/security/inode.c b/security/inode.c
index c4df2fbebe6..43ce6e19015 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -25,100 +25,6 @@
static struct vfsmount *mount;
static int mount_count;
-/*
- * TODO:
- * I think I can get rid of these default_file_ops, but not quite sure...
- */
-static ssize_t default_read_file(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- return 0;
-}
-
-static ssize_t default_write_file(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- return count;
-}
-
-static int default_open(struct inode *inode, struct file *file)
-{
- if (inode->i_private)
- file->private_data = inode->i_private;
-
- return 0;
-}
-
-static const struct file_operations default_file_ops = {
- .read = default_read_file,
- .write = default_write_file,
- .open = default_open,
- .llseek = noop_llseek,
-};
-
-static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
-{
- struct inode *inode = new_inode(sb);
-
- if (inode) {
- inode->i_ino = get_next_ino();
- inode->i_mode = mode;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- switch (mode & S_IFMT) {
- default:
- init_special_inode(inode, mode, dev);
- break;
- case S_IFREG:
- inode->i_fop = &default_file_ops;
- break;
- case S_IFDIR:
- inode->i_op = &simple_dir_inode_operations;
- inode->i_fop = &simple_dir_operations;
-
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
- inc_nlink(inode);
- break;
- }
- }
- return inode;
-}
-
-/* SMP-safe */
-static int mknod(struct inode *dir, struct dentry *dentry,
- int mode, dev_t dev)
-{
- struct inode *inode;
- int error = -ENOMEM;
-
- if (dentry->d_inode)
- return -EEXIST;
-
- inode = get_inode(dir->i_sb, mode, dev);
- if (inode) {
- d_instantiate(dentry, inode);
- dget(dentry);
- error = 0;
- }
- return error;
-}
-
-static int mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- int res;
-
- mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
- res = mknod(dir, dentry, mode, 0);
- if (!res)
- inc_nlink(dir);
- return res;
-}
-
-static int create(struct inode *dir, struct dentry *dentry, int mode)
-{
- mode = (mode & S_IALLUGO) | S_IFREG;
- return mknod(dir, dentry, mode, 0);
-}
-
static inline int positive(struct dentry *dentry)
{
return dentry->d_inode && !d_unhashed(dentry);
@@ -145,38 +51,6 @@ static struct file_system_type fs_type = {
.kill_sb = kill_litter_super,
};
-static int create_by_name(const char *name, mode_t mode,
- struct dentry *parent,
- struct dentry **dentry)
-{
- int error = 0;
-
- *dentry = NULL;
-
- /* If the parent is not specified, we create it in the root.
- * We need the root dentry to do this, which is in the super
- * block. A pointer to that is in the struct vfsmount that we
- * have around.
- */
- if (!parent)
- parent = mount->mnt_sb->s_root;
-
- mutex_lock(&parent->d_inode->i_mutex);
- *dentry = lookup_one_len(name, parent, strlen(name));
- if (!IS_ERR(*dentry)) {
- if ((mode & S_IFMT) == S_IFDIR)
- error = mkdir(parent->d_inode, *dentry, mode);
- else
- error = create(parent->d_inode, *dentry, mode);
- if (error)
- dput(*dentry);
- } else
- error = PTR_ERR(*dentry);
- mutex_unlock(&parent->d_inode->i_mutex);
-
- return error;
-}
-
/**
* securityfs_create_file - create a file in the securityfs filesystem
*
@@ -205,35 +79,70 @@ static int create_by_name(const char *name, mode_t mode,
* If securityfs is not enabled in the kernel, the value %-ENODEV is
* returned.
*/
-struct dentry *securityfs_create_file(const char *name, mode_t mode,
+struct dentry *securityfs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops)
{
- struct dentry *dentry = NULL;
+ struct dentry *dentry;
+ int is_dir = S_ISDIR(mode);
+ struct inode *dir, *inode;
int error;
+ if (!is_dir) {
+ BUG_ON(!fops);
+ mode = (mode & S_IALLUGO) | S_IFREG;
+ }
+
pr_debug("securityfs: creating file '%s'\n",name);
error = simple_pin_fs(&fs_type, &mount, &mount_count);
- if (error) {
- dentry = ERR_PTR(error);
- goto exit;
+ if (error)
+ return ERR_PTR(error);
+
+ if (!parent)
+ parent = mount->mnt_root;
+
+ dir = parent->d_inode;
+
+ mutex_lock(&dir->i_mutex);
+ dentry = lookup_one_len(name, parent, strlen(name));
+ if (IS_ERR(dentry))
+ goto out;
+
+ if (dentry->d_inode) {
+ error = -EEXIST;
+ goto out1;
}
- error = create_by_name(name, mode, parent, &dentry);
- if (error) {
- dentry = ERR_PTR(error);
- simple_release_fs(&mount, &mount_count);
- goto exit;
+ inode = new_inode(dir->i_sb);
+ if (!inode) {
+ error = -ENOMEM;
+ goto out1;
}
- if (dentry->d_inode) {
- if (fops)
- dentry->d_inode->i_fop = fops;
- if (data)
- dentry->d_inode->i_private = data;
+ inode->i_ino = get_next_ino();
+ inode->i_mode = mode;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_private = data;
+ if (is_dir) {
+ inode->i_op = &simple_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+ inc_nlink(inode);
+ inc_nlink(dir);
+ } else {
+ inode->i_fop = fops;
}
-exit:
+ d_instantiate(dentry, inode);
+ dget(dentry);
+ mutex_unlock(&dir->i_mutex);
+ return dentry;
+
+out1:
+ dput(dentry);
+ dentry = ERR_PTR(error);
+out:
+ mutex_unlock(&dir->i_mutex);
+ simple_release_fs(&mount, &mount_count);
return dentry;
}
EXPORT_SYMBOL_GPL(securityfs_create_file);
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 4bf00acf793..5bd1cc1b4a5 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -3,5 +3,19 @@ config INTEGRITY
def_bool y
depends on IMA || EVM
+config INTEGRITY_SIGNATURE
+ boolean "Digital signature verification using multiple keyrings"
+ depends on INTEGRITY && KEYS
+ default n
+ select SIGNATURE
+ help
+ This option enables digital signature verification support
+ using multiple keyrings. It defines separate keyrings for each
+ of the different use cases - evm, ima, and modules.
+ Different keyrings improves search performance, but also allow
+ to "lock" certain keyring to prevent adding new keys.
+ This is useful for evm and module keyrings, when keys are
+ usually only added from initramfs.
+
source security/integrity/ima/Kconfig
source security/integrity/evm/Kconfig
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 0ae44aea651..d43799cc14f 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -3,6 +3,7 @@
#
obj-$(CONFIG_INTEGRITY) += integrity.o
+obj-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
integrity-y := iint.o
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
new file mode 100644
index 00000000000..2dc167d7cde
--- /dev/null
+++ b/security/integrity/digsig.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 Intel Corporation
+ *
+ * Author:
+ * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/err.h>
+#include <linux/rbtree.h>
+#include <linux/key-type.h>
+#include <linux/digsig.h>
+
+#include "integrity.h"
+
+static struct key *keyring[INTEGRITY_KEYRING_MAX];
+
+static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
+ "_evm",
+ "_module",
+ "_ima",
+};
+
+int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
+ const char *digest, int digestlen)
+{
+ if (id >= INTEGRITY_KEYRING_MAX)
+ return -EINVAL;
+
+ if (!keyring[id]) {
+ keyring[id] =
+ request_key(&key_type_keyring, keyring_name[id], NULL);
+ if (IS_ERR(keyring[id])) {
+ int err = PTR_ERR(keyring[id]);
+ pr_err("no %s keyring: %d\n", keyring_name[id], err);
+ keyring[id] = NULL;
+ return err;
+ }
+ }
+
+ return digsig_verify(keyring[id], sig, siglen, digest, digestlen);
+}
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index d320f519743..c885247ebcf 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -12,14 +12,21 @@
* File: evm.h
*
*/
+
+#ifndef __INTEGRITY_EVM_H
+#define __INTEGRITY_EVM_H
+
#include <linux/xattr.h>
#include <linux/security.h>
+
#include "../integrity.h"
extern int evm_initialized;
extern char *evm_hmac;
+extern char *evm_hash;
extern struct crypto_shash *hmac_tfm;
+extern struct crypto_shash *hash_tfm;
/* List of EVM protected security xattrs */
extern char *evm_config_xattrnames[];
@@ -32,7 +39,12 @@ extern int evm_update_evmxattr(struct dentry *dentry,
extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
const char *req_xattr_value,
size_t req_xattr_value_len, char *digest);
+extern int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
+ const char *req_xattr_value,
+ size_t req_xattr_value_len, char *digest);
extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
char *hmac_val);
extern int evm_init_secfs(void);
extern void evm_cleanup_secfs(void);
+
+#endif
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 5dd5b140242..49a464f5595 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -26,36 +26,59 @@ static unsigned char evmkey[MAX_KEY_SIZE];
static int evmkey_len = MAX_KEY_SIZE;
struct crypto_shash *hmac_tfm;
+struct crypto_shash *hash_tfm;
-static struct shash_desc *init_desc(void)
+static DEFINE_MUTEX(mutex);
+
+static struct shash_desc *init_desc(char type)
{
- int rc;
+ long rc;
+ char *algo;
+ struct crypto_shash **tfm;
struct shash_desc *desc;
- if (hmac_tfm == NULL) {
- hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(hmac_tfm)) {
- pr_err("Can not allocate %s (reason: %ld)\n",
- evm_hmac, PTR_ERR(hmac_tfm));
- rc = PTR_ERR(hmac_tfm);
- hmac_tfm = NULL;
+ if (type == EVM_XATTR_HMAC) {
+ tfm = &hmac_tfm;
+ algo = evm_hmac;
+ } else {
+ tfm = &hash_tfm;
+ algo = evm_hash;
+ }
+
+ if (*tfm == NULL) {
+ mutex_lock(&mutex);
+ if (*tfm)
+ goto out;
+ *tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(*tfm)) {
+ rc = PTR_ERR(*tfm);
+ pr_err("Can not allocate %s (reason: %ld)\n", algo, rc);
+ *tfm = NULL;
+ mutex_unlock(&mutex);
return ERR_PTR(rc);
}
+ if (type == EVM_XATTR_HMAC) {
+ rc = crypto_shash_setkey(*tfm, evmkey, evmkey_len);
+ if (rc) {
+ crypto_free_shash(*tfm);
+ *tfm = NULL;
+ mutex_unlock(&mutex);
+ return ERR_PTR(rc);
+ }
+ }
+out:
+ mutex_unlock(&mutex);
}
- desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm),
+ desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm),
GFP_KERNEL);
if (!desc)
return ERR_PTR(-ENOMEM);
- desc->tfm = hmac_tfm;
+ desc->tfm = *tfm;
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
- rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len);
- if (rc)
- goto out;
rc = crypto_shash_init(desc);
-out:
if (rc) {
kfree(desc);
return ERR_PTR(rc);
@@ -97,9 +120,11 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
* the hmac using the requested xattr value. Don't alloc/free memory for
* each xattr, but attempt to re-use the previously allocated memory.
*/
-int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
- const char *req_xattr_value, size_t req_xattr_value_len,
- char *digest)
+static int evm_calc_hmac_or_hash(struct dentry *dentry,
+ const char *req_xattr_name,
+ const char *req_xattr_value,
+ size_t req_xattr_value_len,
+ char type, char *digest)
{
struct inode *inode = dentry->d_inode;
struct shash_desc *desc;
@@ -111,7 +136,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
if (!inode->i_op || !inode->i_op->getxattr)
return -EOPNOTSUPP;
- desc = init_desc();
+ desc = init_desc(type);
if (IS_ERR(desc))
return PTR_ERR(desc);
@@ -145,6 +170,22 @@ out:
return error;
}
+int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
+ const char *req_xattr_value, size_t req_xattr_value_len,
+ char *digest)
+{
+ return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
+ req_xattr_value_len, EVM_XATTR_HMAC, digest);
+}
+
+int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
+ const char *req_xattr_value, size_t req_xattr_value_len,
+ char *digest)
+{
+ return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value,
+ req_xattr_value_len, IMA_XATTR_DIGEST, digest);
+}
+
/*
* Calculate the hmac and update security.evm xattr
*
@@ -175,7 +216,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
{
struct shash_desc *desc;
- desc = init_desc();
+ desc = init_desc(EVM_XATTR_HMAC);
if (IS_ERR(desc)) {
printk(KERN_INFO "init_desc failed\n");
return PTR_ERR(desc);
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 92d3d99a9f7..8901501425f 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -25,6 +25,7 @@
int evm_initialized;
char *evm_hmac = "hmac(sha1)";
+char *evm_hash = "sha1";
char *evm_config_xattrnames[] = {
#ifdef CONFIG_SECURITY_SELINUX
@@ -46,6 +47,29 @@ static int __init evm_set_fixmode(char *str)
}
__setup("evm=", evm_set_fixmode);
+static int evm_find_protected_xattrs(struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+ char **xattr;
+ int error;
+ int count = 0;
+
+ if (!inode->i_op || !inode->i_op->getxattr)
+ return -EOPNOTSUPP;
+
+ for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
+ error = inode->i_op->getxattr(dentry, *xattr, NULL, 0);
+ if (error < 0) {
+ if (error == -ENODATA)
+ continue;
+ return error;
+ }
+ count++;
+ }
+
+ return count;
+}
+
/*
* evm_verify_hmac - calculate and compare the HMAC with the EVM xattr
*
@@ -65,32 +89,72 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
size_t xattr_value_len,
struct integrity_iint_cache *iint)
{
- struct evm_ima_xattr_data xattr_data;
+ struct evm_ima_xattr_data *xattr_data = NULL;
+ struct evm_ima_xattr_data calc;
enum integrity_status evm_status = INTEGRITY_PASS;
- int rc;
+ int rc, xattr_len;
if (iint && iint->evm_status == INTEGRITY_PASS)
return iint->evm_status;
/* if status is not PASS, try to check again - against -ENOMEM */
- rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
- xattr_value_len, xattr_data.digest);
- if (rc < 0) {
- evm_status = (rc == -ENODATA)
- ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
+ /* first need to know the sig type */
+ rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
+ GFP_NOFS);
+ if (rc <= 0) {
+ if (rc == 0)
+ evm_status = INTEGRITY_FAIL; /* empty */
+ else if (rc == -ENODATA) {
+ rc = evm_find_protected_xattrs(dentry);
+ if (rc > 0)
+ evm_status = INTEGRITY_NOLABEL;
+ else if (rc == 0)
+ evm_status = INTEGRITY_NOXATTRS; /* new file */
+ }
goto out;
}
- xattr_data.type = EVM_XATTR_HMAC;
- rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data,
- sizeof xattr_data, GFP_NOFS);
- if (rc < 0)
- evm_status = (rc == -ENODATA)
- ? INTEGRITY_NOLABEL : INTEGRITY_FAIL;
+ xattr_len = rc - 1;
+
+ /* check value type */
+ switch (xattr_data->type) {
+ case EVM_XATTR_HMAC:
+ rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
+ xattr_value_len, calc.digest);
+ if (rc)
+ break;
+ rc = memcmp(xattr_data->digest, calc.digest,
+ sizeof(calc.digest));
+ if (rc)
+ rc = -EINVAL;
+ break;
+ case EVM_IMA_XATTR_DIGSIG:
+ rc = evm_calc_hash(dentry, xattr_name, xattr_value,
+ xattr_value_len, calc.digest);
+ if (rc)
+ break;
+ rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
+ xattr_data->digest, xattr_len,
+ calc.digest, sizeof(calc.digest));
+ if (!rc) {
+ /* we probably want to replace rsa with hmac here */
+ evm_update_evmxattr(dentry, xattr_name, xattr_value,
+ xattr_value_len);
+ }
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc)
+ evm_status = (rc == -ENODATA) ?
+ INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
out:
if (iint)
iint->evm_status = evm_status;
+ kfree(xattr_data);
return evm_status;
}
@@ -354,6 +418,8 @@ static int __init init_evm(void)
printk(KERN_INFO "EVM: Error registering secfs\n");
goto err;
}
+
+ return 0;
err:
return error;
}
@@ -363,6 +429,8 @@ static void __exit cleanup_evm(void)
evm_cleanup_secfs();
if (hmac_tfm)
crypto_free_shash(hmac_tfm);
+ if (hash_tfm)
+ crypto_free_shash(hash_tfm);
}
/*
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 0d50df04ccc..88a2788b981 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -178,8 +178,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
result = ima_store_template(entry, violation, inode);
- if (!result)
+ if (!result || result == -EEXIST)
iint->flags |= IMA_MEASURED;
- else
+ if (result < 0)
kfree(entry);
}
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index c5c5a72c30b..2ad942fb1e2 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -56,9 +56,11 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, fname);
}
- if (inode)
- audit_log_format(ab, " dev=%s ino=%lu",
- inode->i_sb->s_id, inode->i_ino);
+ if (inode) {
+ audit_log_format(ab, " dev=");
+ audit_log_untrustedstring(ab, inode->i_sb->s_id);
+ audit_log_format(ab, " ino=%lu", inode->i_ino);
+ }
audit_log_format(ab, " res=%d", !result ? 0 : 1);
audit_log_end(ab);
}
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index d661afbe474..d45061d02fe 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -99,6 +99,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
struct inode *inode, enum ima_hooks func, int mask)
{
struct task_struct *tsk = current;
+ const struct cred *cred = current_cred();
int i;
if ((rule->flags & IMA_FUNC) && rule->func != func)
@@ -108,7 +109,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
if ((rule->flags & IMA_FSMAGIC)
&& rule->fsmagic != inode->i_sb->s_magic)
return false;
- if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
+ if ((rule->flags & IMA_UID) && rule->uid != cred->uid)
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0;
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 8e28f04a5e2..55a6271bce7 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -23,6 +23,8 @@
#include <linux/slab.h>
#include "ima.h"
+#define AUDIT_CAUSE_LEN_MAX 32
+
LIST_HEAD(ima_measurements); /* list of all measurements */
/* key: inode (before secure-hashing a file) */
@@ -94,7 +96,8 @@ static int ima_pcr_extend(const u8 *hash)
result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
if (result != 0)
- pr_err("IMA: Error Communicating to TPM chip\n");
+ pr_err("IMA: Error Communicating to TPM chip, result: %d\n",
+ result);
return result;
}
@@ -106,14 +109,16 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
{
u8 digest[IMA_DIGEST_SIZE];
const char *audit_cause = "hash_added";
+ char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX];
int audit_info = 1;
- int result = 0;
+ int result = 0, tpmresult = 0;
mutex_lock(&ima_extend_list_mutex);
if (!violation) {
memcpy(digest, entry->digest, sizeof digest);
if (ima_lookup_digest_entry(digest)) {
audit_cause = "hash_exists";
+ result = -EEXIST;
goto out;
}
}
@@ -128,9 +133,11 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
if (violation) /* invalidate pcr */
memset(digest, 0xff, sizeof digest);
- result = ima_pcr_extend(digest);
- if (result != 0) {
- audit_cause = "TPM error";
+ tpmresult = ima_pcr_extend(digest);
+ if (tpmresult != 0) {
+ snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TPM_error(%d)",
+ tpmresult);
+ audit_cause = tpm_audit_cause;
audit_info = 0;
}
out:
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 3143a3c3986..7a25ecec5aa 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -46,5 +46,26 @@ struct integrity_iint_cache {
struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
+#define INTEGRITY_KEYRING_EVM 0
+#define INTEGRITY_KEYRING_MODULE 1
+#define INTEGRITY_KEYRING_IMA 2
+#define INTEGRITY_KEYRING_MAX 3
+
+#ifdef CONFIG_INTEGRITY_SIGNATURE
+
+int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
+ const char *digest, int digestlen);
+
+#else
+
+static inline int integrity_digsig_verify(const unsigned int id,
+ const char *sig, int siglen,
+ const char *digest, int digestlen)
+{
+ return -EOPNOTSUPP;
+}
+
+#endif /* CONFIG_INTEGRITY_SIGNATURE */
+
/* set during initialization */
extern int iint_initialized;
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 41144f71d61..2d1bb8af769 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -314,7 +314,7 @@ static struct key *request_user_key(const char *master_desc, u8 **master_key,
goto error;
down_read(&ukey->sem);
- upayload = rcu_dereference(ukey->payload.data);
+ upayload = ukey->payload.data;
*master_key = upayload->data;
*master_keylen = upayload->datalen;
error:
@@ -810,7 +810,7 @@ static int encrypted_instantiate(struct key *key, const void *data,
goto out;
}
- rcu_assign_pointer(key->payload.data, epayload);
+ rcu_assign_keypointer(key, epayload);
out:
kfree(datablob);
return ret;
@@ -874,7 +874,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen)
memcpy(new_epayload->payload_data, epayload->payload_data,
epayload->payload_datalen);
- rcu_assign_pointer(key->payload.data, new_epayload);
+ rcu_assign_keypointer(key, new_epayload);
call_rcu(&epayload->rcu, encrypted_rcu_free);
out:
kfree(buf);
diff --git a/security/keys/encrypted-keys/masterkey_trusted.c b/security/keys/encrypted-keys/masterkey_trusted.c
index df87272e3f5..013f7e5d3a2 100644
--- a/security/keys/encrypted-keys/masterkey_trusted.c
+++ b/security/keys/encrypted-keys/masterkey_trusted.c
@@ -18,6 +18,8 @@
#include <linux/module.h>
#include <linux/err.h>
#include <keys/trusted-type.h>
+#include <keys/encrypted-type.h>
+#include "encrypted.h"
/*
* request_trusted_key - request the trusted key
@@ -37,7 +39,7 @@ struct key *request_trusted_key(const char *trusted_desc,
goto error;
down_read(&tkey->sem);
- tpayload = rcu_dereference(tkey->payload.data);
+ tpayload = tkey->payload.data;
*master_key = tpayload->key;
*master_keylen = tpayload->key_len;
error:
diff --git a/security/keys/gc.c b/security/keys/gc.c
index bf4d8da5a79..a42b45531aa 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -145,7 +145,9 @@ static void key_gc_keyring(struct key *keyring, time_t limit)
if (!klist)
goto unlock_dont_gc;
- for (loop = klist->nkeys - 1; loop >= 0; loop--) {
+ loop = klist->nkeys;
+ smp_rmb();
+ for (loop--; loop >= 0; loop--) {
key = klist->keys[loop];
if (test_bit(KEY_FLAG_DEAD, &key->flags) ||
(key->expiry > 0 && key->expiry <= limit))
diff --git a/security/keys/internal.h b/security/keys/internal.h
index c7a7caec483..65647f82558 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -33,6 +33,7 @@
extern struct key_type key_type_dead;
extern struct key_type key_type_user;
+extern struct key_type key_type_logon;
/*****************************************************************************/
/*
diff --git a/security/keys/key.c b/security/keys/key.c
index 4414abddcb5..7ada8019be1 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -291,6 +291,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
atomic_set(&key->usage, 1);
init_rwsem(&key->sem);
+ lockdep_set_class(&key->sem, &type->lock_class);
key->type = type;
key->user = user;
key->quotalen = quotalen;
@@ -946,6 +947,8 @@ int register_key_type(struct key_type *ktype)
struct key_type *p;
int ret;
+ memset(&ktype->lock_class, 0, sizeof(ktype->lock_class));
+
ret = -EEXIST;
down_write(&key_types_sem);
@@ -996,6 +999,7 @@ void __init key_init(void)
list_add_tail(&key_type_keyring.link, &key_types_list);
list_add_tail(&key_type_dead.link, &key_types_list);
list_add_tail(&key_type_user.link, &key_types_list);
+ list_add_tail(&key_type_logon.link, &key_types_list);
/* record the root user tracking */
rb_link_node(&root_key_user.node,
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 37a7f3b2885..d605f75292e 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -319,7 +319,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
struct key *keyring, *key;
key_ref_t key_ref;
long err;
- int sp, kix;
+ int sp, nkeys, kix;
keyring = key_ref_to_ptr(keyring_ref);
possessed = is_key_possessed(keyring_ref);
@@ -380,7 +380,9 @@ descend:
goto not_this_keyring;
/* iterate through the keys in this keyring first */
- for (kix = 0; kix < keylist->nkeys; kix++) {
+ nkeys = keylist->nkeys;
+ smp_rmb();
+ for (kix = 0; kix < nkeys; kix++) {
key = keylist->keys[kix];
kflags = key->flags;
@@ -421,7 +423,9 @@ descend:
/* search through the keyrings nested in this one */
kix = 0;
ascend:
- for (; kix < keylist->nkeys; kix++) {
+ nkeys = keylist->nkeys;
+ smp_rmb();
+ for (; kix < nkeys; kix++) {
key = keylist->keys[kix];
if (key->type != &key_type_keyring)
continue;
@@ -515,7 +519,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
struct keyring_list *klist;
unsigned long possessed;
struct key *keyring, *key;
- int loop;
+ int nkeys, loop;
keyring = key_ref_to_ptr(keyring_ref);
possessed = is_key_possessed(keyring_ref);
@@ -524,7 +528,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
klist = rcu_dereference(keyring->payload.subscriptions);
if (klist) {
- for (loop = 0; loop < klist->nkeys; loop++) {
+ nkeys = klist->nkeys;
+ smp_rmb();
+ for (loop = 0; loop < nkeys ; loop++) {
key = klist->keys[loop];
if (key->type == ktype &&
@@ -622,7 +628,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
struct keyring_list *keylist;
struct key *subtree, *key;
- int sp, kix, ret;
+ int sp, nkeys, kix, ret;
rcu_read_lock();
@@ -645,7 +651,9 @@ descend:
ascend:
/* iterate through the remaining keys in this keyring */
- for (; kix < keylist->nkeys; kix++) {
+ nkeys = keylist->nkeys;
+ smp_rmb();
+ for (; kix < nkeys; kix++) {
key = keylist->keys[kix];
if (key == A)
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 0ed5fdf238a..2d5d041f204 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -993,7 +993,7 @@ out:
kfree(datablob);
kfree(options);
if (!ret)
- rcu_assign_pointer(key->payload.data, payload);
+ rcu_assign_keypointer(key, payload);
else
kfree(payload);
return ret;
@@ -1067,7 +1067,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen)
goto out;
}
}
- rcu_assign_pointer(key->payload.data, new_p);
+ rcu_assign_keypointer(key, new_p);
call_rcu(&p->rcu, trusted_rcu_free);
out:
kfree(datablob);
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 69ff52c08e9..c7660a25a3e 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -18,6 +18,8 @@
#include <asm/uaccess.h>
#include "internal.h"
+static int logon_vet_description(const char *desc);
+
/*
* user defined keys take an arbitrary string as the description and an
* arbitrary blob of data as the payload
@@ -36,6 +38,24 @@ struct key_type key_type_user = {
EXPORT_SYMBOL_GPL(key_type_user);
/*
+ * This key type is essentially the same as key_type_user, but it does
+ * not define a .read op. This is suitable for storing username and
+ * password pairs in the keyring that you do not want to be readable
+ * from userspace.
+ */
+struct key_type key_type_logon = {
+ .name = "logon",
+ .instantiate = user_instantiate,
+ .update = user_update,
+ .match = user_match,
+ .revoke = user_revoke,
+ .destroy = user_destroy,
+ .describe = user_describe,
+ .vet_description = logon_vet_description,
+};
+EXPORT_SYMBOL_GPL(key_type_logon);
+
+/*
* instantiate a user defined key
*/
int user_instantiate(struct key *key, const void *data, size_t datalen)
@@ -59,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen)
/* attach the data */
upayload->datalen = datalen;
memcpy(upayload->data, data, datalen);
- rcu_assign_pointer(key->payload.data, upayload);
+ rcu_assign_keypointer(key, upayload);
ret = 0;
error:
@@ -98,7 +118,7 @@ int user_update(struct key *key, const void *data, size_t datalen)
if (ret == 0) {
/* attach the new data, displacing the old */
zap = key->payload.data;
- rcu_assign_pointer(key->payload.data, upayload);
+ rcu_assign_keypointer(key, upayload);
key->expiry = 0;
}
@@ -133,7 +153,7 @@ void user_revoke(struct key *key)
key_payload_reserve(key, 0);
if (upayload) {
- rcu_assign_pointer(key->payload.data, NULL);
+ rcu_assign_keypointer(key, NULL);
kfree_rcu(upayload, rcu);
}
}
@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
}
EXPORT_SYMBOL_GPL(user_read);
+
+/* Vet the description for a "logon" key */
+static int logon_vet_description(const char *desc)
+{
+ char *p;
+
+ /* require a "qualified" description string */
+ p = strchr(desc, ':');
+ if (!p)
+ return -EINVAL;
+
+ /* also reject description with ':' as first char */
+ if (p == desc)
+ return -EINVAL;
+
+ return 0;
+}
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 893af8a2fa1..293b8c45b1d 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -114,19 +114,20 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
int offset, ret = 0;
struct ipv6hdr *ip6;
u8 nexthdr;
+ __be16 frag_off;
ip6 = ipv6_hdr(skb);
if (ip6 == NULL)
return -EINVAL;
- ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
- ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
+ ad->u.net.v6info.saddr = ip6->saddr;
+ ad->u.net.v6info.daddr = ip6->daddr;
ret = 0;
/* IPv6 can have several extension header before the Transport header
* skip them */
offset = skb_network_offset(skb);
offset += sizeof(*ip6);
nexthdr = ip6->nexthdr;
- offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
+ offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
if (offset < 0)
return 0;
if (proto)
@@ -231,13 +232,14 @@ static void dump_common_audit_data(struct audit_buffer *ab,
case LSM_AUDIT_DATA_PATH: {
struct inode *inode;
- audit_log_d_path(ab, "path=", &a->u.path);
+ audit_log_d_path(ab, " path=", &a->u.path);
inode = a->u.path.dentry->d_inode;
- if (inode)
- audit_log_format(ab, " dev=%s ino=%lu",
- inode->i_sb->s_id,
- inode->i_ino);
+ if (inode) {
+ audit_log_format(ab, " dev=");
+ audit_log_untrustedstring(ab, inode->i_sb->s_id);
+ audit_log_format(ab, " ino=%lu", inode->i_ino);
+ }
break;
}
case LSM_AUDIT_DATA_DENTRY: {
@@ -247,10 +249,11 @@ static void dump_common_audit_data(struct audit_buffer *ab,
audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
inode = a->u.dentry->d_inode;
- if (inode)
- audit_log_format(ab, " dev=%s ino=%lu",
- inode->i_sb->s_id,
- inode->i_ino);
+ if (inode) {
+ audit_log_format(ab, " dev=");
+ audit_log_untrustedstring(ab, inode->i_sb->s_id);
+ audit_log_format(ab, " ino=%lu", inode->i_ino);
+ }
break;
}
case LSM_AUDIT_DATA_INODE: {
@@ -265,8 +268,9 @@ static void dump_common_audit_data(struct audit_buffer *ab,
dentry->d_name.name);
dput(dentry);
}
- audit_log_format(ab, " dev=%s ino=%lu", inode->i_sb->s_id,
- inode->i_ino);
+ audit_log_format(ab, " dev=");
+ audit_log_untrustedstring(ab, inode->i_sb->s_id);
+ audit_log_format(ab, " ino=%lu", inode->i_ino);
break;
}
case LSM_AUDIT_DATA_TASK:
@@ -314,7 +318,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
.dentry = u->dentry,
.mnt = u->mnt
};
- audit_log_d_path(ab, "path=", &path);
+ audit_log_d_path(ab, " path=", &path);
break;
}
if (!u->addr)
diff --git a/security/security.c b/security/security.c
index 0c6cc69c8f8..d7542493454 100644
--- a/security/security.c
+++ b/security/security.c
@@ -155,35 +155,16 @@ int security_capset(struct cred *new, const struct cred *old,
effective, inheritable, permitted);
}
-int security_capable(struct user_namespace *ns, const struct cred *cred,
+int security_capable(const struct cred *cred, struct user_namespace *ns,
int cap)
{
- return security_ops->capable(current, cred, ns, cap,
- SECURITY_CAP_AUDIT);
+ return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT);
}
-int security_real_capable(struct task_struct *tsk, struct user_namespace *ns,
- int cap)
+int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
+ int cap)
{
- const struct cred *cred;
- int ret;
-
- cred = get_task_cred(tsk);
- ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_AUDIT);
- put_cred(cred);
- return ret;
-}
-
-int security_real_capable_noaudit(struct task_struct *tsk,
- struct user_namespace *ns, int cap)
-{
- const struct cred *cred;
- int ret;
-
- cred = get_task_cred(tsk);
- ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_NOAUDIT);
- put_cred(cred);
- return ret;
+ return security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
}
int security_quotactl(int cmds, int type, int id, struct super_block *sb)
@@ -381,14 +362,14 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
void **value, size_t *len)
{
if (unlikely(IS_PRIVATE(inode)))
- return 0;
+ return -EOPNOTSUPP;
return security_ops->inode_init_security(inode, dir, qstr, name, value,
len);
}
EXPORT_SYMBOL(security_old_inode_init_security);
#ifdef CONFIG_SECURITY_PATH
-int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
+int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
unsigned int dev)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
@@ -397,7 +378,7 @@ int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
}
EXPORT_SYMBOL(security_path_mknod);
-int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
+int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
return 0;
@@ -454,12 +435,11 @@ int security_path_truncate(struct path *path)
return security_ops->path_truncate(path);
}
-int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
- mode_t mode)
+int security_path_chmod(struct path *path, umode_t mode)
{
- if (unlikely(IS_PRIVATE(dentry->d_inode)))
+ if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
return 0;
- return security_ops->path_chmod(dentry, mnt, mode);
+ return security_ops->path_chmod(path, mode);
}
int security_path_chown(struct path *path, uid_t uid, gid_t gid)
@@ -475,7 +455,7 @@ int security_path_chroot(struct path *path)
}
#endif
-int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
@@ -506,7 +486,7 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
return security_ops->inode_symlink(dir, dentry, old_name);
}
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
@@ -521,7 +501,7 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
return security_ops->inode_rmdir(dir, dentry);
}
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
@@ -995,12 +975,6 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb)
return security_ops->netlink_send(sk, skb);
}
-int security_netlink_recv(struct sk_buff *skb, int cap)
-{
- return security_ops->netlink_recv(skb, cap);
-}
-EXPORT_SYMBOL(security_netlink_recv);
-
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
{
return security_ops->secid_to_secctx(secid, secdata, seclen);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1126c10a5e8..6a3683e2842 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1090,7 +1090,7 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
return SECCLASS_NETLINK_ROUTE_SOCKET;
case NETLINK_FIREWALL:
return SECCLASS_NETLINK_FIREWALL_SOCKET;
- case NETLINK_INET_DIAG:
+ case NETLINK_SOCK_DIAG:
return SECCLASS_NETLINK_TCPDIAG_SOCKET;
case NETLINK_NFLOG:
return SECCLASS_NETLINK_NFLOG_SOCKET;
@@ -1415,8 +1415,7 @@ static int current_has_perm(const struct task_struct *tsk,
#endif
/* Check whether a task is allowed to use a capability. */
-static int task_has_capability(struct task_struct *tsk,
- const struct cred *cred,
+static int cred_has_capability(const struct cred *cred,
int cap, int audit)
{
struct common_audit_data ad;
@@ -1427,7 +1426,7 @@ static int task_has_capability(struct task_struct *tsk,
int rc;
COMMON_AUDIT_DATA_INIT(&ad, CAP);
- ad.tsk = tsk;
+ ad.tsk = current;
ad.u.cap = cap;
switch (CAP_TO_INDEX(cap)) {
@@ -1740,7 +1739,7 @@ static inline u32 file_mask_to_av(int mode, int mask)
{
u32 av = 0;
- if ((mode & S_IFMT) != S_IFDIR) {
+ if (!S_ISDIR(mode)) {
if (mask & MAY_EXEC)
av |= FILE__EXECUTE;
if (mask & MAY_READ)
@@ -1811,7 +1810,7 @@ static int selinux_ptrace_access_check(struct task_struct *child,
if (rc)
return rc;
- if (mode == PTRACE_MODE_READ) {
+ if (mode & PTRACE_MODE_READ) {
u32 sid = current_sid();
u32 csid = task_sid(child);
return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
@@ -1868,16 +1867,16 @@ static int selinux_capset(struct cred *new, const struct cred *old,
* the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
*/
-static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
- struct user_namespace *ns, int cap, int audit)
+static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
+ int cap, int audit)
{
int rc;
- rc = cap_capable(tsk, cred, ns, cap, audit);
+ rc = cap_capable(cred, ns, cap, audit);
if (rc)
return rc;
- return task_has_capability(tsk, cred, cap, audit);
+ return cred_has_capability(cred, cap, audit);
}
static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
@@ -1954,8 +1953,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
{
int rc, cap_sys_admin = 0;
- rc = selinux_capable(current, current_cred(),
- &init_user_ns, CAP_SYS_ADMIN,
+ rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
SECURITY_CAP_NOAUDIT);
if (rc == 0)
cap_sys_admin = 1;
@@ -2507,7 +2505,7 @@ static int selinux_mount(char *dev_name,
const struct cred *cred = current_cred();
if (flags & MS_REMOUNT)
- return superblock_has_perm(cred, path->mnt->mnt_sb,
+ return superblock_has_perm(cred, path->dentry->d_sb,
FILESYSTEM__REMOUNT, NULL);
else
return path_has_perm(cred, path, FILE__MOUNTON);
@@ -2598,7 +2596,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
return 0;
}
-static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
+static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
return may_create(dir, dentry, SECCLASS_FILE);
}
@@ -2618,7 +2616,7 @@ static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const
return may_create(dir, dentry, SECCLASS_LNK_FILE);
}
-static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
+static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
{
return may_create(dir, dentry, SECCLASS_DIR);
}
@@ -2628,7 +2626,7 @@ static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
return may_link(dir, dentry, MAY_RMDIR);
}
-static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
return may_create(dir, dentry, inode_mode_to_security_class(mode));
}
@@ -2859,8 +2857,7 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
* and lack of permission just means that we fall back to the
* in-core context value, not a denial.
*/
- error = selinux_capable(current, current_cred(),
- &init_user_ns, CAP_MAC_ADMIN,
+ error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
SECURITY_CAP_NOAUDIT);
if (!error)
error = security_sid_to_context_force(isec->sid, &context,
@@ -2993,8 +2990,8 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
case KDSKBENT:
case KDSKBSENT:
- error = task_has_capability(current, cred, CAP_SYS_TTY_CONFIG,
- SECURITY_CAP_AUDIT);
+ error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
+ SECURITY_CAP_AUDIT);
break;
/* default case assumes that the command will go
@@ -3561,19 +3558,20 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
u8 nexthdr;
int ret = -EINVAL, offset;
struct ipv6hdr _ipv6h, *ip6;
+ __be16 frag_off;
offset = skb_network_offset(skb);
ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
if (ip6 == NULL)
goto out;
- ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
- ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
+ ad->u.net.v6info.saddr = ip6->saddr;
+ ad->u.net.v6info.daddr = ip6->daddr;
ret = 0;
nexthdr = ip6->nexthdr;
offset += sizeof(_ipv6h);
- offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
+ offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
if (offset < 0)
goto out;
@@ -3871,7 +3869,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (family == PF_INET)
ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
else
- ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
+ ad.u.net.v6info.saddr = addr6->sin6_addr;
err = avc_has_perm(sksec->sid, sid,
sksec->sclass, node_perm, &ad);
@@ -4717,24 +4715,6 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
return selinux_nlmsg_perm(sk, skb);
}
-static int selinux_netlink_recv(struct sk_buff *skb, int capability)
-{
- int err;
- struct common_audit_data ad;
- u32 sid;
-
- err = cap_netlink_recv(skb, capability);
- if (err)
- return err;
-
- COMMON_AUDIT_DATA_INIT(&ad, CAP);
- ad.u.cap = capability;
-
- security_task_getsecid(current, &sid);
- return avc_has_perm(sid, sid, SECCLASS_CAPABILITY,
- CAP_TO_MASK(capability), &ad);
-}
-
static int ipc_alloc_security(struct task_struct *task,
struct kern_ipc_perm *perm,
u16 sclass)
@@ -5463,7 +5443,6 @@ static struct security_operations selinux_ops = {
.vm_enough_memory = selinux_vm_enough_memory,
.netlink_send = selinux_netlink_send,
- .netlink_recv = selinux_netlink_recv,
.bprm_set_creds = selinux_bprm_set_creds,
.bprm_committing_creds = selinux_bprm_committing_creds,
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index 3bf46abaa68..86365857c08 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -220,7 +220,7 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
case PF_INET6:
ret = security_node_sid(PF_INET6,
addr, sizeof(struct in6_addr), sid);
- ipv6_addr_copy(&new->nsec.addr.ipv6, addr);
+ new->nsec.addr.ipv6 = *(struct in6_addr *)addr;
break;
default:
BUG();
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
index 0b62bd11246..7b9eb1faf68 100644
--- a/security/selinux/netport.c
+++ b/security/selinux/netport.c
@@ -123,7 +123,9 @@ static void sel_netport_insert(struct sel_netport *port)
if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) {
struct sel_netport *tail;
tail = list_entry(
- rcu_dereference(sel_netport_hash[idx].list.prev),
+ rcu_dereference_protected(
+ sel_netport_hash[idx].list.prev,
+ lockdep_is_held(&sel_netport_lock)),
struct sel_netport, list);
list_del_rcu(&tail->list);
kfree_rcu(tail, rcu);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index f46658722c7..48a7d0014b4 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -749,14 +749,6 @@ out:
return length;
}
-static inline int hexcode_to_int(int code) {
- if (code == '\0' || !isxdigit(code))
- return -1;
- if (isdigit(code))
- return code - '0';
- return tolower(code) - 'a' + 10;
-}
-
static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
{
char *scon = NULL, *tcon = NULL;
@@ -808,9 +800,11 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
if (c1 == '+')
c1 = ' ';
else if (c1 == '%') {
- if ((c1 = hexcode_to_int(*r++)) < 0)
+ c1 = hex_to_bin(*r++);
+ if (c1 < 0)
goto out;
- if ((c2 = hexcode_to_int(*r++)) < 0)
+ c2 = hex_to_bin(*r++);
+ if (c2 < 0)
goto out;
c1 = (c1 << 4) | c2;
}
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index 2ec904177fe..377d148e715 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -175,7 +175,7 @@ void cond_policydb_destroy(struct policydb *p)
int cond_init_bool_indexes(struct policydb *p)
{
kfree(p->bool_val_to_struct);
- p->bool_val_to_struct = (struct cond_bool_datum **)
+ p->bool_val_to_struct =
kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum *), GFP_KERNEL);
if (!p->bool_val_to_struct)
return -ENOMEM;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 7db62b48eb4..e8af5b0ba80 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -406,7 +406,7 @@ static int smack_sb_statfs(struct dentry *dentry)
static int smack_sb_mount(char *dev_name, struct path *path,
char *type, unsigned long flags, void *data)
{
- struct superblock_smack *sbp = path->mnt->mnt_sb->s_security;
+ struct superblock_smack *sbp = path->dentry->d_sb->s_security;
struct smk_audit_info ad;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
@@ -435,7 +435,7 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags)
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, path);
- sbp = mnt->mnt_sb->s_security;
+ sbp = path.dentry->d_sb->s_security;
return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
}
diff --git a/security/tomoyo/.gitignore b/security/tomoyo/.gitignore
new file mode 100644
index 00000000000..5caf1a6f590
--- /dev/null
+++ b/security/tomoyo/.gitignore
@@ -0,0 +1,2 @@
+builtin-policy.h
+policy/
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c
index 075c3a6d164..5ca47ea3049 100644
--- a/security/tomoyo/audit.c
+++ b/security/tomoyo/audit.c
@@ -112,7 +112,7 @@ out:
*
* Returns file type string.
*/
-static inline const char *tomoyo_filetype(const mode_t mode)
+static inline const char *tomoyo_filetype(const umode_t mode)
{
switch (mode & S_IFMT) {
case S_IFREG:
@@ -180,7 +180,7 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
struct tomoyo_mini_stat *stat;
unsigned int dev;
- mode_t mode;
+ umode_t mode;
if (!obj->stat_valid[i])
continue;
stat = &obj->stat[i];
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index ed311d7a8ce..9512222d558 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -564,7 +564,7 @@ struct tomoyo_mini_stat {
uid_t uid;
gid_t gid;
ino_t ino;
- mode_t mode;
+ umode_t mode;
dev_t dev;
dev_t rdev;
};
@@ -1122,7 +1122,7 @@ static inline pid_t tomoyo_sys_getppid(void)
{
pid_t pid;
rcu_read_lock();
- pid = task_tgid_vnr(current->real_parent);
+ pid = task_tgid_vnr(rcu_dereference(current->real_parent));
rcu_read_unlock();
return pid;
}
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index d9f3ced8756..80a09c37cac 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -4,15 +4,8 @@
* Copyright (C) 2005-2011 NTT DATA CORPORATION
*/
-#include <linux/types.h>
-#include <linux/mount.h>
-#include <linux/mnt_namespace.h>
-#include <linux/fs_struct.h>
-#include <linux/magic.h>
-#include <linux/slab.h>
-#include <net/sock.h>
#include "common.h"
-#include "../../fs/internal.h"
+#include <linux/magic.h>
/**
* tomoyo_encode2 - Encode binary string to ascii string.
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
index 2672ac4f3be..482b2a5f48f 100644
--- a/security/tomoyo/securityfs_if.c
+++ b/security/tomoyo/securityfs_if.c
@@ -224,7 +224,7 @@ static const struct file_operations tomoyo_operations = {
*
* Returns nothing.
*/
-static void __init tomoyo_create_entry(const char *name, const mode_t mode,
+static void __init tomoyo_create_entry(const char *name, const umode_t mode,
struct dentry *parent, const u8 key)
{
securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 4b327b69174..620d37c159a 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -186,7 +186,7 @@ static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
* Returns 0 on success, negative value otherwise.
*/
static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
- int mode)
+ umode_t mode)
{
struct path path = { parent->mnt, dentry };
return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path,
@@ -234,7 +234,7 @@ static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
* Returns 0 on success, negative value otherwise.
*/
static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
- int mode, unsigned int dev)
+ umode_t mode, unsigned int dev)
{
struct path path = { parent->mnt, dentry };
int type = TOMOYO_TYPE_CREATE;
@@ -353,17 +353,14 @@ static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,
/**
* tomoyo_path_chmod - Target for security_path_chmod().
*
- * @dentry: Pointer to "struct dentry".
- * @mnt: Pointer to "struct vfsmount".
- * @mode: DAC permission mode.
+ * @path: Pointer to "struct path".
+ * @mode: DAC permission mode.
*
* Returns 0 on success, negative value otherwise.
*/
-static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
- mode_t mode)
+static int tomoyo_path_chmod(struct path *path, umode_t mode)
{
- struct path path = { mnt, dentry };
- return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, &path,
+ return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path,
mode & S_IALLUGO);
}
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 4a9b4b2eb75..867558c9833 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -492,13 +492,13 @@ static bool tomoyo_correct_word2(const char *string, size_t len)
if (d < '0' || d > '7' || e < '0' || e > '7')
break;
c = tomoyo_make_byte(c, d, e);
- if (tomoyo_invalid(c))
- continue; /* pattern is not \000 */
+ if (c <= ' ' || c >= 127)
+ continue;
}
goto out;
} else if (in_repetition && c == '/') {
goto out;
- } else if (tomoyo_invalid(c)) {
+ } else if (c <= ' ' || c >= 127) {
goto out;
}
}