aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/cipso_ipv4.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 70858dccaca2..60aafb4a8adf 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -455,6 +455,10 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
455 switch (doi_def->tags[iter]) { 455 switch (doi_def->tags[iter]) {
456 case CIPSO_V4_TAG_RBITMAP: 456 case CIPSO_V4_TAG_RBITMAP:
457 break; 457 break;
458 case CIPSO_V4_TAG_RANGE:
459 if (doi_def->type != CIPSO_V4_MAP_PASS)
460 return -EINVAL;
461 break;
458 case CIPSO_V4_TAG_INVALID: 462 case CIPSO_V4_TAG_INVALID:
459 if (iter == 0) 463 if (iter == 0)
460 return -EINVAL; 464 return -EINVAL;
@@ -1045,6 +1049,148 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
1045 return 0; 1049 return 0;
1046} 1050}
1047 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;
1072
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)
1084 return -EFAULT;
1085
1086 cat_prev = cat_low;
1087 }
1088
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;
1192}
1193
1048/* 1194/*
1049 * Protocol Handling Functions 1195 * Protocol Handling Functions
1050 */ 1196 */
@@ -1266,6 +1412,98 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
1266} 1412}
1267 1413
1268/** 1414/**
1415 * cipso_v4_gentag_rng - Generate a CIPSO ranged tag (type #5)
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;
1459}
1460
1461/**
1462 * cipso_v4_parsetag_rng - Parse a CIPSO ranged tag
1463 * @doi_def: the DOI definition
1464 * @tag: the CIPSO tag
1465 * @secattr: the security attributes
1466 *
1467 * Description:
1468 * Parse a CIPSO ranged tag (tag type #5) and return the security attributes
1469 * in @secattr. Return zero on success, negatives values on failure.
1470 *
1471 */
1472static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
1473 const unsigned char *tag,
1474 struct netlbl_lsm_secattr *secattr)
1475{
1476 int ret_val;
1477 u8 tag_len = tag[1];
1478 u32 level;
1479
1480 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1481 if (ret_val != 0)
1482 return ret_val;
1483 secattr->mls_lvl = level;
1484 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1485
1486 if (tag_len > 4) {
1487 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1488 if (secattr->mls_cat == NULL)
1489 return -ENOMEM;
1490
1491 ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
1492 &tag[4],
1493 tag_len - 4,
1494 secattr);
1495 if (ret_val != 0) {
1496 netlbl_secattr_catmap_free(secattr->mls_cat);
1497 return ret_val;
1498 }
1499
1500 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1501 }
1502
1503 return 0;
1504}
1505
1506/**
1269 * cipso_v4_validate - Validate a CIPSO option 1507 * cipso_v4_validate - Validate a CIPSO option
1270 * @option: the start of the option, on error it is set to point to the error 1508 * @option: the start of the option, on error it is set to point to the error
1271 * 1509 *
@@ -1373,6 +1611,25 @@ int cipso_v4_validate(unsigned char **option)
1373 goto validate_return_locked; 1611 goto validate_return_locked;
1374 } 1612 }
1375 break; 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;
1376 default: 1633 default:
1377 err_offset = opt_iter; 1634 err_offset = opt_iter;
1378 goto validate_return_locked; 1635 goto validate_return_locked;
@@ -1492,6 +1749,12 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1492 &buf[CIPSO_V4_HDR_LEN], 1749 &buf[CIPSO_V4_HDR_LEN],
1493 buf_len - CIPSO_V4_HDR_LEN); 1750 buf_len - CIPSO_V4_HDR_LEN);
1494 break; 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);
1757 break;
1495 default: 1758 default:
1496 ret_val = -EPERM; 1759 ret_val = -EPERM;
1497 goto socket_setattr_failure; 1760 goto socket_setattr_failure;
@@ -1593,6 +1856,11 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1593 &cipso_ptr[6], 1856 &cipso_ptr[6],
1594 secattr); 1857 secattr);
1595 break; 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;
1596 } 1864 }
1597 rcu_read_unlock(); 1865 rcu_read_unlock();
1598 1866