diff options
Diffstat (limited to 'security/selinux/selinuxfs.c')
| -rw-r--r-- | security/selinux/selinuxfs.c | 123 | 
1 files changed, 64 insertions, 59 deletions
| diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index f3d374d2ca04..f3a5a138a096 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -441,22 +441,16 @@ static int sel_release_policy(struct inode *inode, struct file *filp)  static ssize_t sel_read_policy(struct file *filp, char __user *buf,  			       size_t count, loff_t *ppos)  { -	struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;  	struct policy_load_memory *plm = filp->private_data;  	int ret; -	mutex_lock(&fsi->mutex); -  	ret = avc_has_perm(&selinux_state,  			   current_sid(), SECINITSID_SECURITY,  			  SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);  	if (ret) -		goto out; +		return ret; -	ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len); -out: -	mutex_unlock(&fsi->mutex); -	return ret; +	return simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);  }  static vm_fault_t sel_mmap_policy_fault(struct vm_fault *vmf) @@ -620,7 +614,7 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size)  	length = -ERANGE;  	if (len > SIMPLE_TRANSACTION_LIMIT) { -		printk(KERN_ERR "SELinux: %s:  context size (%u) exceeds " +		pr_err("SELinux: %s:  context size (%u) exceeds "  			"payload max\n", __func__, len);  		goto out;  	} @@ -773,7 +767,7 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size);  static ssize_t sel_write_user(struct file *file, char *buf, size_t size);  static ssize_t sel_write_member(struct file *file, char *buf, size_t size); -static ssize_t (*write_op[])(struct file *, char *, size_t) = { +static ssize_t (*const write_op[])(struct file *, char *, size_t) = {  	[SEL_ACCESS] = sel_write_access,  	[SEL_CREATE] = sel_write_create,  	[SEL_RELABEL] = sel_write_relabel, @@ -956,7 +950,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)  	length = -ERANGE;  	if (len > SIMPLE_TRANSACTION_LIMIT) { -		printk(KERN_ERR "SELinux: %s:  context size (%u) exceeds " +		pr_err("SELinux: %s:  context size (%u) exceeds "  			"payload max\n", __func__, len);  		goto out;  	} @@ -1147,7 +1141,7 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size)  	length = -ERANGE;  	if (len > SIMPLE_TRANSACTION_LIMIT) { -		printk(KERN_ERR "SELinux: %s:  context size (%u) exceeds " +		pr_err("SELinux: %s:  context size (%u) exceeds "  			"payload max\n", __func__, len);  		goto out;  	} @@ -1188,25 +1182,29 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,  	ret = -EINVAL;  	if (index >= fsi->bool_num || strcmp(name,  					     fsi->bool_pending_names[index])) -		goto out; +		goto out_unlock;  	ret = -ENOMEM;  	page = (char *)get_zeroed_page(GFP_KERNEL);  	if (!page) -		goto out; +		goto out_unlock;  	cur_enforcing = security_get_bool_value(fsi->state, index);  	if (cur_enforcing < 0) {  		ret = cur_enforcing; -		goto out; +		goto out_unlock;  	}  	length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,  			  fsi->bool_pending_values[index]); -	ret = simple_read_from_buffer(buf, count, ppos, page, length); -out:  	mutex_unlock(&fsi->mutex); +	ret = simple_read_from_buffer(buf, count, ppos, page, length); +out_free:  	free_page((unsigned long)page);  	return ret; + +out_unlock: +	mutex_unlock(&fsi->mutex); +	goto out_free;  }  static ssize_t sel_write_bool(struct file *filep, const char __user *buf, @@ -1219,6 +1217,17 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,  	unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;  	const char *name = filep->f_path.dentry->d_name.name; +	if (count >= PAGE_SIZE) +		return -ENOMEM; + +	/* No partial writes. */ +	if (*ppos != 0) +		return -EINVAL; + +	page = memdup_user_nul(buf, count); +	if (IS_ERR(page)) +		return PTR_ERR(page); +  	mutex_lock(&fsi->mutex);  	length = avc_has_perm(&selinux_state, @@ -1233,22 +1242,6 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,  					     fsi->bool_pending_names[index]))  		goto out; -	length = -ENOMEM; -	if (count >= PAGE_SIZE) -		goto out; - -	/* No partial writes. */ -	length = -EINVAL; -	if (*ppos != 0) -		goto out; - -	page = memdup_user_nul(buf, count); -	if (IS_ERR(page)) { -		length = PTR_ERR(page); -		page = NULL; -		goto out; -	} -  	length = -EINVAL;  	if (sscanf(page, "%d", &new_value) != 1)  		goto out; @@ -1280,6 +1273,17 @@ static ssize_t sel_commit_bools_write(struct file *filep,  	ssize_t length;  	int new_value; +	if (count >= PAGE_SIZE) +		return -ENOMEM; + +	/* No partial writes. */ +	if (*ppos != 0) +		return -EINVAL; + +	page = memdup_user_nul(buf, count); +	if (IS_ERR(page)) +		return PTR_ERR(page); +  	mutex_lock(&fsi->mutex);  	length = avc_has_perm(&selinux_state, @@ -1289,22 +1293,6 @@ static ssize_t sel_commit_bools_write(struct file *filep,  	if (length)  		goto out; -	length = -ENOMEM; -	if (count >= PAGE_SIZE) -		goto out; - -	/* No partial writes. */ -	length = -EINVAL; -	if (*ppos != 0) -		goto out; - -	page = memdup_user_nul(buf, count); -	if (IS_ERR(page)) { -		length = PTR_ERR(page); -		page = NULL; -		goto out; -	} -  	length = -EINVAL;  	if (sscanf(page, "%d", &new_value) != 1)  		goto out; @@ -1377,13 +1365,18 @@ static int sel_make_bools(struct selinux_fs_info *fsi)  		ret = -ENOMEM;  		inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR); -		if (!inode) +		if (!inode) { +			dput(dentry);  			goto out; +		}  		ret = -ENAMETOOLONG;  		len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); -		if (len >= PAGE_SIZE) +		if (len >= PAGE_SIZE) { +			dput(dentry); +			iput(inode);  			goto out; +		}  		isec = (struct inode_security_struct *)inode->i_security;  		ret = security_genfs_sid(fsi->state, "selinuxfs", page, @@ -1598,8 +1591,10 @@ static int sel_make_avc_files(struct dentry *dir)  			return -ENOMEM;  		inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); -		if (!inode) +		if (!inode) { +			dput(dentry);  			return -ENOMEM; +		}  		inode->i_fop = files[i].ops;  		inode->i_ino = ++fsi->last_ino; @@ -1644,8 +1639,10 @@ static int sel_make_initcon_files(struct dentry *dir)  			return -ENOMEM;  		inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); -		if (!inode) +		if (!inode) { +			dput(dentry);  			return -ENOMEM; +		}  		inode->i_fop = &sel_initcon_ops;  		inode->i_ino = i|SEL_INITCON_INO_OFFSET; @@ -1745,8 +1742,10 @@ static int sel_make_perm_files(char *objclass, int classvalue,  		rc = -ENOMEM;  		inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); -		if (!inode) +		if (!inode) { +			dput(dentry);  			goto out; +		}  		inode->i_fop = &sel_perm_ops;  		/* i+1 since perm values are 1-indexed */ @@ -1775,8 +1774,10 @@ static int sel_make_class_dir_entries(char *classname, int index,  		return -ENOMEM;  	inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); -	if (!inode) +	if (!inode) { +		dput(dentry);  		return -ENOMEM; +	}  	inode->i_fop = &sel_class_ops;  	inode->i_ino = sel_class_to_ino(index); @@ -1850,8 +1851,10 @@ static int sel_make_policycap(struct selinux_fs_info *fsi)  			return -ENOMEM;  		inode = sel_make_inode(fsi->sb, S_IFREG | 0444); -		if (inode == NULL) +		if (inode == NULL) { +			dput(dentry);  			return -ENOMEM; +		}  		inode->i_fop = &sel_policycap_ops;  		inode->i_ino = iter | SEL_POLICYCAP_INO_OFFSET; @@ -1944,8 +1947,10 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)  	ret = -ENOMEM;  	inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); -	if (!inode) +	if (!inode) { +		dput(dentry);  		goto err; +	}  	inode->i_ino = ++fsi->last_ino;  	isec = (struct inode_security_struct *)inode->i_security; @@ -1996,7 +2001,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)  		goto err;  	return 0;  err: -	printk(KERN_ERR "SELinux: %s:  failed while creating inodes\n", +	pr_err("SELinux: %s:  failed while creating inodes\n",  		__func__);  	selinux_fs_info_free(sb); @@ -2046,7 +2051,7 @@ static int __init init_sel_fs(void)  	selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type);  	if (IS_ERR(selinuxfs_mount)) { -		printk(KERN_ERR "selinuxfs:  could not mount!\n"); +		pr_err("selinuxfs:  could not mount!\n");  		err = PTR_ERR(selinuxfs_mount);  		selinuxfs_mount = NULL;  	} |