aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/cipso_ipv4.c168
-rw-r--r--net/netlabel/netlabel_kapi.c201
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 */
833static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, 832static 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 */
905static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, 893static 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 */
56int 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 */
113int 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 */
172int 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 */
211int 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