diff options
-rw-r--r-- | security/selinux/selinuxfs.c | 43 |
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 */ |
66 | static struct dentry *bool_dir = NULL; | 66 | static struct dentry *bool_dir = NULL; |
67 | static int bool_num = 0; | 67 | static int bool_num = 0; |
68 | static char **bool_pending_names; | ||
68 | static int *bool_pending_values = NULL; | 69 | static 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); |
860 | out: | 864 | out: |
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 | ||
909 | out: | 922 | out: |
@@ -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; |
1056 | out: | 1073 | out: |
1057 | free_page((unsigned long)page); | 1074 | free_page((unsigned long)page); |
1075 | return ret; | ||
1076 | err: | ||
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; | ||
1064 | err: | ||
1065 | kfree(values); | 1082 | kfree(values); |
1066 | sel_remove_entries(dir); | 1083 | sel_remove_entries(dir); |
1067 | ret = -ENOMEM; | 1084 | ret = -ENOMEM; |