diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 168 | ||||
-rw-r--r-- | net/netlabel/netlabel_kapi.c | 201 |
2 files changed, 270 insertions, 99 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index f3957cfaed42..08144f8fc911 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -819,8 +819,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, | |||
819 | /** | 819 | /** |
820 | * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network | 820 | * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network |
821 | * @doi_def: the DOI definition | 821 | * @doi_def: the DOI definition |
822 | * @host_cat: the category bitmap in host format | 822 | * @secattr: the security attributes |
823 | * @host_cat_len: the length of the host's category bitmap in bytes | ||
824 | * @net_cat: the zero'd out category bitmap in network/CIPSO format | 823 | * @net_cat: the zero'd out category bitmap in network/CIPSO format |
825 | * @net_cat_len: the length of the CIPSO bitmap in bytes | 824 | * @net_cat_len: the length of the CIPSO bitmap in bytes |
826 | * | 825 | * |
@@ -831,61 +830,51 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, | |||
831 | * | 830 | * |
832 | */ | 831 | */ |
833 | static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, | 832 | static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, |
834 | const unsigned char *host_cat, | 833 | const struct netlbl_lsm_secattr *secattr, |
835 | u32 host_cat_len, | ||
836 | unsigned char *net_cat, | 834 | unsigned char *net_cat, |
837 | u32 net_cat_len) | 835 | u32 net_cat_len) |
838 | { | 836 | { |
839 | int host_spot = -1; | 837 | int host_spot = -1; |
840 | u32 net_spot; | 838 | u32 net_spot = CIPSO_V4_INV_CAT; |
841 | u32 net_spot_max = 0; | 839 | u32 net_spot_max = 0; |
842 | u32 host_clen_bits = host_cat_len * 8; | ||
843 | u32 net_clen_bits = net_cat_len * 8; | 840 | u32 net_clen_bits = net_cat_len * 8; |
844 | u32 host_cat_size; | 841 | u32 host_cat_size = 0; |
845 | u32 *host_cat_array; | 842 | u32 *host_cat_array = NULL; |
846 | 843 | ||
847 | switch (doi_def->type) { | 844 | if (doi_def->type == CIPSO_V4_MAP_STD) { |
848 | case CIPSO_V4_MAP_PASS: | ||
849 | net_spot_max = host_cat_len; | ||
850 | while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0) | ||
851 | net_spot_max--; | ||
852 | if (net_spot_max > net_cat_len) | ||
853 | return -EINVAL; | ||
854 | memcpy(net_cat, host_cat, net_spot_max); | ||
855 | return net_spot_max; | ||
856 | case CIPSO_V4_MAP_STD: | ||
857 | host_cat_size = doi_def->map.std->cat.local_size; | 845 | host_cat_size = doi_def->map.std->cat.local_size; |
858 | host_cat_array = doi_def->map.std->cat.local; | 846 | host_cat_array = doi_def->map.std->cat.local; |
859 | for (;;) { | 847 | } |
860 | host_spot = cipso_v4_bitmap_walk(host_cat, | 848 | |
861 | host_clen_bits, | 849 | for (;;) { |
862 | host_spot + 1, | 850 | host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat, |
863 | 1); | 851 | host_spot + 1); |
864 | if (host_spot < 0) | 852 | if (host_spot < 0) |
865 | break; | 853 | break; |
854 | |||
855 | switch (doi_def->type) { | ||
856 | case CIPSO_V4_MAP_PASS: | ||
857 | net_spot = host_spot; | ||
858 | break; | ||
859 | case CIPSO_V4_MAP_STD: | ||
866 | if (host_spot >= host_cat_size) | 860 | if (host_spot >= host_cat_size) |
867 | return -EPERM; | 861 | return -EPERM; |
868 | |||
869 | net_spot = host_cat_array[host_spot]; | 862 | net_spot = host_cat_array[host_spot]; |
870 | if (net_spot >= CIPSO_V4_INV_CAT) | 863 | if (net_spot >= CIPSO_V4_INV_CAT) |
871 | return -EPERM; | 864 | return -EPERM; |
872 | if (net_spot >= net_clen_bits) | 865 | break; |
873 | return -ENOSPC; | ||
874 | cipso_v4_bitmap_setbit(net_cat, net_spot, 1); | ||
875 | |||
876 | if (net_spot > net_spot_max) | ||
877 | net_spot_max = net_spot; | ||
878 | } | 866 | } |
867 | if (net_spot >= net_clen_bits) | ||
868 | return -ENOSPC; | ||
869 | cipso_v4_bitmap_setbit(net_cat, net_spot, 1); | ||
879 | 870 | ||
880 | if (host_spot == -2) | 871 | if (net_spot > net_spot_max) |
881 | return -EFAULT; | 872 | net_spot_max = net_spot; |
882 | |||
883 | if (++net_spot_max % 8) | ||
884 | return net_spot_max / 8 + 1; | ||
885 | return net_spot_max / 8; | ||
886 | } | 873 | } |
887 | 874 | ||
888 | return -EINVAL; | 875 | if (++net_spot_max % 8) |
876 | return net_spot_max / 8 + 1; | ||
877 | return net_spot_max / 8; | ||
889 | } | 878 | } |
890 | 879 | ||
891 | /** | 880 | /** |
@@ -893,66 +882,59 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, | |||
893 | * @doi_def: the DOI definition | 882 | * @doi_def: the DOI definition |
894 | * @net_cat: the category bitmap in network/CIPSO format | 883 | * @net_cat: the category bitmap in network/CIPSO format |
895 | * @net_cat_len: the length of the CIPSO bitmap in bytes | 884 | * @net_cat_len: the length of the CIPSO bitmap in bytes |
896 | * @host_cat: the zero'd out category bitmap in host format | 885 | * @secattr: the security attributes |
897 | * @host_cat_len: the length of the host's category bitmap in bytes | ||
898 | * | 886 | * |
899 | * Description: | 887 | * Description: |
900 | * Perform a label mapping to translate a CIPSO bitmap to the correct local | 888 | * Perform a label mapping to translate a CIPSO bitmap to the correct local |
901 | * MLS category bitmap using the given DOI definition. Returns the minimum | 889 | * MLS category bitmap using the given DOI definition. Returns zero on |
902 | * size in bytes of the host bitmap on success, negative values otherwise. | 890 | * success, negative values on failure. |
903 | * | 891 | * |
904 | */ | 892 | */ |
905 | static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, | 893 | static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, |
906 | const unsigned char *net_cat, | 894 | const unsigned char *net_cat, |
907 | u32 net_cat_len, | 895 | u32 net_cat_len, |
908 | unsigned char *host_cat, | 896 | struct netlbl_lsm_secattr *secattr) |
909 | u32 host_cat_len) | ||
910 | { | 897 | { |
911 | u32 host_spot; | 898 | int ret_val; |
912 | u32 host_spot_max = 0; | ||
913 | int net_spot = -1; | 899 | int net_spot = -1; |
900 | u32 host_spot = CIPSO_V4_INV_CAT; | ||
914 | u32 net_clen_bits = net_cat_len * 8; | 901 | u32 net_clen_bits = net_cat_len * 8; |
915 | u32 host_clen_bits = host_cat_len * 8; | 902 | u32 net_cat_size = 0; |
916 | u32 net_cat_size; | 903 | u32 *net_cat_array = NULL; |
917 | u32 *net_cat_array; | ||
918 | 904 | ||
919 | switch (doi_def->type) { | 905 | if (doi_def->type == CIPSO_V4_MAP_STD) { |
920 | case CIPSO_V4_MAP_PASS: | ||
921 | if (net_cat_len > host_cat_len) | ||
922 | return -EINVAL; | ||
923 | memcpy(host_cat, net_cat, net_cat_len); | ||
924 | return net_cat_len; | ||
925 | case CIPSO_V4_MAP_STD: | ||
926 | net_cat_size = doi_def->map.std->cat.cipso_size; | 906 | net_cat_size = doi_def->map.std->cat.cipso_size; |
927 | net_cat_array = doi_def->map.std->cat.cipso; | 907 | net_cat_array = doi_def->map.std->cat.cipso; |
928 | for (;;) { | 908 | } |
929 | net_spot = cipso_v4_bitmap_walk(net_cat, | ||
930 | net_clen_bits, | ||
931 | net_spot + 1, | ||
932 | 1); | ||
933 | if (net_spot < 0) | ||
934 | break; | ||
935 | if (net_spot >= net_cat_size || | ||
936 | net_cat_array[net_spot] >= CIPSO_V4_INV_CAT) | ||
937 | return -EPERM; | ||
938 | 909 | ||
910 | for (;;) { | ||
911 | net_spot = cipso_v4_bitmap_walk(net_cat, | ||
912 | net_clen_bits, | ||
913 | net_spot + 1, | ||
914 | 1); | ||
915 | if (net_spot < 0) { | ||
916 | if (net_spot == -2) | ||
917 | return -EFAULT; | ||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | switch (doi_def->type) { | ||
922 | case CIPSO_V4_MAP_PASS: | ||
923 | host_spot = net_spot; | ||
924 | break; | ||
925 | case CIPSO_V4_MAP_STD: | ||
926 | if (net_spot >= net_cat_size) | ||
927 | return -EPERM; | ||
939 | host_spot = net_cat_array[net_spot]; | 928 | host_spot = net_cat_array[net_spot]; |
940 | if (host_spot >= CIPSO_V4_INV_CAT) | 929 | if (host_spot >= CIPSO_V4_INV_CAT) |
941 | return -EPERM; | 930 | return -EPERM; |
942 | if (host_spot >= host_clen_bits) | 931 | break; |
943 | return -ENOSPC; | ||
944 | cipso_v4_bitmap_setbit(host_cat, host_spot, 1); | ||
945 | |||
946 | if (host_spot > host_spot_max) | ||
947 | host_spot_max = host_spot; | ||
948 | } | 932 | } |
949 | 933 | ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat, | |
950 | if (net_spot == -2) | 934 | host_spot, |
951 | return -EFAULT; | 935 | GFP_ATOMIC); |
952 | 936 | if (ret_val != 0) | |
953 | if (++host_spot_max % 8) | 937 | return ret_val; |
954 | return host_spot_max / 8 + 1; | ||
955 | return host_spot_max / 8; | ||
956 | } | 938 | } |
957 | 939 | ||
958 | return -EINVAL; | 940 | return -EINVAL; |
@@ -1016,8 +998,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, | |||
1016 | 998 | ||
1017 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { | 999 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { |
1018 | ret_val = cipso_v4_map_cat_rbm_hton(doi_def, | 1000 | ret_val = cipso_v4_map_cat_rbm_hton(doi_def, |
1019 | secattr->mls_cat, | 1001 | secattr, |
1020 | secattr->mls_cat_len, | ||
1021 | &buffer[4], | 1002 | &buffer[4], |
1022 | buffer_len - 4); | 1003 | buffer_len - 4); |
1023 | if (ret_val < 0) | 1004 | if (ret_val < 0) |
@@ -1067,31 +1048,20 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, | |||
1067 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; | 1048 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; |
1068 | 1049 | ||
1069 | if (tag_len > 4) { | 1050 | if (tag_len > 4) { |
1070 | switch (doi_def->type) { | 1051 | secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); |
1071 | case CIPSO_V4_MAP_PASS: | ||
1072 | secattr->mls_cat_len = tag_len - 4; | ||
1073 | break; | ||
1074 | case CIPSO_V4_MAP_STD: | ||
1075 | secattr->mls_cat_len = | ||
1076 | doi_def->map.std->cat.local_size; | ||
1077 | break; | ||
1078 | } | ||
1079 | secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC); | ||
1080 | if (secattr->mls_cat == NULL) | 1052 | if (secattr->mls_cat == NULL) |
1081 | return -ENOMEM; | 1053 | return -ENOMEM; |
1082 | 1054 | ||
1083 | ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, | 1055 | ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, |
1084 | &tag[4], | 1056 | &tag[4], |
1085 | tag_len - 4, | 1057 | tag_len - 4, |
1086 | secattr->mls_cat, | 1058 | secattr); |
1087 | secattr->mls_cat_len); | 1059 | if (ret_val != 0) { |
1088 | if (ret_val < 0) { | 1060 | netlbl_secattr_catmap_free(secattr->mls_cat); |
1089 | kfree(secattr->mls_cat); | ||
1090 | return ret_val; | 1061 | return ret_val; |
1091 | } else if (ret_val > 0) { | ||
1092 | secattr->mls_cat_len = ret_val; | ||
1093 | secattr->flags |= NETLBL_SECATTR_MLS_CAT; | ||
1094 | } | 1062 | } |
1063 | |||
1064 | secattr->flags |= NETLBL_SECATTR_MLS_CAT; | ||
1095 | } | 1065 | } |
1096 | 1066 | ||
1097 | return 0; | 1067 | return 0; |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index b35ebf94918c..e03a3282c551 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -40,6 +40,207 @@ | |||
40 | #include "netlabel_user.h" | 40 | #include "netlabel_user.h" |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * Security Attribute Functions | ||
44 | */ | ||
45 | |||
46 | /** | ||
47 | * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit | ||
48 | * @catmap: the category bitmap | ||
49 | * @offset: the offset to start searching at, in bits | ||
50 | * | ||
51 | * Description: | ||
52 | * This function walks a LSM secattr category bitmap starting at @offset and | ||
53 | * returns the spot of the first set bit or -ENOENT if no bits are set. | ||
54 | * | ||
55 | */ | ||
56 | int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, | ||
57 | u32 offset) | ||
58 | { | ||
59 | struct netlbl_lsm_secattr_catmap *iter = catmap; | ||
60 | u32 node_idx; | ||
61 | u32 node_bit; | ||
62 | NETLBL_CATMAP_MAPTYPE bitmap; | ||
63 | |||
64 | if (offset > iter->startbit) { | ||
65 | while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { | ||
66 | iter = iter->next; | ||
67 | if (iter == NULL) | ||
68 | return -ENOENT; | ||
69 | } | ||
70 | node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; | ||
71 | node_bit = offset - iter->startbit - | ||
72 | (NETLBL_CATMAP_MAPSIZE * node_idx); | ||
73 | } else { | ||
74 | node_idx = 0; | ||
75 | node_bit = 0; | ||
76 | } | ||
77 | bitmap = iter->bitmap[node_idx] >> node_bit; | ||
78 | |||
79 | for (;;) { | ||
80 | if (bitmap != 0) { | ||
81 | while ((bitmap & NETLBL_CATMAP_BIT) == 0) { | ||
82 | bitmap >>= 1; | ||
83 | node_bit++; | ||
84 | } | ||
85 | return iter->startbit + | ||
86 | (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit; | ||
87 | } | ||
88 | if (++node_idx >= NETLBL_CATMAP_MAPCNT) { | ||
89 | if (iter->next != NULL) { | ||
90 | iter = iter->next; | ||
91 | node_idx = 0; | ||
92 | } else | ||
93 | return -ENOENT; | ||
94 | } | ||
95 | bitmap = iter->bitmap[node_idx]; | ||
96 | node_bit = 0; | ||
97 | } | ||
98 | |||
99 | return -ENOENT; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * netlbl_secattr_catmap_walk_rng - Find the end of a string of set bits | ||
104 | * @catmap: the category bitmap | ||
105 | * @offset: the offset to start searching at, in bits | ||
106 | * | ||
107 | * Description: | ||
108 | * This function walks a LSM secattr category bitmap starting at @offset and | ||
109 | * returns the spot of the first cleared bit or -ENOENT if the offset is past | ||
110 | * the end of the bitmap. | ||
111 | * | ||
112 | */ | ||
113 | int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, | ||
114 | u32 offset) | ||
115 | { | ||
116 | struct netlbl_lsm_secattr_catmap *iter = catmap; | ||
117 | u32 node_idx; | ||
118 | u32 node_bit; | ||
119 | NETLBL_CATMAP_MAPTYPE bitmask; | ||
120 | NETLBL_CATMAP_MAPTYPE bitmap; | ||
121 | |||
122 | if (offset > iter->startbit) { | ||
123 | while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { | ||
124 | iter = iter->next; | ||
125 | if (iter == NULL) | ||
126 | return -ENOENT; | ||
127 | } | ||
128 | node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; | ||
129 | node_bit = offset - iter->startbit - | ||
130 | (NETLBL_CATMAP_MAPSIZE * node_idx); | ||
131 | } else { | ||
132 | node_idx = 0; | ||
133 | node_bit = 0; | ||
134 | } | ||
135 | bitmask = NETLBL_CATMAP_BIT << node_bit; | ||
136 | |||
137 | for (;;) { | ||
138 | bitmap = iter->bitmap[node_idx]; | ||
139 | while (bitmask != 0 && (bitmap & bitmask) != 0) { | ||
140 | bitmask <<= 1; | ||
141 | node_bit++; | ||
142 | } | ||
143 | |||
144 | if (bitmask != 0) | ||
145 | return iter->startbit + | ||
146 | (NETLBL_CATMAP_MAPSIZE * node_idx) + | ||
147 | node_bit - 1; | ||
148 | else if (++node_idx >= NETLBL_CATMAP_MAPCNT) { | ||
149 | if (iter->next == NULL) | ||
150 | return iter->startbit + NETLBL_CATMAP_SIZE - 1; | ||
151 | iter = iter->next; | ||
152 | node_idx = 0; | ||
153 | } | ||
154 | bitmask = NETLBL_CATMAP_BIT; | ||
155 | node_bit = 0; | ||
156 | } | ||
157 | |||
158 | return -ENOENT; | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap | ||
163 | * @catmap: the category bitmap | ||
164 | * @bit: the bit to set | ||
165 | * @flags: memory allocation flags | ||
166 | * | ||
167 | * Description: | ||
168 | * Set the bit specified by @bit in @catmap. Returns zero on success, | ||
169 | * negative values on failure. | ||
170 | * | ||
171 | */ | ||
172 | int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap, | ||
173 | u32 bit, | ||
174 | gfp_t flags) | ||
175 | { | ||
176 | struct netlbl_lsm_secattr_catmap *iter = catmap; | ||
177 | u32 node_bit; | ||
178 | u32 node_idx; | ||
179 | |||
180 | while (iter->next != NULL && | ||
181 | bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) | ||
182 | iter = iter->next; | ||
183 | if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) { | ||
184 | iter->next = netlbl_secattr_catmap_alloc(flags); | ||
185 | if (iter->next == NULL) | ||
186 | return -ENOMEM; | ||
187 | iter = iter->next; | ||
188 | iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1); | ||
189 | } | ||
190 | |||
191 | /* gcc always rounds to zero when doing integer division */ | ||
192 | node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE; | ||
193 | node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx); | ||
194 | iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit; | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap | ||
201 | * @catmap: the category bitmap | ||
202 | * @start: the starting bit | ||
203 | * @end: the last bit in the string | ||
204 | * @flags: memory allocation flags | ||
205 | * | ||
206 | * Description: | ||
207 | * Set a range of bits, starting at @start and ending with @end. Returns zero | ||
208 | * on success, negative values on failure. | ||
209 | * | ||
210 | */ | ||
211 | int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, | ||
212 | u32 start, | ||
213 | u32 end, | ||
214 | gfp_t flags) | ||
215 | { | ||
216 | int ret_val = 0; | ||
217 | struct netlbl_lsm_secattr_catmap *iter = catmap; | ||
218 | u32 iter_max_spot; | ||
219 | u32 spot; | ||
220 | |||
221 | /* XXX - This could probably be made a bit faster by combining writes | ||
222 | * to the catmap instead of setting a single bit each time, but for | ||
223 | * right now skipping to the start of the range in the catmap should | ||
224 | * be a nice improvement over calling the individual setbit function | ||
225 | * repeatedly from a loop. */ | ||
226 | |||
227 | while (iter->next != NULL && | ||
228 | start >= (iter->startbit + NETLBL_CATMAP_SIZE)) | ||
229 | iter = iter->next; | ||
230 | iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; | ||
231 | |||
232 | for (spot = start; spot <= end && ret_val == 0; spot++) { | ||
233 | if (spot >= iter_max_spot && iter->next != NULL) { | ||
234 | iter = iter->next; | ||
235 | iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; | ||
236 | } | ||
237 | ret_val = netlbl_secattr_catmap_setbit(iter, spot, GFP_ATOMIC); | ||
238 | } | ||
239 | |||
240 | return ret_val; | ||
241 | } | ||
242 | |||
243 | /* | ||
43 | * LSM Functions | 244 | * LSM Functions |
44 | */ | 245 | */ |
45 | 246 | ||