diff options
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r-- | security/selinux/selinuxfs.c | 65 |
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 */ |
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,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); |
864 | out: | 864 | out: |
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 | ||
917 | out: | 922 | out: |
@@ -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 */ | ||
986 | static void sel_remove_entries(struct dentry *de) | 987 | static 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; |
1082 | out: | 1073 | out: |
1083 | free_page((unsigned long)page); | 1074 | free_page((unsigned long)page); |
1075 | return ret; | ||
1076 | err: | ||
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; | ||
1090 | err: | ||
1091 | kfree(values); | 1082 | kfree(values); |
1092 | sel_remove_entries(dir); | 1083 | sel_remove_entries(dir); |
1093 | ret = -ENOMEM; | 1084 | ret = -ENOMEM; |