aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/cipso_ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r--net/ipv4/cipso_ipv4.c813
1 files changed, 649 insertions, 164 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 6460233407c7..60aafb4a8adf 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -319,6 +319,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
319 entry->activity += 1; 319 entry->activity += 1;
320 atomic_inc(&entry->lsm_data->refcount); 320 atomic_inc(&entry->lsm_data->refcount);
321 secattr->cache = entry->lsm_data; 321 secattr->cache = entry->lsm_data;
322 secattr->flags |= NETLBL_SECATTR_CACHE;
322 if (prev_entry == NULL) { 323 if (prev_entry == NULL) {
323 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 324 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
324 return 0; 325 return 0;
@@ -377,12 +378,11 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
377 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 378 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
378 if (entry == NULL) 379 if (entry == NULL)
379 return -ENOMEM; 380 return -ENOMEM;
380 entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC); 381 entry->key = kmemdup(cipso_ptr, cipso_ptr_len, GFP_ATOMIC);
381 if (entry->key == NULL) { 382 if (entry->key == NULL) {
382 ret_val = -ENOMEM; 383 ret_val = -ENOMEM;
383 goto cache_add_failure; 384 goto cache_add_failure;
384 } 385 }
385 memcpy(entry->key, cipso_ptr, cipso_ptr_len);
386 entry->key_len = cipso_ptr_len; 386 entry->key_len = cipso_ptr_len;
387 entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); 387 entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
388 atomic_inc(&secattr->cache->refcount); 388 atomic_inc(&secattr->cache->refcount);
@@ -447,8 +447,30 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
447 */ 447 */
448int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) 448int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
449{ 449{
450 u32 iter;
451
450 if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN) 452 if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
451 return -EINVAL; 453 return -EINVAL;
454 for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {
455 switch (doi_def->tags[iter]) {
456 case CIPSO_V4_TAG_RBITMAP:
457 break;
458 case CIPSO_V4_TAG_RANGE:
459 if (doi_def->type != CIPSO_V4_MAP_PASS)
460 return -EINVAL;
461 break;
462 case CIPSO_V4_TAG_INVALID:
463 if (iter == 0)
464 return -EINVAL;
465 break;
466 case CIPSO_V4_TAG_ENUM:
467 if (doi_def->type != CIPSO_V4_MAP_PASS)
468 return -EINVAL;
469 break;
470 default:
471 return -EINVAL;
472 }
473 }
452 474
453 doi_def->valid = 1; 475 doi_def->valid = 1;
454 INIT_RCU_HEAD(&doi_def->rcu); 476 INIT_RCU_HEAD(&doi_def->rcu);
@@ -805,8 +827,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
805/** 827/**
806 * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network 828 * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
807 * @doi_def: the DOI definition 829 * @doi_def: the DOI definition
808 * @host_cat: the category bitmap in host format 830 * @secattr: the security attributes
809 * @host_cat_len: the length of the host's category bitmap in bytes
810 * @net_cat: the zero'd out category bitmap in network/CIPSO format 831 * @net_cat: the zero'd out category bitmap in network/CIPSO format
811 * @net_cat_len: the length of the CIPSO bitmap in bytes 832 * @net_cat_len: the length of the CIPSO bitmap in bytes
812 * 833 *
@@ -817,59 +838,51 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
817 * 838 *
818 */ 839 */
819static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, 840static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
820 const unsigned char *host_cat, 841 const struct netlbl_lsm_secattr *secattr,
821 u32 host_cat_len,
822 unsigned char *net_cat, 842 unsigned char *net_cat,
823 u32 net_cat_len) 843 u32 net_cat_len)
824{ 844{
825 int host_spot = -1; 845 int host_spot = -1;
826 u32 net_spot; 846 u32 net_spot = CIPSO_V4_INV_CAT;
827 u32 net_spot_max = 0; 847 u32 net_spot_max = 0;
828 u32 host_clen_bits = host_cat_len * 8;
829 u32 net_clen_bits = net_cat_len * 8; 848 u32 net_clen_bits = net_cat_len * 8;
830 u32 host_cat_size; 849 u32 host_cat_size = 0;
831 u32 *host_cat_array; 850 u32 *host_cat_array = NULL;
832 851
833 switch (doi_def->type) { 852 if (doi_def->type == CIPSO_V4_MAP_STD) {
834 case CIPSO_V4_MAP_PASS:
835 net_spot_max = host_cat_len;
836 while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0)
837 net_spot_max--;
838 if (net_spot_max > net_cat_len)
839 return -EINVAL;
840 memcpy(net_cat, host_cat, net_spot_max);
841 return net_spot_max;
842 case CIPSO_V4_MAP_STD:
843 host_cat_size = doi_def->map.std->cat.local_size; 853 host_cat_size = doi_def->map.std->cat.local_size;
844 host_cat_array = doi_def->map.std->cat.local; 854 host_cat_array = doi_def->map.std->cat.local;
845 for (;;) { 855 }
846 host_spot = cipso_v4_bitmap_walk(host_cat, 856
847 host_clen_bits, 857 for (;;) {
848 host_spot + 1, 858 host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat,
849 1); 859 host_spot + 1);
850 if (host_spot < 0) 860 if (host_spot < 0)
851 break; 861 break;
862
863 switch (doi_def->type) {
864 case CIPSO_V4_MAP_PASS:
865 net_spot = host_spot;
866 break;
867 case CIPSO_V4_MAP_STD:
852 if (host_spot >= host_cat_size) 868 if (host_spot >= host_cat_size)
853 return -EPERM; 869 return -EPERM;
854
855 net_spot = host_cat_array[host_spot]; 870 net_spot = host_cat_array[host_spot];
856 if (net_spot >= net_clen_bits) 871 if (net_spot >= CIPSO_V4_INV_CAT)
857 return -ENOSPC; 872 return -EPERM;
858 cipso_v4_bitmap_setbit(net_cat, net_spot, 1); 873 break;
859
860 if (net_spot > net_spot_max)
861 net_spot_max = net_spot;
862 } 874 }
875 if (net_spot >= net_clen_bits)
876 return -ENOSPC;
877 cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
863 878
864 if (host_spot == -2) 879 if (net_spot > net_spot_max)
865 return -EFAULT; 880 net_spot_max = net_spot;
866
867 if (++net_spot_max % 8)
868 return net_spot_max / 8 + 1;
869 return net_spot_max / 8;
870 } 881 }
871 882
872 return -EINVAL; 883 if (++net_spot_max % 8)
884 return net_spot_max / 8 + 1;
885 return net_spot_max / 8;
873} 886}
874 887
875/** 888/**
@@ -877,102 +890,333 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
877 * @doi_def: the DOI definition 890 * @doi_def: the DOI definition
878 * @net_cat: the category bitmap in network/CIPSO format 891 * @net_cat: the category bitmap in network/CIPSO format
879 * @net_cat_len: the length of the CIPSO bitmap in bytes 892 * @net_cat_len: the length of the CIPSO bitmap in bytes
880 * @host_cat: the zero'd out category bitmap in host format 893 * @secattr: the security attributes
881 * @host_cat_len: the length of the host's category bitmap in bytes
882 * 894 *
883 * Description: 895 * Description:
884 * Perform a label mapping to translate a CIPSO bitmap to the correct local 896 * Perform a label mapping to translate a CIPSO bitmap to the correct local
885 * MLS category bitmap using the given DOI definition. Returns the minimum 897 * MLS category bitmap using the given DOI definition. Returns zero on
886 * size in bytes of the host bitmap on success, negative values otherwise. 898 * success, negative values on failure.
887 * 899 *
888 */ 900 */
889static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, 901static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
890 const unsigned char *net_cat, 902 const unsigned char *net_cat,
891 u32 net_cat_len, 903 u32 net_cat_len,
892 unsigned char *host_cat, 904 struct netlbl_lsm_secattr *secattr)
893 u32 host_cat_len)
894{ 905{
895 u32 host_spot; 906 int ret_val;
896 u32 host_spot_max = 0;
897 int net_spot = -1; 907 int net_spot = -1;
908 u32 host_spot = CIPSO_V4_INV_CAT;
898 u32 net_clen_bits = net_cat_len * 8; 909 u32 net_clen_bits = net_cat_len * 8;
899 u32 host_clen_bits = host_cat_len * 8; 910 u32 net_cat_size = 0;
900 u32 net_cat_size; 911 u32 *net_cat_array = NULL;
901 u32 *net_cat_array;
902 912
903 switch (doi_def->type) { 913 if (doi_def->type == CIPSO_V4_MAP_STD) {
904 case CIPSO_V4_MAP_PASS:
905 if (net_cat_len > host_cat_len)
906 return -EINVAL;
907 memcpy(host_cat, net_cat, net_cat_len);
908 return net_cat_len;
909 case CIPSO_V4_MAP_STD:
910 net_cat_size = doi_def->map.std->cat.cipso_size; 914 net_cat_size = doi_def->map.std->cat.cipso_size;
911 net_cat_array = doi_def->map.std->cat.cipso; 915 net_cat_array = doi_def->map.std->cat.cipso;
912 for (;;) { 916 }
913 net_spot = cipso_v4_bitmap_walk(net_cat,
914 net_clen_bits,
915 net_spot + 1,
916 1);
917 if (net_spot < 0)
918 break;
919 if (net_spot >= net_cat_size ||
920 net_cat_array[net_spot] >= CIPSO_V4_INV_CAT)
921 return -EPERM;
922 917
923 host_spot = net_cat_array[net_spot]; 918 for (;;) {
924 if (host_spot >= host_clen_bits) 919 net_spot = cipso_v4_bitmap_walk(net_cat,
925 return -ENOSPC; 920 net_clen_bits,
926 cipso_v4_bitmap_setbit(host_cat, host_spot, 1); 921 net_spot + 1,
922 1);
923 if (net_spot < 0) {
924 if (net_spot == -2)
925 return -EFAULT;
926 return 0;
927 }
927 928
928 if (host_spot > host_spot_max) 929 switch (doi_def->type) {
929 host_spot_max = host_spot; 930 case CIPSO_V4_MAP_PASS:
931 host_spot = net_spot;
932 break;
933 case CIPSO_V4_MAP_STD:
934 if (net_spot >= net_cat_size)
935 return -EPERM;
936 host_spot = net_cat_array[net_spot];
937 if (host_spot >= CIPSO_V4_INV_CAT)
938 return -EPERM;
939 break;
930 } 940 }
941 ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
942 host_spot,
943 GFP_ATOMIC);
944 if (ret_val != 0)
945 return ret_val;
946 }
947
948 return -EINVAL;
949}
950
951/**
952 * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid
953 * @doi_def: the DOI definition
954 * @enumcat: category list
955 * @enumcat_len: length of the category list in bytes
956 *
957 * Description:
958 * Checks the given categories against the given DOI definition and returns a
959 * negative value if any of the categories do not have a valid mapping and a
960 * zero value if all of the categories are valid.
961 *
962 */
963static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def,
964 const unsigned char *enumcat,
965 u32 enumcat_len)
966{
967 u16 cat;
968 int cat_prev = -1;
969 u32 iter;
970
971 if (doi_def->type != CIPSO_V4_MAP_PASS || enumcat_len & 0x01)
972 return -EFAULT;
973
974 for (iter = 0; iter < enumcat_len; iter += 2) {
975 cat = ntohs(*((__be16 *)&enumcat[iter]));
976 if (cat <= cat_prev)
977 return -EFAULT;
978 cat_prev = cat;
979 }
980
981 return 0;
982}
983
984/**
985 * cipso_v4_map_cat_enum_hton - Perform a category mapping from host to network
986 * @doi_def: the DOI definition
987 * @secattr: the security attributes
988 * @net_cat: the zero'd out category list in network/CIPSO format
989 * @net_cat_len: the length of the CIPSO category list in bytes
990 *
991 * Description:
992 * Perform a label mapping to translate a local MLS category bitmap to the
993 * correct CIPSO category list using the given DOI definition. Returns the
994 * size in bytes of the network category bitmap on success, negative values
995 * otherwise.
996 *
997 */
998static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def,
999 const struct netlbl_lsm_secattr *secattr,
1000 unsigned char *net_cat,
1001 u32 net_cat_len)
1002{
1003 int cat = -1;
1004 u32 cat_iter = 0;
1005
1006 for (;;) {
1007 cat = netlbl_secattr_catmap_walk(secattr->mls_cat, cat + 1);
1008 if (cat < 0)
1009 break;
1010 if ((cat_iter + 2) > net_cat_len)
1011 return -ENOSPC;
1012
1013 *((__be16 *)&net_cat[cat_iter]) = htons(cat);
1014 cat_iter += 2;
1015 }
1016
1017 return cat_iter;
1018}
1019
1020/**
1021 * cipso_v4_map_cat_enum_ntoh - Perform a category mapping from network to host
1022 * @doi_def: the DOI definition
1023 * @net_cat: the category list in network/CIPSO format
1024 * @net_cat_len: the length of the CIPSO bitmap in bytes
1025 * @secattr: the security attributes
1026 *
1027 * Description:
1028 * Perform a label mapping to translate a CIPSO category list to the correct
1029 * local MLS category bitmap using the given DOI definition. Returns zero on
1030 * success, negative values on failure.
1031 *
1032 */
1033static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
1034 const unsigned char *net_cat,
1035 u32 net_cat_len,
1036 struct netlbl_lsm_secattr *secattr)
1037{
1038 int ret_val;
1039 u32 iter;
1040
1041 for (iter = 0; iter < net_cat_len; iter += 2) {
1042 ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
1043 ntohs(*((__be16 *)&net_cat[iter])),
1044 GFP_ATOMIC);
1045 if (ret_val != 0)
1046 return ret_val;
1047 }
1048
1049 return 0;
1050}
1051
1052/**
1053 * cipso_v4_map_cat_rng_valid - Checks to see if the categories are valid
1054 * @doi_def: the DOI definition
1055 * @rngcat: category list
1056 * @rngcat_len: length of the category list in bytes
1057 *
1058 * Description:
1059 * Checks the given categories against the given DOI definition and returns a
1060 * negative value if any of the categories do not have a valid mapping and a
1061 * zero value if all of the categories are valid.
1062 *
1063 */
1064static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def,
1065 const unsigned char *rngcat,
1066 u32 rngcat_len)
1067{
1068 u16 cat_high;
1069 u16 cat_low;
1070 u32 cat_prev = CIPSO_V4_MAX_REM_CATS + 1;
1071 u32 iter;
931 1072
932 if (net_spot == -2) 1073 if (doi_def->type != CIPSO_V4_MAP_PASS || rngcat_len & 0x01)
1074 return -EFAULT;
1075
1076 for (iter = 0; iter < rngcat_len; iter += 4) {
1077 cat_high = ntohs(*((__be16 *)&rngcat[iter]));
1078 if ((iter + 4) <= rngcat_len)
1079 cat_low = ntohs(*((__be16 *)&rngcat[iter + 2]));
1080 else
1081 cat_low = 0;
1082
1083 if (cat_high > cat_prev)
933 return -EFAULT; 1084 return -EFAULT;
934 1085
935 if (++host_spot_max % 8) 1086 cat_prev = cat_low;
936 return host_spot_max / 8 + 1;
937 return host_spot_max / 8;
938 } 1087 }
939 1088
940 return -EINVAL; 1089 return 0;
1090}
1091
1092/**
1093 * cipso_v4_map_cat_rng_hton - Perform a category mapping from host to network
1094 * @doi_def: the DOI definition
1095 * @secattr: the security attributes
1096 * @net_cat: the zero'd out category list in network/CIPSO format
1097 * @net_cat_len: the length of the CIPSO category list in bytes
1098 *
1099 * Description:
1100 * Perform a label mapping to translate a local MLS category bitmap to the
1101 * correct CIPSO category list using the given DOI definition. Returns the
1102 * size in bytes of the network category bitmap on success, negative values
1103 * otherwise.
1104 *
1105 */
1106static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
1107 const struct netlbl_lsm_secattr *secattr,
1108 unsigned char *net_cat,
1109 u32 net_cat_len)
1110{
1111 /* The constant '16' is not random, it is the maximum number of
1112 * high/low category range pairs as permitted by the CIPSO draft based
1113 * on a maximum IPv4 header length of 60 bytes - the BUG_ON() assertion
1114 * does a sanity check to make sure we don't overflow the array. */
1115 int iter = -1;
1116 u16 array[16];
1117 u32 array_cnt = 0;
1118 u32 cat_size = 0;
1119
1120 BUG_ON(net_cat_len > 30);
1121
1122 for (;;) {
1123 iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1);
1124 if (iter < 0)
1125 break;
1126 cat_size += (iter == 0 ? 0 : sizeof(u16));
1127 if (cat_size > net_cat_len)
1128 return -ENOSPC;
1129 array[array_cnt++] = iter;
1130
1131 iter = netlbl_secattr_catmap_walk_rng(secattr->mls_cat, iter);
1132 if (iter < 0)
1133 return -EFAULT;
1134 cat_size += sizeof(u16);
1135 if (cat_size > net_cat_len)
1136 return -ENOSPC;
1137 array[array_cnt++] = iter;
1138 }
1139
1140 for (iter = 0; array_cnt > 0;) {
1141 *((__be16 *)&net_cat[iter]) = htons(array[--array_cnt]);
1142 iter += 2;
1143 array_cnt--;
1144 if (array[array_cnt] != 0) {
1145 *((__be16 *)&net_cat[iter]) = htons(array[array_cnt]);
1146 iter += 2;
1147 }
1148 }
1149
1150 return cat_size;
1151}
1152
1153/**
1154 * cipso_v4_map_cat_rng_ntoh - Perform a category mapping from network to host
1155 * @doi_def: the DOI definition
1156 * @net_cat: the category list in network/CIPSO format
1157 * @net_cat_len: the length of the CIPSO bitmap in bytes
1158 * @secattr: the security attributes
1159 *
1160 * Description:
1161 * Perform a label mapping to translate a CIPSO category list to the correct
1162 * local MLS category bitmap using the given DOI definition. Returns zero on
1163 * success, negative values on failure.
1164 *
1165 */
1166static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
1167 const unsigned char *net_cat,
1168 u32 net_cat_len,
1169 struct netlbl_lsm_secattr *secattr)
1170{
1171 int ret_val;
1172 u32 net_iter;
1173 u16 cat_low;
1174 u16 cat_high;
1175
1176 for(net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
1177 cat_high = ntohs(*((__be16 *)&net_cat[net_iter]));
1178 if ((net_iter + 4) <= net_cat_len)
1179 cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2]));
1180 else
1181 cat_low = 0;
1182
1183 ret_val = netlbl_secattr_catmap_setrng(secattr->mls_cat,
1184 cat_low,
1185 cat_high,
1186 GFP_ATOMIC);
1187 if (ret_val != 0)
1188 return ret_val;
1189 }
1190
1191 return 0;
941} 1192}
942 1193
943/* 1194/*
944 * Protocol Handling Functions 1195 * Protocol Handling Functions
945 */ 1196 */
946 1197
1198#define CIPSO_V4_OPT_LEN_MAX 40
947#define CIPSO_V4_HDR_LEN 6 1199#define CIPSO_V4_HDR_LEN 6
948 1200
949/** 1201/**
950 * cipso_v4_gentag_hdr - Generate a CIPSO option header 1202 * cipso_v4_gentag_hdr - Generate a CIPSO option header
951 * @doi_def: the DOI definition 1203 * @doi_def: the DOI definition
952 * @len: the total tag length in bytes 1204 * @len: the total tag length in bytes, not including this header
953 * @buf: the CIPSO option buffer 1205 * @buf: the CIPSO option buffer
954 * 1206 *
955 * Description: 1207 * Description:
956 * Write a CIPSO header into the beginning of @buffer. Return zero on success, 1208 * Write a CIPSO header into the beginning of @buffer.
957 * negative values on failure.
958 * 1209 *
959 */ 1210 */
960static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, 1211static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
961 u32 len, 1212 unsigned char *buf,
962 unsigned char *buf) 1213 u32 len)
963{ 1214{
964 if (CIPSO_V4_HDR_LEN + len > 40)
965 return -ENOSPC;
966
967 buf[0] = IPOPT_CIPSO; 1215 buf[0] = IPOPT_CIPSO;
968 buf[1] = CIPSO_V4_HDR_LEN + len; 1216 buf[1] = CIPSO_V4_HDR_LEN + len;
969 *(u32 *)&buf[2] = htonl(doi_def->doi); 1217 *(__be32 *)&buf[2] = htonl(doi_def->doi);
970
971 return 0;
972} 1218}
973 1219
974#define CIPSO_V4_TAG1_CAT_LEN 30
975
976/** 1220/**
977 * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) 1221 * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
978 * @doi_def: the DOI definition 1222 * @doi_def: the DOI definition
@@ -983,83 +1227,249 @@ static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
983 * Description: 1227 * Description:
984 * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The 1228 * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The
985 * actual buffer length may be larger than the indicated size due to 1229 * actual buffer length may be larger than the indicated size due to
986 * translation between host and network category bitmaps. Returns zero on 1230 * translation between host and network category bitmaps. Returns the size of
987 * success, negative values on failure. 1231 * the tag on success, negative values on failure.
988 * 1232 *
989 */ 1233 */
990static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, 1234static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
991 const struct netlbl_lsm_secattr *secattr, 1235 const struct netlbl_lsm_secattr *secattr,
992 unsigned char **buffer, 1236 unsigned char *buffer,
993 u32 *buffer_len) 1237 u32 buffer_len)
994{ 1238{
995 int ret_val = -EPERM; 1239 int ret_val;
996 unsigned char *buf = NULL; 1240 u32 tag_len;
997 u32 buf_len;
998 u32 level; 1241 u32 level;
999 1242
1000 if (secattr->mls_cat) { 1243 if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
1001 buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, 1244 return -EPERM;
1002 GFP_ATOMIC); 1245
1003 if (buf == NULL) 1246 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1004 return -ENOMEM; 1247 if (ret_val != 0)
1248 return ret_val;
1005 1249
1250 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1006 ret_val = cipso_v4_map_cat_rbm_hton(doi_def, 1251 ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
1007 secattr->mls_cat, 1252 secattr,
1008 secattr->mls_cat_len, 1253 &buffer[4],
1009 &buf[CIPSO_V4_HDR_LEN + 4], 1254 buffer_len - 4);
1010 CIPSO_V4_TAG1_CAT_LEN);
1011 if (ret_val < 0) 1255 if (ret_val < 0)
1012 goto gentag_failure; 1256 return ret_val;
1013 1257
1014 /* This will send packets using the "optimized" format when 1258 /* This will send packets using the "optimized" format when
1015 * possibile as specified in section 3.4.2.6 of the 1259 * possibile as specified in section 3.4.2.6 of the
1016 * CIPSO draft. */ 1260 * CIPSO draft. */
1017 if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10)) 1261 if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10)
1018 ret_val = 10; 1262 tag_len = 14;
1263 else
1264 tag_len = 4 + ret_val;
1265 } else
1266 tag_len = 4;
1267
1268 buffer[0] = 0x01;
1269 buffer[1] = tag_len;
1270 buffer[3] = level;
1271
1272 return tag_len;
1273}
1019 1274
1020 buf_len = 4 + ret_val; 1275/**
1021 } else { 1276 * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
1022 buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); 1277 * @doi_def: the DOI definition
1023 if (buf == NULL) 1278 * @tag: the CIPSO tag
1279 * @secattr: the security attributes
1280 *
1281 * Description:
1282 * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
1283 * attributes in @secattr. Return zero on success, negatives values on
1284 * failure.
1285 *
1286 */
1287static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
1288 const unsigned char *tag,
1289 struct netlbl_lsm_secattr *secattr)
1290{
1291 int ret_val;
1292 u8 tag_len = tag[1];
1293 u32 level;
1294
1295 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1296 if (ret_val != 0)
1297 return ret_val;
1298 secattr->mls_lvl = level;
1299 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1300
1301 if (tag_len > 4) {
1302 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1303 if (secattr->mls_cat == NULL)
1024 return -ENOMEM; 1304 return -ENOMEM;
1025 buf_len = 4; 1305
1306 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
1307 &tag[4],
1308 tag_len - 4,
1309 secattr);
1310 if (ret_val != 0) {
1311 netlbl_secattr_catmap_free(secattr->mls_cat);
1312 return ret_val;
1313 }
1314
1315 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1026 } 1316 }
1027 1317
1318 return 0;
1319}
1320
1321/**
1322 * cipso_v4_gentag_enum - Generate a CIPSO enumerated tag (type #2)
1323 * @doi_def: the DOI definition
1324 * @secattr: the security attributes
1325 * @buffer: the option buffer
1326 * @buffer_len: length of buffer in bytes
1327 *
1328 * Description:
1329 * Generate a CIPSO option using the enumerated tag, tag type #2. Returns the
1330 * size of the tag on success, negative values on failure.
1331 *
1332 */
1333static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
1334 const struct netlbl_lsm_secattr *secattr,
1335 unsigned char *buffer,
1336 u32 buffer_len)
1337{
1338 int ret_val;
1339 u32 tag_len;
1340 u32 level;
1341
1342 if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
1343 return -EPERM;
1344
1028 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); 1345 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1029 if (ret_val != 0) 1346 if (ret_val != 0)
1030 goto gentag_failure; 1347 return ret_val;
1348
1349 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1350 ret_val = cipso_v4_map_cat_enum_hton(doi_def,
1351 secattr,
1352 &buffer[4],
1353 buffer_len - 4);
1354 if (ret_val < 0)
1355 return ret_val;
1356
1357 tag_len = 4 + ret_val;
1358 } else
1359 tag_len = 4;
1360
1361 buffer[0] = 0x02;
1362 buffer[1] = tag_len;
1363 buffer[3] = level;
1031 1364
1032 ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf); 1365 return tag_len;
1366}
1367
1368/**
1369 * cipso_v4_parsetag_enum - Parse a CIPSO enumerated tag
1370 * @doi_def: the DOI definition
1371 * @tag: the CIPSO tag
1372 * @secattr: the security attributes
1373 *
1374 * Description:
1375 * Parse a CIPSO enumerated tag (tag type #2) and return the security
1376 * attributes in @secattr. Return zero on success, negatives values on
1377 * failure.
1378 *
1379 */
1380static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
1381 const unsigned char *tag,
1382 struct netlbl_lsm_secattr *secattr)
1383{
1384 int ret_val;
1385 u8 tag_len = tag[1];
1386 u32 level;
1387
1388 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1033 if (ret_val != 0) 1389 if (ret_val != 0)
1034 goto gentag_failure; 1390 return ret_val;
1391 secattr->mls_lvl = level;
1392 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1393
1394 if (tag_len > 4) {
1395 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1396 if (secattr->mls_cat == NULL)
1397 return -ENOMEM;
1035 1398
1036 buf[CIPSO_V4_HDR_LEN] = 0x01; 1399 ret_val = cipso_v4_map_cat_enum_ntoh(doi_def,
1037 buf[CIPSO_V4_HDR_LEN + 1] = buf_len; 1400 &tag[4],
1038 buf[CIPSO_V4_HDR_LEN + 3] = level; 1401 tag_len - 4,
1402 secattr);
1403 if (ret_val != 0) {
1404 netlbl_secattr_catmap_free(secattr->mls_cat);
1405 return ret_val;
1406 }
1039 1407
1040 *buffer = buf; 1408 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1041 *buffer_len = CIPSO_V4_HDR_LEN + buf_len; 1409 }
1042 1410
1043 return 0; 1411 return 0;
1412}
1044 1413
1045gentag_failure: 1414/**
1046 kfree(buf); 1415 * cipso_v4_gentag_rng - Generate a CIPSO ranged tag (type #5)
1047 return ret_val; 1416 * @doi_def: the DOI definition
1417 * @secattr: the security attributes
1418 * @buffer: the option buffer
1419 * @buffer_len: length of buffer in bytes
1420 *
1421 * Description:
1422 * Generate a CIPSO option using the ranged tag, tag type #5. Returns the
1423 * size of the tag on success, negative values on failure.
1424 *
1425 */
1426static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
1427 const struct netlbl_lsm_secattr *secattr,
1428 unsigned char *buffer,
1429 u32 buffer_len)
1430{
1431 int ret_val;
1432 u32 tag_len;
1433 u32 level;
1434
1435 if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
1436 return -EPERM;
1437
1438 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1439 if (ret_val != 0)
1440 return ret_val;
1441
1442 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1443 ret_val = cipso_v4_map_cat_rng_hton(doi_def,
1444 secattr,
1445 &buffer[4],
1446 buffer_len - 4);
1447 if (ret_val < 0)
1448 return ret_val;
1449
1450 tag_len = 4 + ret_val;
1451 } else
1452 tag_len = 4;
1453
1454 buffer[0] = 0x05;
1455 buffer[1] = tag_len;
1456 buffer[3] = level;
1457
1458 return tag_len;
1048} 1459}
1049 1460
1050/** 1461/**
1051 * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag 1462 * cipso_v4_parsetag_rng - Parse a CIPSO ranged tag
1052 * @doi_def: the DOI definition 1463 * @doi_def: the DOI definition
1053 * @tag: the CIPSO tag 1464 * @tag: the CIPSO tag
1054 * @secattr: the security attributes 1465 * @secattr: the security attributes
1055 * 1466 *
1056 * Description: 1467 * Description:
1057 * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security 1468 * Parse a CIPSO ranged tag (tag type #5) and return the security attributes
1058 * attributes in @secattr. Return zero on success, negatives values on 1469 * in @secattr. Return zero on success, negatives values on failure.
1059 * failure.
1060 * 1470 *
1061 */ 1471 */
1062static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, 1472static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
1063 const unsigned char *tag, 1473 const unsigned char *tag,
1064 struct netlbl_lsm_secattr *secattr) 1474 struct netlbl_lsm_secattr *secattr)
1065{ 1475{
@@ -1071,32 +1481,23 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
1071 if (ret_val != 0) 1481 if (ret_val != 0)
1072 return ret_val; 1482 return ret_val;
1073 secattr->mls_lvl = level; 1483 secattr->mls_lvl = level;
1074 secattr->mls_lvl_vld = 1; 1484 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1075 1485
1076 if (tag_len > 4) { 1486 if (tag_len > 4) {
1077 switch (doi_def->type) { 1487 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1078 case CIPSO_V4_MAP_PASS:
1079 secattr->mls_cat_len = tag_len - 4;
1080 break;
1081 case CIPSO_V4_MAP_STD:
1082 secattr->mls_cat_len =
1083 doi_def->map.std->cat.local_size;
1084 break;
1085 }
1086 secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC);
1087 if (secattr->mls_cat == NULL) 1488 if (secattr->mls_cat == NULL)
1088 return -ENOMEM; 1489 return -ENOMEM;
1089 1490
1090 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, 1491 ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
1091 &tag[4], 1492 &tag[4],
1092 tag_len - 4, 1493 tag_len - 4,
1093 secattr->mls_cat, 1494 secattr);
1094 secattr->mls_cat_len); 1495 if (ret_val != 0) {
1095 if (ret_val < 0) { 1496 netlbl_secattr_catmap_free(secattr->mls_cat);
1096 kfree(secattr->mls_cat);
1097 return ret_val; 1497 return ret_val;
1098 } 1498 }
1099 secattr->mls_cat_len = ret_val; 1499
1500 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1100 } 1501 }
1101 1502
1102 return 0; 1503 return 0;
@@ -1140,7 +1541,7 @@ int cipso_v4_validate(unsigned char **option)
1140 } 1541 }
1141 1542
1142 rcu_read_lock(); 1543 rcu_read_lock();
1143 doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2]))); 1544 doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2])));
1144 if (doi_def == NULL) { 1545 if (doi_def == NULL) {
1145 err_offset = 2; 1546 err_offset = 2;
1146 goto validate_return_locked; 1547 goto validate_return_locked;
@@ -1191,6 +1592,44 @@ int cipso_v4_validate(unsigned char **option)
1191 } 1592 }
1192 } 1593 }
1193 break; 1594 break;
1595 case CIPSO_V4_TAG_ENUM:
1596 if (tag_len < 4) {
1597 err_offset = opt_iter + 1;
1598 goto validate_return_locked;
1599 }
1600
1601 if (cipso_v4_map_lvl_valid(doi_def,
1602 tag[3]) < 0) {
1603 err_offset = opt_iter + 3;
1604 goto validate_return_locked;
1605 }
1606 if (tag_len > 4 &&
1607 cipso_v4_map_cat_enum_valid(doi_def,
1608 &tag[4],
1609 tag_len - 4) < 0) {
1610 err_offset = opt_iter + 4;
1611 goto validate_return_locked;
1612 }
1613 break;
1614 case CIPSO_V4_TAG_RANGE:
1615 if (tag_len < 4) {
1616 err_offset = opt_iter + 1;
1617 goto validate_return_locked;
1618 }
1619
1620 if (cipso_v4_map_lvl_valid(doi_def,
1621 tag[3]) < 0) {
1622 err_offset = opt_iter + 3;
1623 goto validate_return_locked;
1624 }
1625 if (tag_len > 4 &&
1626 cipso_v4_map_cat_rng_valid(doi_def,
1627 &tag[4],
1628 tag_len - 4) < 0) {
1629 err_offset = opt_iter + 4;
1630 goto validate_return_locked;
1631 }
1632 break;
1194 default: 1633 default:
1195 err_offset = opt_iter; 1634 err_offset = opt_iter;
1196 goto validate_return_locked; 1635 goto validate_return_locked;
@@ -1265,7 +1704,7 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1265{ 1704{
1266 int ret_val = -EPERM; 1705 int ret_val = -EPERM;
1267 u32 iter; 1706 u32 iter;
1268 unsigned char *buf = NULL; 1707 unsigned char *buf;
1269 u32 buf_len = 0; 1708 u32 buf_len = 0;
1270 u32 opt_len; 1709 u32 opt_len;
1271 struct ip_options *opt = NULL; 1710 struct ip_options *opt = NULL;
@@ -1281,17 +1720,40 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1281 if (sk == NULL) 1720 if (sk == NULL)
1282 return 0; 1721 return 0;
1283 1722
1723 /* We allocate the maximum CIPSO option size here so we are probably
1724 * being a little wasteful, but it makes our life _much_ easier later
1725 * on and after all we are only talking about 40 bytes. */
1726 buf_len = CIPSO_V4_OPT_LEN_MAX;
1727 buf = kmalloc(buf_len, GFP_ATOMIC);
1728 if (buf == NULL) {
1729 ret_val = -ENOMEM;
1730 goto socket_setattr_failure;
1731 }
1732
1284 /* XXX - This code assumes only one tag per CIPSO option which isn't 1733 /* XXX - This code assumes only one tag per CIPSO option which isn't
1285 * really a good assumption to make but since we only support the MAC 1734 * really a good assumption to make but since we only support the MAC
1286 * tags right now it is a safe assumption. */ 1735 * tags right now it is a safe assumption. */
1287 iter = 0; 1736 iter = 0;
1288 do { 1737 do {
1738 memset(buf, 0, buf_len);
1289 switch (doi_def->tags[iter]) { 1739 switch (doi_def->tags[iter]) {
1290 case CIPSO_V4_TAG_RBITMAP: 1740 case CIPSO_V4_TAG_RBITMAP:
1291 ret_val = cipso_v4_gentag_rbm(doi_def, 1741 ret_val = cipso_v4_gentag_rbm(doi_def,
1292 secattr, 1742 secattr,
1293 &buf, 1743 &buf[CIPSO_V4_HDR_LEN],
1294 &buf_len); 1744 buf_len - CIPSO_V4_HDR_LEN);
1745 break;
1746 case CIPSO_V4_TAG_ENUM:
1747 ret_val = cipso_v4_gentag_enum(doi_def,
1748 secattr,
1749 &buf[CIPSO_V4_HDR_LEN],
1750 buf_len - CIPSO_V4_HDR_LEN);
1751 break;
1752 case CIPSO_V4_TAG_RANGE:
1753 ret_val = cipso_v4_gentag_rng(doi_def,
1754 secattr,
1755 &buf[CIPSO_V4_HDR_LEN],
1756 buf_len - CIPSO_V4_HDR_LEN);
1295 break; 1757 break;
1296 default: 1758 default:
1297 ret_val = -EPERM; 1759 ret_val = -EPERM;
@@ -1299,11 +1761,13 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1299 } 1761 }
1300 1762
1301 iter++; 1763 iter++;
1302 } while (ret_val != 0 && 1764 } while (ret_val < 0 &&
1303 iter < CIPSO_V4_TAG_MAXCNT && 1765 iter < CIPSO_V4_TAG_MAXCNT &&
1304 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); 1766 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
1305 if (ret_val != 0) 1767 if (ret_val < 0)
1306 goto socket_setattr_failure; 1768 goto socket_setattr_failure;
1769 cipso_v4_gentag_hdr(doi_def, buf, ret_val);
1770 buf_len = CIPSO_V4_HDR_LEN + ret_val;
1307 1771
1308 /* We can't use ip_options_get() directly because it makes a call to 1772 /* We can't use ip_options_get() directly because it makes a call to
1309 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and 1773 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
@@ -1370,19 +1834,33 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1370 if (ret_val == 0) 1834 if (ret_val == 0)
1371 return ret_val; 1835 return ret_val;
1372 1836
1373 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1837 doi = ntohl(*(__be32 *)&cipso_ptr[2]);
1374 rcu_read_lock(); 1838 rcu_read_lock();
1375 doi_def = cipso_v4_doi_getdef(doi); 1839 doi_def = cipso_v4_doi_search(doi);
1376 if (doi_def == NULL) { 1840 if (doi_def == NULL) {
1377 rcu_read_unlock(); 1841 rcu_read_unlock();
1378 return -ENOMSG; 1842 return -ENOMSG;
1379 } 1843 }
1844
1845 /* XXX - This code assumes only one tag per CIPSO option which isn't
1846 * really a good assumption to make but since we only support the MAC
1847 * tags right now it is a safe assumption. */
1380 switch (cipso_ptr[6]) { 1848 switch (cipso_ptr[6]) {
1381 case CIPSO_V4_TAG_RBITMAP: 1849 case CIPSO_V4_TAG_RBITMAP:
1382 ret_val = cipso_v4_parsetag_rbm(doi_def, 1850 ret_val = cipso_v4_parsetag_rbm(doi_def,
1383 &cipso_ptr[6], 1851 &cipso_ptr[6],
1384 secattr); 1852 secattr);
1385 break; 1853 break;
1854 case CIPSO_V4_TAG_ENUM:
1855 ret_val = cipso_v4_parsetag_enum(doi_def,
1856 &cipso_ptr[6],
1857 secattr);
1858 break;
1859 case CIPSO_V4_TAG_RANGE:
1860 ret_val = cipso_v4_parsetag_rng(doi_def,
1861 &cipso_ptr[6],
1862 secattr);
1863 break;
1386 } 1864 }
1387 rcu_read_unlock(); 1865 rcu_read_unlock();
1388 1866
@@ -1430,23 +1908,30 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
1430 u32 doi; 1908 u32 doi;
1431 struct cipso_v4_doi *doi_def; 1909 struct cipso_v4_doi *doi_def;
1432 1910
1433 if (!CIPSO_V4_OPTEXIST(skb))
1434 return -ENOMSG;
1435 cipso_ptr = CIPSO_V4_OPTPTR(skb); 1911 cipso_ptr = CIPSO_V4_OPTPTR(skb);
1436 if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) 1912 if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
1437 return 0; 1913 return 0;
1438 1914
1439 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1915 doi = ntohl(*(__be32 *)&cipso_ptr[2]);
1440 rcu_read_lock(); 1916 rcu_read_lock();
1441 doi_def = cipso_v4_doi_getdef(doi); 1917 doi_def = cipso_v4_doi_search(doi);
1442 if (doi_def == NULL) 1918 if (doi_def == NULL)
1443 goto skbuff_getattr_return; 1919 goto skbuff_getattr_return;
1920
1921 /* XXX - This code assumes only one tag per CIPSO option which isn't
1922 * really a good assumption to make but since we only support the MAC
1923 * tags right now it is a safe assumption. */
1444 switch (cipso_ptr[6]) { 1924 switch (cipso_ptr[6]) {
1445 case CIPSO_V4_TAG_RBITMAP: 1925 case CIPSO_V4_TAG_RBITMAP:
1446 ret_val = cipso_v4_parsetag_rbm(doi_def, 1926 ret_val = cipso_v4_parsetag_rbm(doi_def,
1447 &cipso_ptr[6], 1927 &cipso_ptr[6],
1448 secattr); 1928 secattr);
1449 break; 1929 break;
1930 case CIPSO_V4_TAG_ENUM:
1931 ret_val = cipso_v4_parsetag_enum(doi_def,
1932 &cipso_ptr[6],
1933 secattr);
1934 break;
1450 } 1935 }
1451 1936
1452skbuff_getattr_return: 1937skbuff_getattr_return: