diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 08144f8fc911..70858dccaca2 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -459,6 +459,10 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) | |||
459 | if (iter == 0) | 459 | if (iter == 0) |
460 | return -EINVAL; | 460 | return -EINVAL; |
461 | break; | 461 | break; |
462 | case CIPSO_V4_TAG_ENUM: | ||
463 | if (doi_def->type != CIPSO_V4_MAP_PASS) | ||
464 | return -EINVAL; | ||
465 | break; | ||
462 | default: | 466 | default: |
463 | return -EINVAL; | 467 | return -EINVAL; |
464 | } | 468 | } |
@@ -940,6 +944,107 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, | |||
940 | return -EINVAL; | 944 | return -EINVAL; |
941 | } | 945 | } |
942 | 946 | ||
947 | /** | ||
948 | * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid | ||
949 | * @doi_def: the DOI definition | ||
950 | * @enumcat: category list | ||
951 | * @enumcat_len: length of the category list in bytes | ||
952 | * | ||
953 | * Description: | ||
954 | * Checks the given categories against the given DOI definition and returns a | ||
955 | * negative value if any of the categories do not have a valid mapping and a | ||
956 | * zero value if all of the categories are valid. | ||
957 | * | ||
958 | */ | ||
959 | static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def, | ||
960 | const unsigned char *enumcat, | ||
961 | u32 enumcat_len) | ||
962 | { | ||
963 | u16 cat; | ||
964 | int cat_prev = -1; | ||
965 | u32 iter; | ||
966 | |||
967 | if (doi_def->type != CIPSO_V4_MAP_PASS || enumcat_len & 0x01) | ||
968 | return -EFAULT; | ||
969 | |||
970 | for (iter = 0; iter < enumcat_len; iter += 2) { | ||
971 | cat = ntohs(*((__be16 *)&enumcat[iter])); | ||
972 | if (cat <= cat_prev) | ||
973 | return -EFAULT; | ||
974 | cat_prev = cat; | ||
975 | } | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | /** | ||
981 | * cipso_v4_map_cat_enum_hton - Perform a category mapping from host to network | ||
982 | * @doi_def: the DOI definition | ||
983 | * @secattr: the security attributes | ||
984 | * @net_cat: the zero'd out category list in network/CIPSO format | ||
985 | * @net_cat_len: the length of the CIPSO category list in bytes | ||
986 | * | ||
987 | * Description: | ||
988 | * Perform a label mapping to translate a local MLS category bitmap to the | ||
989 | * correct CIPSO category list using the given DOI definition. Returns the | ||
990 | * size in bytes of the network category bitmap on success, negative values | ||
991 | * otherwise. | ||
992 | * | ||
993 | */ | ||
994 | static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def, | ||
995 | const struct netlbl_lsm_secattr *secattr, | ||
996 | unsigned char *net_cat, | ||
997 | u32 net_cat_len) | ||
998 | { | ||
999 | int cat = -1; | ||
1000 | u32 cat_iter = 0; | ||
1001 | |||
1002 | for (;;) { | ||
1003 | cat = netlbl_secattr_catmap_walk(secattr->mls_cat, cat + 1); | ||
1004 | if (cat < 0) | ||
1005 | break; | ||
1006 | if ((cat_iter + 2) > net_cat_len) | ||
1007 | return -ENOSPC; | ||
1008 | |||
1009 | *((__be16 *)&net_cat[cat_iter]) = htons(cat); | ||
1010 | cat_iter += 2; | ||
1011 | } | ||
1012 | |||
1013 | return cat_iter; | ||
1014 | } | ||
1015 | |||
1016 | /** | ||
1017 | * cipso_v4_map_cat_enum_ntoh - Perform a category mapping from network to host | ||
1018 | * @doi_def: the DOI definition | ||
1019 | * @net_cat: the category list in network/CIPSO format | ||
1020 | * @net_cat_len: the length of the CIPSO bitmap in bytes | ||
1021 | * @secattr: the security attributes | ||
1022 | * | ||
1023 | * Description: | ||
1024 | * Perform a label mapping to translate a CIPSO category list to the correct | ||
1025 | * local MLS category bitmap using the given DOI definition. Returns zero on | ||
1026 | * success, negative values on failure. | ||
1027 | * | ||
1028 | */ | ||
1029 | static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def, | ||
1030 | const unsigned char *net_cat, | ||
1031 | u32 net_cat_len, | ||
1032 | struct netlbl_lsm_secattr *secattr) | ||
1033 | { | ||
1034 | int ret_val; | ||
1035 | u32 iter; | ||
1036 | |||
1037 | for (iter = 0; iter < net_cat_len; iter += 2) { | ||
1038 | ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat, | ||
1039 | ntohs(*((__be16 *)&net_cat[iter])), | ||
1040 | GFP_ATOMIC); | ||
1041 | if (ret_val != 0) | ||
1042 | return ret_val; | ||
1043 | } | ||
1044 | |||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
943 | /* | 1048 | /* |
944 | * Protocol Handling Functions | 1049 | * Protocol Handling Functions |
945 | */ | 1050 | */ |
@@ -1068,6 +1173,99 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, | |||
1068 | } | 1173 | } |
1069 | 1174 | ||
1070 | /** | 1175 | /** |
1176 | * cipso_v4_gentag_enum - Generate a CIPSO enumerated tag (type #2) | ||
1177 | * @doi_def: the DOI definition | ||
1178 | * @secattr: the security attributes | ||
1179 | * @buffer: the option buffer | ||
1180 | * @buffer_len: length of buffer in bytes | ||
1181 | * | ||
1182 | * Description: | ||
1183 | * Generate a CIPSO option using the enumerated tag, tag type #2. Returns the | ||
1184 | * size of the tag on success, negative values on failure. | ||
1185 | * | ||
1186 | */ | ||
1187 | static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def, | ||
1188 | const struct netlbl_lsm_secattr *secattr, | ||
1189 | unsigned char *buffer, | ||
1190 | u32 buffer_len) | ||
1191 | { | ||
1192 | int ret_val; | ||
1193 | u32 tag_len; | ||
1194 | u32 level; | ||
1195 | |||
1196 | if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL)) | ||
1197 | return -EPERM; | ||
1198 | |||
1199 | ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); | ||
1200 | if (ret_val != 0) | ||
1201 | return ret_val; | ||
1202 | |||
1203 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { | ||
1204 | ret_val = cipso_v4_map_cat_enum_hton(doi_def, | ||
1205 | secattr, | ||
1206 | &buffer[4], | ||
1207 | buffer_len - 4); | ||
1208 | if (ret_val < 0) | ||
1209 | return ret_val; | ||
1210 | |||
1211 | tag_len = 4 + ret_val; | ||
1212 | } else | ||
1213 | tag_len = 4; | ||
1214 | |||
1215 | buffer[0] = 0x02; | ||
1216 | buffer[1] = tag_len; | ||
1217 | buffer[3] = level; | ||
1218 | |||
1219 | return tag_len; | ||
1220 | } | ||
1221 | |||
1222 | /** | ||
1223 | * cipso_v4_parsetag_enum - Parse a CIPSO enumerated tag | ||
1224 | * @doi_def: the DOI definition | ||
1225 | * @tag: the CIPSO tag | ||
1226 | * @secattr: the security attributes | ||
1227 | * | ||
1228 | * Description: | ||
1229 | * Parse a CIPSO enumerated tag (tag type #2) and return the security | ||
1230 | * attributes in @secattr. Return zero on success, negatives values on | ||
1231 | * failure. | ||
1232 | * | ||
1233 | */ | ||
1234 | static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def, | ||
1235 | const unsigned char *tag, | ||
1236 | struct netlbl_lsm_secattr *secattr) | ||
1237 | { | ||
1238 | int ret_val; | ||
1239 | u8 tag_len = tag[1]; | ||
1240 | u32 level; | ||
1241 | |||
1242 | ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level); | ||
1243 | if (ret_val != 0) | ||
1244 | return ret_val; | ||
1245 | secattr->mls_lvl = level; | ||
1246 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; | ||
1247 | |||
1248 | if (tag_len > 4) { | ||
1249 | secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | ||
1250 | if (secattr->mls_cat == NULL) | ||
1251 | return -ENOMEM; | ||
1252 | |||
1253 | ret_val = cipso_v4_map_cat_enum_ntoh(doi_def, | ||
1254 | &tag[4], | ||
1255 | tag_len - 4, | ||
1256 | secattr); | ||
1257 | if (ret_val != 0) { | ||
1258 | netlbl_secattr_catmap_free(secattr->mls_cat); | ||
1259 | return ret_val; | ||
1260 | } | ||
1261 | |||
1262 | secattr->flags |= NETLBL_SECATTR_MLS_CAT; | ||
1263 | } | ||
1264 | |||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | /** | ||
1071 | * cipso_v4_validate - Validate a CIPSO option | 1269 | * cipso_v4_validate - Validate a CIPSO option |
1072 | * @option: the start of the option, on error it is set to point to the error | 1270 | * @option: the start of the option, on error it is set to point to the error |
1073 | * | 1271 | * |
@@ -1156,6 +1354,25 @@ int cipso_v4_validate(unsigned char **option) | |||
1156 | } | 1354 | } |
1157 | } | 1355 | } |
1158 | break; | 1356 | break; |
1357 | case CIPSO_V4_TAG_ENUM: | ||
1358 | if (tag_len < 4) { | ||
1359 | err_offset = opt_iter + 1; | ||
1360 | goto validate_return_locked; | ||
1361 | } | ||
1362 | |||
1363 | if (cipso_v4_map_lvl_valid(doi_def, | ||
1364 | tag[3]) < 0) { | ||
1365 | err_offset = opt_iter + 3; | ||
1366 | goto validate_return_locked; | ||
1367 | } | ||
1368 | if (tag_len > 4 && | ||
1369 | cipso_v4_map_cat_enum_valid(doi_def, | ||
1370 | &tag[4], | ||
1371 | tag_len - 4) < 0) { | ||
1372 | err_offset = opt_iter + 4; | ||
1373 | goto validate_return_locked; | ||
1374 | } | ||
1375 | break; | ||
1159 | default: | 1376 | default: |
1160 | err_offset = opt_iter; | 1377 | err_offset = opt_iter; |
1161 | goto validate_return_locked; | 1378 | goto validate_return_locked; |
@@ -1269,6 +1486,12 @@ int cipso_v4_socket_setattr(const struct socket *sock, | |||
1269 | &buf[CIPSO_V4_HDR_LEN], | 1486 | &buf[CIPSO_V4_HDR_LEN], |
1270 | buf_len - CIPSO_V4_HDR_LEN); | 1487 | buf_len - CIPSO_V4_HDR_LEN); |
1271 | break; | 1488 | break; |
1489 | case CIPSO_V4_TAG_ENUM: | ||
1490 | ret_val = cipso_v4_gentag_enum(doi_def, | ||
1491 | secattr, | ||
1492 | &buf[CIPSO_V4_HDR_LEN], | ||
1493 | buf_len - CIPSO_V4_HDR_LEN); | ||
1494 | break; | ||
1272 | default: | 1495 | default: |
1273 | ret_val = -EPERM; | 1496 | ret_val = -EPERM; |
1274 | goto socket_setattr_failure; | 1497 | goto socket_setattr_failure; |
@@ -1365,6 +1588,11 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) | |||
1365 | &cipso_ptr[6], | 1588 | &cipso_ptr[6], |
1366 | secattr); | 1589 | secattr); |
1367 | break; | 1590 | break; |
1591 | case CIPSO_V4_TAG_ENUM: | ||
1592 | ret_val = cipso_v4_parsetag_enum(doi_def, | ||
1593 | &cipso_ptr[6], | ||
1594 | secattr); | ||
1595 | break; | ||
1368 | } | 1596 | } |
1369 | rcu_read_unlock(); | 1597 | rcu_read_unlock(); |
1370 | 1598 | ||
@@ -1431,6 +1659,11 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb, | |||
1431 | &cipso_ptr[6], | 1659 | &cipso_ptr[6], |
1432 | secattr); | 1660 | secattr); |
1433 | break; | 1661 | break; |
1662 | case CIPSO_V4_TAG_ENUM: | ||
1663 | ret_val = cipso_v4_parsetag_enum(doi_def, | ||
1664 | &cipso_ptr[6], | ||
1665 | secattr); | ||
1666 | break; | ||
1434 | } | 1667 | } |
1435 | 1668 | ||
1436 | skbuff_getattr_return: | 1669 | skbuff_getattr_return: |