diff options
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r-- | security/selinux/selinuxfs.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 0619a1cbbfbe..e172f182b65c 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -571,11 +571,18 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; + struct selinux_fs_info *fsi; struct selinux_load_state load_state; ssize_t length; void *data = NULL; + /* no partial writes */ + if (*ppos) + return -EINVAL; + /* no empty policies */ + if (!count) + return -EINVAL; + mutex_lock(&selinux_state.policy_mutex); length = avc_has_perm(current_sid(), SECINITSID_SECURITY, @@ -583,26 +590,22 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, if (length) goto out; - /* No partial writes. */ - length = -EINVAL; - if (*ppos != 0) - goto out; - - length = -ENOMEM; data = vmalloc(count); - if (!data) + if (!data) { + length = -ENOMEM; goto out; - - length = -EFAULT; - if (copy_from_user(data, buf, count) != 0) + } + if (copy_from_user(data, buf, count) != 0) { + length = -EFAULT; goto out; + } length = security_load_policy(data, count, &load_state); if (length) { pr_warn_ratelimited("SELinux: failed to load policy\n"); goto out; } - + fsi = file_inode(file)->i_sb->s_fs_info; length = sel_make_policy_nodes(fsi, load_state.policy); if (length) { pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n"); @@ -611,13 +614,12 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, } selinux_policy_commit(&load_state); - length = count; - audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, "auid=%u ses=%u lsm=selinux res=1", from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); + out: mutex_unlock(&selinux_state.policy_mutex); vfree(data); @@ -2123,7 +2125,6 @@ static struct file_system_type sel_fs_type = { .kill_sb = sel_kill_sb, }; -static struct vfsmount *selinuxfs_mount __ro_after_init; struct path selinux_null __ro_after_init; static int __init init_sel_fs(void) @@ -2145,20 +2146,29 @@ static int __init init_sel_fs(void) return err; } - selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type); - if (IS_ERR(selinuxfs_mount)) { + selinux_null.mnt = kern_mount(&sel_fs_type); + if (IS_ERR(selinux_null.mnt)) { pr_err("selinuxfs: could not mount!\n"); - err = PTR_ERR(selinuxfs_mount); - selinuxfs_mount = NULL; + err = PTR_ERR(selinux_null.mnt); + selinux_null.mnt = NULL; + return err; } + selinux_null.dentry = d_hash_and_lookup(selinux_null.mnt->mnt_root, &null_name); if (IS_ERR(selinux_null.dentry)) { pr_err("selinuxfs: could not lookup null!\n"); err = PTR_ERR(selinux_null.dentry); selinux_null.dentry = NULL; + return err; } + /* + * Try to pre-allocate the status page, so the sequence number of the + * initial policy load can be stored. + */ + (void) selinux_kernel_status_page(); + return err; } |