aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2006-11-29 13:18:18 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:36 -0500
commit02752760359db6b00a3ffb1acfc13ef8d9eb1e3f (patch)
tree796cd65fd4cd732b295e61dac194efbf36b78842 /net
parentef91fd522ba3c88d9c68261c243567bc4c5a8f55 (diff)
NetLabel: convert to an extensibile/sparse category bitmap
The original NetLabel category bitmap was a straight char bitmap which worked fine for the initial release as it only supported 240 bits due to limitations in the CIPSO restricted bitmap tag (tag type 0x01). This patch converts that straight char bitmap into an extensibile/sparse bitmap in order to lay the foundation for other CIPSO tag types and protocols. This patch also has a nice side effect in that all of the security attributes passed by NetLabel into the LSM are now in a format which is in the host's native byte/bit ordering which makes the LSM specific code much simpler; look at the changes in security/selinux/ss/ebitmap.c as an example. Signed-off-by: Paul Moore <paul.moore@hp.com> Signed-off-by: James Morris <jmorris@namei.org>
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