aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/selinuxfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r--security/selinux/selinuxfs.c112
1 files changed, 50 insertions, 62 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 5eba6664eac0..a4efc966f065 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -15,6 +15,7 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/vmalloc.h> 16#include <linux/vmalloc.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/mutex.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/string.h> 20#include <linux/string.h>
20#include <linux/security.h> 21#include <linux/security.h>
@@ -45,7 +46,7 @@ static int __init checkreqprot_setup(char *str)
45__setup("checkreqprot=", checkreqprot_setup); 46__setup("checkreqprot=", checkreqprot_setup);
46 47
47 48
48static DECLARE_MUTEX(sel_sem); 49static DEFINE_MUTEX(sel_mutex);
49 50
50/* global data for booleans */ 51/* global data for booleans */
51static struct dentry *bool_dir = NULL; 52static struct dentry *bool_dir = NULL;
@@ -238,7 +239,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
238 ssize_t length; 239 ssize_t length;
239 void *data = NULL; 240 void *data = NULL;
240 241
241 down(&sel_sem); 242 mutex_lock(&sel_mutex);
242 243
243 length = task_has_security(current, SECURITY__LOAD_POLICY); 244 length = task_has_security(current, SECURITY__LOAD_POLICY);
244 if (length) 245 if (length)
@@ -273,7 +274,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
273 "policy loaded auid=%u", 274 "policy loaded auid=%u",
274 audit_get_loginuid(current->audit_context)); 275 audit_get_loginuid(current->audit_context));
275out: 276out:
276 up(&sel_sem); 277 mutex_unlock(&sel_mutex);
277 vfree(data); 278 vfree(data);
278 return length; 279 return length;
279} 280}
@@ -720,12 +721,11 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
720{ 721{
721 char *page = NULL; 722 char *page = NULL;
722 ssize_t length; 723 ssize_t length;
723 ssize_t end;
724 ssize_t ret; 724 ssize_t ret;
725 int cur_enforcing; 725 int cur_enforcing;
726 struct inode *inode; 726 struct inode *inode;
727 727
728 down(&sel_sem); 728 mutex_lock(&sel_mutex);
729 729
730 ret = -EFAULT; 730 ret = -EFAULT;
731 731
@@ -751,26 +751,9 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
751 751
752 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, 752 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
753 bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]); 753 bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]);
754 if (length < 0) { 754 ret = simple_read_from_buffer(buf, count, ppos, page, length);
755 ret = length;
756 goto out;
757 }
758
759 if (*ppos >= length) {
760 ret = 0;
761 goto out;
762 }
763 if (count + *ppos > length)
764 count = length - *ppos;
765 end = count + *ppos;
766 if (copy_to_user(buf, (char *) page + *ppos, count)) {
767 ret = -EFAULT;
768 goto out;
769 }
770 *ppos = end;
771 ret = count;
772out: 755out:
773 up(&sel_sem); 756 mutex_unlock(&sel_mutex);
774 if (page) 757 if (page)
775 free_page((unsigned long)page); 758 free_page((unsigned long)page);
776 return ret; 759 return ret;
@@ -784,7 +767,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
784 int new_value; 767 int new_value;
785 struct inode *inode; 768 struct inode *inode;
786 769
787 down(&sel_sem); 770 mutex_lock(&sel_mutex);
788 771
789 length = task_has_security(current, SECURITY__SETBOOL); 772 length = task_has_security(current, SECURITY__SETBOOL);
790 if (length) 773 if (length)
@@ -823,7 +806,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
823 length = count; 806 length = count;
824 807
825out: 808out:
826 up(&sel_sem); 809 mutex_unlock(&sel_mutex);
827 if (page) 810 if (page)
828 free_page((unsigned long) page); 811 free_page((unsigned long) page);
829 return length; 812 return length;
@@ -842,7 +825,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
842 ssize_t length = -EFAULT; 825 ssize_t length = -EFAULT;
843 int new_value; 826 int new_value;
844 827
845 down(&sel_sem); 828 mutex_lock(&sel_mutex);
846 829
847 length = task_has_security(current, SECURITY__SETBOOL); 830 length = task_has_security(current, SECURITY__SETBOOL);
848 if (length) 831 if (length)
@@ -880,7 +863,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
880 length = count; 863 length = count;
881 864
882out: 865out:
883 up(&sel_sem); 866 mutex_unlock(&sel_mutex);
884 if (page) 867 if (page)
885 free_page((unsigned long) page); 868 free_page((unsigned long) page);
886 return length; 869 return length;
@@ -998,7 +981,7 @@ out:
998 return ret; 981 return ret;
999err: 982err:
1000 kfree(values); 983 kfree(values);
1001 d_genocide(dir); 984 sel_remove_bools(dir);
1002 ret = -ENOMEM; 985 ret = -ENOMEM;
1003 goto out; 986 goto out;
1004} 987}
@@ -1179,37 +1162,38 @@ static int sel_make_avc_files(struct dentry *dir)
1179 dentry = d_alloc_name(dir, files[i].name); 1162 dentry = d_alloc_name(dir, files[i].name);
1180 if (!dentry) { 1163 if (!dentry) {
1181 ret = -ENOMEM; 1164 ret = -ENOMEM;
1182 goto err; 1165 goto out;
1183 } 1166 }
1184 1167
1185 inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); 1168 inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode);
1186 if (!inode) { 1169 if (!inode) {
1187 ret = -ENOMEM; 1170 ret = -ENOMEM;
1188 goto err; 1171 goto out;
1189 } 1172 }
1190 inode->i_fop = files[i].ops; 1173 inode->i_fop = files[i].ops;
1191 d_add(dentry, inode); 1174 d_add(dentry, inode);
1192 } 1175 }
1193out: 1176out:
1194 return ret; 1177 return ret;
1195err:
1196 d_genocide(dir);
1197 goto out;
1198} 1178}
1199 1179
1200static int sel_make_dir(struct super_block *sb, struct dentry *dentry) 1180static int sel_make_dir(struct inode *dir, struct dentry *dentry)
1201{ 1181{
1202 int ret = 0; 1182 int ret = 0;
1203 struct inode *inode; 1183 struct inode *inode;
1204 1184
1205 inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); 1185 inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO);
1206 if (!inode) { 1186 if (!inode) {
1207 ret = -ENOMEM; 1187 ret = -ENOMEM;
1208 goto out; 1188 goto out;
1209 } 1189 }
1210 inode->i_op = &simple_dir_inode_operations; 1190 inode->i_op = &simple_dir_inode_operations;
1211 inode->i_fop = &simple_dir_operations; 1191 inode->i_fop = &simple_dir_operations;
1192 /* directory inodes start off with i_nlink == 2 (for "." entry) */
1193 inode->i_nlink++;
1212 d_add(dentry, inode); 1194 d_add(dentry, inode);
1195 /* bump link count on parent directory, too */
1196 dir->i_nlink++;
1213out: 1197out:
1214 return ret; 1198 return ret;
1215} 1199}
@@ -1218,7 +1202,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1218{ 1202{
1219 int ret; 1203 int ret;
1220 struct dentry *dentry; 1204 struct dentry *dentry;
1221 struct inode *inode; 1205 struct inode *inode, *root_inode;
1222 struct inode_security_struct *isec; 1206 struct inode_security_struct *isec;
1223 1207
1224 static struct tree_descr selinux_files[] = { 1208 static struct tree_descr selinux_files[] = {
@@ -1239,30 +1223,33 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1239 }; 1223 };
1240 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); 1224 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
1241 if (ret) 1225 if (ret)
1242 return ret; 1226 goto err;
1227
1228 root_inode = sb->s_root->d_inode;
1243 1229
1244 dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); 1230 dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME);
1245 if (!dentry) 1231 if (!dentry) {
1246 return -ENOMEM; 1232 ret = -ENOMEM;
1233 goto err;
1234 }
1247 1235
1248 inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); 1236 ret = sel_make_dir(root_inode, dentry);
1249 if (!inode)
1250 goto out;
1251 inode->i_op = &simple_dir_inode_operations;
1252 inode->i_fop = &simple_dir_operations;
1253 d_add(dentry, inode);
1254 bool_dir = dentry;
1255 ret = sel_make_bools();
1256 if (ret) 1237 if (ret)
1257 goto out; 1238 goto err;
1239
1240 bool_dir = dentry;
1258 1241
1259 dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); 1242 dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
1260 if (!dentry) 1243 if (!dentry) {
1261 return -ENOMEM; 1244 ret = -ENOMEM;
1245 goto err;
1246 }
1262 1247
1263 inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); 1248 inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
1264 if (!inode) 1249 if (!inode) {
1265 goto out; 1250 ret = -ENOMEM;
1251 goto err;
1252 }
1266 isec = (struct inode_security_struct*)inode->i_security; 1253 isec = (struct inode_security_struct*)inode->i_security;
1267 isec->sid = SECINITSID_DEVNULL; 1254 isec->sid = SECINITSID_DEVNULL;
1268 isec->sclass = SECCLASS_CHR_FILE; 1255 isec->sclass = SECCLASS_CHR_FILE;
@@ -1273,22 +1260,23 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1273 selinux_null = dentry; 1260 selinux_null = dentry;
1274 1261
1275 dentry = d_alloc_name(sb->s_root, "avc"); 1262 dentry = d_alloc_name(sb->s_root, "avc");
1276 if (!dentry) 1263 if (!dentry) {
1277 return -ENOMEM; 1264 ret = -ENOMEM;
1265 goto err;
1266 }
1278 1267
1279 ret = sel_make_dir(sb, dentry); 1268 ret = sel_make_dir(root_inode, dentry);
1280 if (ret) 1269 if (ret)
1281 goto out; 1270 goto err;
1282 1271
1283 ret = sel_make_avc_files(dentry); 1272 ret = sel_make_avc_files(dentry);
1284 if (ret) 1273 if (ret)
1285 goto out; 1274 goto err;
1286
1287 return 0;
1288out: 1275out:
1289 dput(dentry); 1276 return ret;
1277err:
1290 printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__); 1278 printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
1291 return -ENOMEM; 1279 goto out;
1292} 1280}
1293 1281
1294static struct super_block *sel_get_sb(struct file_system_type *fs_type, 1282static struct super_block *sel_get_sb(struct file_system_type *fs_type,