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.c65
1 files changed, 28 insertions, 37 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index f5f3e6da5da7..2fa483f26113 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -65,6 +65,7 @@ static DEFINE_MUTEX(sel_mutex);
65/* global data for booleans */ 65/* global data for booleans */
66static struct dentry *bool_dir = NULL; 66static struct dentry *bool_dir = NULL;
67static int bool_num = 0; 67static int bool_num = 0;
68static char **bool_pending_names;
68static int *bool_pending_values = NULL; 69static int *bool_pending_values = NULL;
69 70
70/* global data for classes */ 71/* global data for classes */
@@ -832,15 +833,16 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
832 ssize_t length; 833 ssize_t length;
833 ssize_t ret; 834 ssize_t ret;
834 int cur_enforcing; 835 int cur_enforcing;
835 struct inode *inode; 836 struct inode *inode = filep->f_path.dentry->d_inode;
837 unsigned index = inode->i_ino & SEL_INO_MASK;
838 const char *name = filep->f_path.dentry->d_name.name;
836 839
837 mutex_lock(&sel_mutex); 840 mutex_lock(&sel_mutex);
838 841
839 ret = -EFAULT; 842 if (index >= bool_num || strcmp(name, bool_pending_names[index])) {
840 843 ret = -EINVAL;
841 /* check to see if this file has been deleted */
842 if (!filep->f_op)
843 goto out; 844 goto out;
845 }
844 846
845 if (count > PAGE_SIZE) { 847 if (count > PAGE_SIZE) {
846 ret = -EINVAL; 848 ret = -EINVAL;
@@ -851,15 +853,13 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
851 goto out; 853 goto out;
852 } 854 }
853 855
854 inode = filep->f_path.dentry->d_inode; 856 cur_enforcing = security_get_bool_value(index);
855 cur_enforcing = security_get_bool_value(inode->i_ino&SEL_INO_MASK);
856 if (cur_enforcing < 0) { 857 if (cur_enforcing < 0) {
857 ret = cur_enforcing; 858 ret = cur_enforcing;
858 goto out; 859 goto out;
859 } 860 }
860
861 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, 861 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
862 bool_pending_values[inode->i_ino&SEL_INO_MASK]); 862 bool_pending_values[index]);
863 ret = simple_read_from_buffer(buf, count, ppos, page, length); 863 ret = simple_read_from_buffer(buf, count, ppos, page, length);
864out: 864out:
865 mutex_unlock(&sel_mutex); 865 mutex_unlock(&sel_mutex);
@@ -872,9 +872,11 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
872 size_t count, loff_t *ppos) 872 size_t count, loff_t *ppos)
873{ 873{
874 char *page = NULL; 874 char *page = NULL;
875 ssize_t length = -EFAULT; 875 ssize_t length;
876 int new_value; 876 int new_value;
877 struct inode *inode; 877 struct inode *inode = filep->f_path.dentry->d_inode;
878 unsigned index = inode->i_ino & SEL_INO_MASK;
879 const char *name = filep->f_path.dentry->d_name.name;
878 880
879 mutex_lock(&sel_mutex); 881 mutex_lock(&sel_mutex);
880 882
@@ -882,16 +884,19 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
882 if (length) 884 if (length)
883 goto out; 885 goto out;
884 886
885 /* check to see if this file has been deleted */ 887 if (index >= bool_num || strcmp(name, bool_pending_names[index])) {
886 if (!filep->f_op) 888 length = -EINVAL;
887 goto out; 889 goto out;
890 }
888 891
889 if (count >= PAGE_SIZE) { 892 if (count >= PAGE_SIZE) {
890 length = -ENOMEM; 893 length = -ENOMEM;
891 goto out; 894 goto out;
892 } 895 }
896
893 if (*ppos != 0) { 897 if (*ppos != 0) {
894 /* No partial writes. */ 898 /* No partial writes. */
899 length = -EINVAL;
895 goto out; 900 goto out;
896 } 901 }
897 page = (char*)get_zeroed_page(GFP_KERNEL); 902 page = (char*)get_zeroed_page(GFP_KERNEL);
@@ -900,6 +905,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
900 goto out; 905 goto out;
901 } 906 }
902 907
908 length = -EFAULT;
903 if (copy_from_user(page, buf, count)) 909 if (copy_from_user(page, buf, count))
904 goto out; 910 goto out;
905 911
@@ -910,8 +916,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
910 if (new_value) 916 if (new_value)
911 new_value = 1; 917 new_value = 1;
912 918
913 inode = filep->f_path.dentry->d_inode; 919 bool_pending_values[index] = new_value;
914 bool_pending_values[inode->i_ino&SEL_INO_MASK] = new_value;
915 length = count; 920 length = count;
916 921
917out: 922out:
@@ -931,7 +936,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
931 size_t count, loff_t *ppos) 936 size_t count, loff_t *ppos)
932{ 937{
933 char *page = NULL; 938 char *page = NULL;
934 ssize_t length = -EFAULT; 939 ssize_t length;
935 int new_value; 940 int new_value;
936 941
937 mutex_lock(&sel_mutex); 942 mutex_lock(&sel_mutex);
@@ -940,10 +945,6 @@ static ssize_t sel_commit_bools_write(struct file *filep,
940 if (length) 945 if (length)
941 goto out; 946 goto out;
942 947
943 /* check to see if this file has been deleted */
944 if (!filep->f_op)
945 goto out;
946
947 if (count >= PAGE_SIZE) { 948 if (count >= PAGE_SIZE) {
948 length = -ENOMEM; 949 length = -ENOMEM;
949 goto out; 950 goto out;
@@ -958,6 +959,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
958 goto out; 959 goto out;
959 } 960 }
960 961
962 length = -EFAULT;
961 if (copy_from_user(page, buf, count)) 963 if (copy_from_user(page, buf, count))
962 goto out; 964 goto out;
963 965
@@ -982,11 +984,9 @@ static const struct file_operations sel_commit_bools_ops = {
982 .write = sel_commit_bools_write, 984 .write = sel_commit_bools_write,
983}; 985};
984 986
985/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
986static void sel_remove_entries(struct dentry *de) 987static void sel_remove_entries(struct dentry *de)
987{ 988{
988 struct list_head *p, *node; 989 struct list_head *node;
989 struct super_block *sb = de->d_sb;
990 990
991 spin_lock(&dcache_lock); 991 spin_lock(&dcache_lock);
992 node = de->d_subdirs.next; 992 node = de->d_subdirs.next;
@@ -1006,18 +1006,6 @@ static void sel_remove_entries(struct dentry *de)
1006 } 1006 }
1007 1007
1008 spin_unlock(&dcache_lock); 1008 spin_unlock(&dcache_lock);
1009
1010 file_list_lock();
1011 list_for_each(p, &sb->s_files) {
1012 struct file * filp = list_entry(p, struct file, f_u.fu_list);
1013 struct dentry * dentry = filp->f_path.dentry;
1014
1015 if (dentry->d_parent != de) {
1016 continue;
1017 }
1018 filp->f_op = NULL;
1019 }
1020 file_list_unlock();
1021} 1009}
1022 1010
1023#define BOOL_DIR_NAME "booleans" 1011#define BOOL_DIR_NAME "booleans"
@@ -1036,7 +1024,9 @@ static int sel_make_bools(void)
1036 u32 sid; 1024 u32 sid;
1037 1025
1038 /* remove any existing files */ 1026 /* remove any existing files */
1027 kfree(bool_pending_names);
1039 kfree(bool_pending_values); 1028 kfree(bool_pending_values);
1029 bool_pending_names = NULL;
1040 bool_pending_values = NULL; 1030 bool_pending_values = NULL;
1041 1031
1042 sel_remove_entries(dir); 1032 sel_remove_entries(dir);
@@ -1078,16 +1068,17 @@ static int sel_make_bools(void)
1078 d_add(dentry, inode); 1068 d_add(dentry, inode);
1079 } 1069 }
1080 bool_num = num; 1070 bool_num = num;
1071 bool_pending_names = names;
1081 bool_pending_values = values; 1072 bool_pending_values = values;
1082out: 1073out:
1083 free_page((unsigned long)page); 1074 free_page((unsigned long)page);
1075 return ret;
1076err:
1084 if (names) { 1077 if (names) {
1085 for (i = 0; i < num; i++) 1078 for (i = 0; i < num; i++)
1086 kfree(names[i]); 1079 kfree(names[i]);
1087 kfree(names); 1080 kfree(names);
1088 } 1081 }
1089 return ret;
1090err:
1091 kfree(values); 1082 kfree(values);
1092 sel_remove_entries(dir); 1083 sel_remove_entries(dir);
1093 ret = -ENOMEM; 1084 ret = -ENOMEM;