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.c168
1 files changed, 69 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;