aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/selinuxfs.c
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2007-11-26 11:12:53 -0500
committerJames Morris <jmorris@namei.org>2007-12-05 08:24:09 -0500
commitd313f948309ab22797316e789a7ff8fa358176b6 (patch)
tree7a6d4a54ea7448ce53cf23349eb8a64d7fd93151 /security/selinux/selinuxfs.c
parent0955dc03aedfb6a5565445b3f2176255b784cc6a (diff)
SELinux: detect dead booleans
Instead of using f_op to detect dead booleans, check the inode index against the number of booleans and check the dentry name against the boolean name for that index on reads and writes. This prevents incorrect use of a boolean file opened prior to a policy reload while allowing valid use of it as long as it still corresponds to the same boolean in the policy. Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/selinuxfs.c')
-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;