diff options
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 813 |
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 | */ |
448 | int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) | 448 | int 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 | */ |
819 | static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, | 840 | static 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 | */ |
889 | static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, | 901 | static 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 | */ | ||
963 | static 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 | */ | ||
998 | static 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 | */ | ||
1033 | static 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 | */ | ||
1064 | static 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 | */ | ||
1106 | static 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 | */ | ||
1166 | static 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 | */ |
960 | static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, | 1211 | static 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 | */ |
990 | static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, | 1234 | static 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 | */ | ||
1287 | static 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 | */ | ||
1333 | static 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 | */ | ||
1380 | static 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 | ||
1045 | gentag_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 | */ | ||
1426 | static 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 | */ |
1062 | static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, | 1472 | static 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 | ||
1452 | skbuff_getattr_return: | 1937 | skbuff_getattr_return: |