summaryrefslogtreecommitdiffstats
path: root/security/selinux/selinuxfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r--security/selinux/selinuxfs.c65
1 files changed, 28 insertions, 37 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index f5f3e6da5da..2fa483f2611 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -65,6 +65,7 @@ static DEFINE_MUTEX(sel_mutex);
/* global data for booleans */
static struct dentry *bool_dir = NULL;
static int bool_num = 0;
+static char **bool_pending_names;
static int *bool_pending_values = NULL;
/* global data for classes */
@@ -832,15 +833,16 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
ssize_t length;
ssize_t ret;
int cur_enforcing;
- struct inode *inode;
+ struct inode *inode = filep->f_path.dentry->d_inode;
+ unsigned index = inode->i_ino & SEL_INO_MASK;
+ const char *name = filep->f_path.dentry->d_name.name;
mutex_lock(&sel_mutex);
- ret = -EFAULT;
-
- /* check to see if this file has been deleted */
- if (!filep->f_op)
+ if (index >= bool_num || strcmp(name, bool_pending_names[index])) {
+ ret = -EINVAL;
goto out;
+ }
if (count > PAGE_SIZE) {
ret = -EINVAL;
@@ -851,15 +853,13 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
goto out;
}
- inode = filep->f_path.dentry->d_inode;
- cur_enforcing = security_get_bool_value(inode->i_ino&SEL_INO_MASK);
+ cur_enforcing = security_get_bool_value(index);
if (cur_enforcing < 0) {
ret = cur_enforcing;
goto out;
}
-
length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
- bool_pending_values[inode->i_ino&SEL_INO_MASK]);
+ bool_pending_values[index]);
ret = simple_read_from_buffer(buf, count, ppos, page, length);
out:
mutex_unlock(&sel_mutex);
@@ -872,9 +872,11 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
size_t count, loff_t *ppos)
{
char *page = NULL;
- ssize_t length = -EFAULT;
+ ssize_t length;
int new_value;
- struct inode *inode;
+ struct inode *inode = filep->f_path.dentry->d_inode;
+ unsigned index = inode->i_ino & SEL_INO_MASK;
+ const char *name = filep->f_path.dentry->d_name.name;
mutex_lock(&sel_mutex);
@@ -882,16 +884,19 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
if (length)
goto out;
- /* check to see if this file has been deleted */
- if (!filep->f_op)
+ if (index >= bool_num || strcmp(name, bool_pending_names[index])) {
+ length = -EINVAL;
goto out;
+ }
if (count >= PAGE_SIZE) {
length = -ENOMEM;
goto out;
}
+
if (*ppos != 0) {
/* No partial writes. */
+ length = -EINVAL;
goto out;
}
page = (char*)get_zeroed_page(GFP_KERNEL);
@@ -900,6 +905,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
goto out;
}
+ length = -EFAULT;
if (copy_from_user(page, buf, count))
goto out;
@@ -910,8 +916,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
if (new_value)
new_value = 1;
- inode = filep->f_path.dentry->d_inode;
- bool_pending_values[inode->i_ino&SEL_INO_MASK] = new_value;
+ bool_pending_values[index] = new_value;
length = count;
out:
@@ -931,7 +936,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
size_t count, loff_t *ppos)
{
char *page = NULL;
- ssize_t length = -EFAULT;
+ ssize_t length;
int new_value;
mutex_lock(&sel_mutex);
@@ -940,10 +945,6 @@ static ssize_t sel_commit_bools_write(struct file *filep,
if (length)
goto out;
- /* check to see if this file has been deleted */
- if (!filep->f_op)
- goto out;
-
if (count >= PAGE_SIZE) {
length = -ENOMEM;
goto out;
@@ -958,6 +959,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
goto out;
}
+ length = -EFAULT;
if (copy_from_user(page, buf, count))
goto out;
@@ -982,11 +984,9 @@ static const struct file_operations sel_commit_bools_ops = {
.write = sel_commit_bools_write,
};
-/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
static void sel_remove_entries(struct dentry *de)
{
- struct list_head *p, *node;
- struct super_block *sb = de->d_sb;
+ struct list_head *node;
spin_lock(&dcache_lock);
node = de->d_subdirs.next;
@@ -1006,18 +1006,6 @@ static void sel_remove_entries(struct dentry *de)
}
spin_unlock(&dcache_lock);
-
- file_list_lock();
- list_for_each(p, &sb->s_files) {
- struct file * filp = list_entry(p, struct file, f_u.fu_list);
- struct dentry * dentry = filp->f_path.dentry;
-
- if (dentry->d_parent != de) {
- continue;
- }
- filp->f_op = NULL;
- }
- file_list_unlock();
}
#define BOOL_DIR_NAME "booleans"
@@ -1036,7 +1024,9 @@ static int sel_make_bools(void)
u32 sid;
/* remove any existing files */
+ kfree(bool_pending_names);
kfree(bool_pending_values);
+ bool_pending_names = NULL;
bool_pending_values = NULL;
sel_remove_entries(dir);
@@ -1078,16 +1068,17 @@ static int sel_make_bools(void)
d_add(dentry, inode);
}
bool_num = num;
+ bool_pending_names = names;
bool_pending_values = values;
out:
free_page((unsigned long)page);
+ return ret;
+err:
if (names) {
for (i = 0; i < num; i++)
kfree(names[i]);
kfree(names);
}
- return ret;
-err:
kfree(values);
sel_remove_entries(dir);
ret = -ENOMEM;