aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/selinux/selinuxfs.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index ac6fe99bd32c..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,11 +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])) {
843 ret = -EINVAL;
844 goto out;
845 }
840 846
841 if (count > PAGE_SIZE) { 847 if (count > PAGE_SIZE) {
842 ret = -EINVAL; 848 ret = -EINVAL;
@@ -847,15 +853,13 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
847 goto out; 853 goto out;
848 } 854 }
849 855
850 inode = filep->f_path.dentry->d_inode; 856 cur_enforcing = security_get_bool_value(index);
851 cur_enforcing = security_get_bool_value(inode->i_ino&SEL_INO_MASK);
852 if (cur_enforcing < 0) { 857 if (cur_enforcing < 0) {
853 ret = cur_enforcing; 858 ret = cur_enforcing;
854 goto out; 859 goto out;
855 } 860 }
856
857 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, 861 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
858 bool_pending_values[inode->i_ino&SEL_INO_MASK]); 862 bool_pending_values[index]);
859 ret = simple_read_from_buffer(buf, count, ppos, page, length); 863 ret = simple_read_from_buffer(buf, count, ppos, page, length);
860out: 864out:
861 mutex_unlock(&sel_mutex); 865 mutex_unlock(&sel_mutex);
@@ -868,9 +872,11 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
868 size_t count, loff_t *ppos) 872 size_t count, loff_t *ppos)
869{ 873{
870 char *page = NULL; 874 char *page = NULL;
871 ssize_t length = -EFAULT; 875 ssize_t length;
872 int new_value; 876 int new_value;
873 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;
874 880
875 mutex_lock(&sel_mutex); 881 mutex_lock(&sel_mutex);
876 882
@@ -878,12 +884,19 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
878 if (length) 884 if (length)
879 goto out; 885 goto out;
880 886
887 if (index >= bool_num || strcmp(name, bool_pending_names[index])) {
888 length = -EINVAL;
889 goto out;
890 }
891
881 if (count >= PAGE_SIZE) { 892 if (count >= PAGE_SIZE) {
882 length = -ENOMEM; 893 length = -ENOMEM;
883 goto out; 894 goto out;
884 } 895 }
896
885 if (*ppos != 0) { 897 if (*ppos != 0) {
886 /* No partial writes. */ 898 /* No partial writes. */
899 length = -EINVAL;
887 goto out; 900 goto out;
888 } 901 }
889 page = (char*)get_zeroed_page(GFP_KERNEL); 902 page = (char*)get_zeroed_page(GFP_KERNEL);
@@ -892,6 +905,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
892 goto out; 905 goto out;
893 } 906 }
894 907
908 length = -EFAULT;
895 if (copy_from_user(page, buf, count)) 909 if (copy_from_user(page, buf, count))
896 goto out; 910 goto out;
897 911
@@ -902,8 +916,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
902 if (new_value) 916 if (new_value)
903 new_value = 1; 917 new_value = 1;
904 918
905 inode = filep->f_path.dentry->d_inode; 919 bool_pending_values[index] = new_value;
906 bool_pending_values[inode->i_ino&SEL_INO_MASK] = new_value;
907 length = count; 920 length = count;
908 921
909out: 922out:
@@ -923,7 +936,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
923 size_t count, loff_t *ppos) 936 size_t count, loff_t *ppos)
924{ 937{
925 char *page = NULL; 938 char *page = NULL;
926 ssize_t length = -EFAULT; 939 ssize_t length;
927 int new_value; 940 int new_value;
928 941
929 mutex_lock(&sel_mutex); 942 mutex_lock(&sel_mutex);
@@ -946,6 +959,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
946 goto out; 959 goto out;
947 } 960 }
948 961
962 length = -EFAULT;
949 if (copy_from_user(page, buf, count)) 963 if (copy_from_user(page, buf, count))
950 goto out; 964 goto out;
951 965
@@ -1010,7 +1024,9 @@ static int sel_make_bools(void)
1010 u32 sid; 1024 u32 sid;
1011 1025
1012 /* remove any existing files */ 1026 /* remove any existing files */
1027 kfree(bool_pending_names);
1013 kfree(bool_pending_values); 1028 kfree(bool_pending_values);
1029 bool_pending_names = NULL;
1014 bool_pending_values = NULL; 1030 bool_pending_values = NULL;
1015 1031
1016 sel_remove_entries(dir); 1032 sel_remove_entries(dir);
@@ -1052,16 +1068,17 @@ static int sel_make_bools(void)
1052 d_add(dentry, inode); 1068 d_add(dentry, inode);
1053 } 1069 }
1054 bool_num = num; 1070 bool_num = num;
1071 bool_pending_names = names;
1055 bool_pending_values = values; 1072 bool_pending_values = values;
1056out: 1073out:
1057 free_page((unsigned long)page); 1074 free_page((unsigned long)page);
1075 return ret;
1076err:
1058 if (names) { 1077 if (names) {
1059 for (i = 0; i < num; i++) 1078 for (i = 0; i < num; i++)
1060 kfree(names[i]); 1079 kfree(names[i]);
1061 kfree(names); 1080 kfree(names);
1062 } 1081 }
1063 return ret;
1064err:
1065 kfree(values); 1082 kfree(values);
1066 sel_remove_entries(dir); 1083 sel_remove_entries(dir);
1067 ret = -ENOMEM; 1084 ret = -ENOMEM;