diff options
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 127 |
1 files changed, 107 insertions, 20 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 23768b9d6b64..490e035c6d90 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -109,6 +109,19 @@ int cipso_v4_rbm_strictvalid = 1; | |||
109 | * be omitted. */ | 109 | * be omitted. */ |
110 | #define CIPSO_V4_TAG_RNG_CAT_MAX 8 | 110 | #define CIPSO_V4_TAG_RNG_CAT_MAX 8 |
111 | 111 | ||
112 | /* Base length of the local tag (non-standard tag). | ||
113 | * Tag definition (may change between kernel versions) | ||
114 | * | ||
115 | * 0 8 16 24 32 | ||
116 | * +----------+----------+----------+----------+ | ||
117 | * | 10000000 | 00000110 | 32-bit secid value | | ||
118 | * +----------+----------+----------+----------+ | ||
119 | * | in (host byte order)| | ||
120 | * +----------+----------+ | ||
121 | * | ||
122 | */ | ||
123 | #define CIPSO_V4_TAG_LOC_BLEN 6 | ||
124 | |||
112 | /* | 125 | /* |
113 | * Helper Functions | 126 | * Helper Functions |
114 | */ | 127 | */ |
@@ -467,6 +480,10 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) | |||
467 | if (doi_def->type != CIPSO_V4_MAP_PASS) | 480 | if (doi_def->type != CIPSO_V4_MAP_PASS) |
468 | return -EINVAL; | 481 | return -EINVAL; |
469 | break; | 482 | break; |
483 | case CIPSO_V4_TAG_LOCAL: | ||
484 | if (doi_def->type != CIPSO_V4_MAP_LOCAL) | ||
485 | return -EINVAL; | ||
486 | break; | ||
470 | default: | 487 | default: |
471 | return -EINVAL; | 488 | return -EINVAL; |
472 | } | 489 | } |
@@ -502,7 +519,7 @@ void cipso_v4_doi_free(struct cipso_v4_doi *doi_def) | |||
502 | return; | 519 | return; |
503 | 520 | ||
504 | switch (doi_def->type) { | 521 | switch (doi_def->type) { |
505 | case CIPSO_V4_MAP_STD: | 522 | case CIPSO_V4_MAP_TRANS: |
506 | kfree(doi_def->map.std->lvl.cipso); | 523 | kfree(doi_def->map.std->lvl.cipso); |
507 | kfree(doi_def->map.std->lvl.local); | 524 | kfree(doi_def->map.std->lvl.local); |
508 | kfree(doi_def->map.std->cat.cipso); | 525 | kfree(doi_def->map.std->cat.cipso); |
@@ -673,7 +690,7 @@ static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level) | |||
673 | switch (doi_def->type) { | 690 | switch (doi_def->type) { |
674 | case CIPSO_V4_MAP_PASS: | 691 | case CIPSO_V4_MAP_PASS: |
675 | return 0; | 692 | return 0; |
676 | case CIPSO_V4_MAP_STD: | 693 | case CIPSO_V4_MAP_TRANS: |
677 | if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL) | 694 | if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL) |
678 | return 0; | 695 | return 0; |
679 | break; | 696 | break; |
@@ -702,7 +719,7 @@ static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def, | |||
702 | case CIPSO_V4_MAP_PASS: | 719 | case CIPSO_V4_MAP_PASS: |
703 | *net_lvl = host_lvl; | 720 | *net_lvl = host_lvl; |
704 | return 0; | 721 | return 0; |
705 | case CIPSO_V4_MAP_STD: | 722 | case CIPSO_V4_MAP_TRANS: |
706 | if (host_lvl < doi_def->map.std->lvl.local_size && | 723 | if (host_lvl < doi_def->map.std->lvl.local_size && |
707 | doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) { | 724 | doi_def->map.std->lvl.local[host_lvl] < CIPSO_V4_INV_LVL) { |
708 | *net_lvl = doi_def->map.std->lvl.local[host_lvl]; | 725 | *net_lvl = doi_def->map.std->lvl.local[host_lvl]; |
@@ -736,7 +753,7 @@ static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def, | |||
736 | case CIPSO_V4_MAP_PASS: | 753 | case CIPSO_V4_MAP_PASS: |
737 | *host_lvl = net_lvl; | 754 | *host_lvl = net_lvl; |
738 | return 0; | 755 | return 0; |
739 | case CIPSO_V4_MAP_STD: | 756 | case CIPSO_V4_MAP_TRANS: |
740 | map_tbl = doi_def->map.std; | 757 | map_tbl = doi_def->map.std; |
741 | if (net_lvl < map_tbl->lvl.cipso_size && | 758 | if (net_lvl < map_tbl->lvl.cipso_size && |
742 | map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) { | 759 | map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) { |
@@ -773,7 +790,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, | |||
773 | switch (doi_def->type) { | 790 | switch (doi_def->type) { |
774 | case CIPSO_V4_MAP_PASS: | 791 | case CIPSO_V4_MAP_PASS: |
775 | return 0; | 792 | return 0; |
776 | case CIPSO_V4_MAP_STD: | 793 | case CIPSO_V4_MAP_TRANS: |
777 | cipso_cat_size = doi_def->map.std->cat.cipso_size; | 794 | cipso_cat_size = doi_def->map.std->cat.cipso_size; |
778 | cipso_array = doi_def->map.std->cat.cipso; | 795 | cipso_array = doi_def->map.std->cat.cipso; |
779 | for (;;) { | 796 | for (;;) { |
@@ -821,7 +838,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, | |||
821 | u32 host_cat_size = 0; | 838 | u32 host_cat_size = 0; |
822 | u32 *host_cat_array = NULL; | 839 | u32 *host_cat_array = NULL; |
823 | 840 | ||
824 | if (doi_def->type == CIPSO_V4_MAP_STD) { | 841 | if (doi_def->type == CIPSO_V4_MAP_TRANS) { |
825 | host_cat_size = doi_def->map.std->cat.local_size; | 842 | host_cat_size = doi_def->map.std->cat.local_size; |
826 | host_cat_array = doi_def->map.std->cat.local; | 843 | host_cat_array = doi_def->map.std->cat.local; |
827 | } | 844 | } |
@@ -836,7 +853,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, | |||
836 | case CIPSO_V4_MAP_PASS: | 853 | case CIPSO_V4_MAP_PASS: |
837 | net_spot = host_spot; | 854 | net_spot = host_spot; |
838 | break; | 855 | break; |
839 | case CIPSO_V4_MAP_STD: | 856 | case CIPSO_V4_MAP_TRANS: |
840 | if (host_spot >= host_cat_size) | 857 | if (host_spot >= host_cat_size) |
841 | return -EPERM; | 858 | return -EPERM; |
842 | net_spot = host_cat_array[host_spot]; | 859 | net_spot = host_cat_array[host_spot]; |
@@ -882,7 +899,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, | |||
882 | u32 net_cat_size = 0; | 899 | u32 net_cat_size = 0; |
883 | u32 *net_cat_array = NULL; | 900 | u32 *net_cat_array = NULL; |
884 | 901 | ||
885 | if (doi_def->type == CIPSO_V4_MAP_STD) { | 902 | if (doi_def->type == CIPSO_V4_MAP_TRANS) { |
886 | net_cat_size = doi_def->map.std->cat.cipso_size; | 903 | net_cat_size = doi_def->map.std->cat.cipso_size; |
887 | net_cat_array = doi_def->map.std->cat.cipso; | 904 | net_cat_array = doi_def->map.std->cat.cipso; |
888 | } | 905 | } |
@@ -902,7 +919,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, | |||
902 | case CIPSO_V4_MAP_PASS: | 919 | case CIPSO_V4_MAP_PASS: |
903 | host_spot = net_spot; | 920 | host_spot = net_spot; |
904 | break; | 921 | break; |
905 | case CIPSO_V4_MAP_STD: | 922 | case CIPSO_V4_MAP_TRANS: |
906 | if (net_spot >= net_cat_size) | 923 | if (net_spot >= net_cat_size) |
907 | return -EPERM; | 924 | return -EPERM; |
908 | host_spot = net_cat_array[net_spot]; | 925 | host_spot = net_cat_array[net_spot]; |
@@ -1238,7 +1255,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, | |||
1238 | } else | 1255 | } else |
1239 | tag_len = 4; | 1256 | tag_len = 4; |
1240 | 1257 | ||
1241 | buffer[0] = 0x01; | 1258 | buffer[0] = CIPSO_V4_TAG_RBITMAP; |
1242 | buffer[1] = tag_len; | 1259 | buffer[1] = tag_len; |
1243 | buffer[3] = level; | 1260 | buffer[3] = level; |
1244 | 1261 | ||
@@ -1334,7 +1351,7 @@ static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def, | |||
1334 | } else | 1351 | } else |
1335 | tag_len = 4; | 1352 | tag_len = 4; |
1336 | 1353 | ||
1337 | buffer[0] = 0x02; | 1354 | buffer[0] = CIPSO_V4_TAG_ENUM; |
1338 | buffer[1] = tag_len; | 1355 | buffer[1] = tag_len; |
1339 | buffer[3] = level; | 1356 | buffer[3] = level; |
1340 | 1357 | ||
@@ -1430,7 +1447,7 @@ static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def, | |||
1430 | } else | 1447 | } else |
1431 | tag_len = 4; | 1448 | tag_len = 4; |
1432 | 1449 | ||
1433 | buffer[0] = 0x05; | 1450 | buffer[0] = CIPSO_V4_TAG_RANGE; |
1434 | buffer[1] = tag_len; | 1451 | buffer[1] = tag_len; |
1435 | buffer[3] = level; | 1452 | buffer[3] = level; |
1436 | 1453 | ||
@@ -1484,6 +1501,54 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def, | |||
1484 | } | 1501 | } |
1485 | 1502 | ||
1486 | /** | 1503 | /** |
1504 | * cipso_v4_gentag_loc - Generate a CIPSO local tag (non-standard) | ||
1505 | * @doi_def: the DOI definition | ||
1506 | * @secattr: the security attributes | ||
1507 | * @buffer: the option buffer | ||
1508 | * @buffer_len: length of buffer in bytes | ||
1509 | * | ||
1510 | * Description: | ||
1511 | * Generate a CIPSO option using the local tag. Returns the size of the tag | ||
1512 | * on success, negative values on failure. | ||
1513 | * | ||
1514 | */ | ||
1515 | static int cipso_v4_gentag_loc(const struct cipso_v4_doi *doi_def, | ||
1516 | const struct netlbl_lsm_secattr *secattr, | ||
1517 | unsigned char *buffer, | ||
1518 | u32 buffer_len) | ||
1519 | { | ||
1520 | if (!(secattr->flags & NETLBL_SECATTR_SECID)) | ||
1521 | return -EPERM; | ||
1522 | |||
1523 | buffer[0] = CIPSO_V4_TAG_LOCAL; | ||
1524 | buffer[1] = CIPSO_V4_TAG_LOC_BLEN; | ||
1525 | *(u32 *)&buffer[2] = secattr->attr.secid; | ||
1526 | |||
1527 | return CIPSO_V4_TAG_LOC_BLEN; | ||
1528 | } | ||
1529 | |||
1530 | /** | ||
1531 | * cipso_v4_parsetag_loc - Parse a CIPSO local tag | ||
1532 | * @doi_def: the DOI definition | ||
1533 | * @tag: the CIPSO tag | ||
1534 | * @secattr: the security attributes | ||
1535 | * | ||
1536 | * Description: | ||
1537 | * Parse a CIPSO local tag and return the security attributes in @secattr. | ||
1538 | * Return zero on success, negatives values on failure. | ||
1539 | * | ||
1540 | */ | ||
1541 | static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def, | ||
1542 | const unsigned char *tag, | ||
1543 | struct netlbl_lsm_secattr *secattr) | ||
1544 | { | ||
1545 | secattr->attr.secid = *(u32 *)&tag[2]; | ||
1546 | secattr->flags |= NETLBL_SECATTR_SECID; | ||
1547 | |||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | /** | ||
1487 | * cipso_v4_validate - Validate a CIPSO option | 1552 | * cipso_v4_validate - Validate a CIPSO option |
1488 | * @option: the start of the option, on error it is set to point to the error | 1553 | * @option: the start of the option, on error it is set to point to the error |
1489 | * | 1554 | * |
@@ -1502,7 +1567,7 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def, | |||
1502 | * that is unrecognized." | 1567 | * that is unrecognized." |
1503 | * | 1568 | * |
1504 | */ | 1569 | */ |
1505 | int cipso_v4_validate(unsigned char **option) | 1570 | int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) |
1506 | { | 1571 | { |
1507 | unsigned char *opt = *option; | 1572 | unsigned char *opt = *option; |
1508 | unsigned char *tag; | 1573 | unsigned char *tag; |
@@ -1527,7 +1592,7 @@ int cipso_v4_validate(unsigned char **option) | |||
1527 | goto validate_return_locked; | 1592 | goto validate_return_locked; |
1528 | } | 1593 | } |
1529 | 1594 | ||
1530 | opt_iter = 6; | 1595 | opt_iter = CIPSO_V4_HDR_LEN; |
1531 | tag = opt + opt_iter; | 1596 | tag = opt + opt_iter; |
1532 | while (opt_iter < opt_len) { | 1597 | while (opt_iter < opt_len) { |
1533 | for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];) | 1598 | for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];) |
@@ -1545,7 +1610,7 @@ int cipso_v4_validate(unsigned char **option) | |||
1545 | 1610 | ||
1546 | switch (tag[0]) { | 1611 | switch (tag[0]) { |
1547 | case CIPSO_V4_TAG_RBITMAP: | 1612 | case CIPSO_V4_TAG_RBITMAP: |
1548 | if (tag_len < 4) { | 1613 | if (tag_len < CIPSO_V4_TAG_RBM_BLEN) { |
1549 | err_offset = opt_iter + 1; | 1614 | err_offset = opt_iter + 1; |
1550 | goto validate_return_locked; | 1615 | goto validate_return_locked; |
1551 | } | 1616 | } |
@@ -1563,7 +1628,7 @@ int cipso_v4_validate(unsigned char **option) | |||
1563 | err_offset = opt_iter + 3; | 1628 | err_offset = opt_iter + 3; |
1564 | goto validate_return_locked; | 1629 | goto validate_return_locked; |
1565 | } | 1630 | } |
1566 | if (tag_len > 4 && | 1631 | if (tag_len > CIPSO_V4_TAG_RBM_BLEN && |
1567 | cipso_v4_map_cat_rbm_valid(doi_def, | 1632 | cipso_v4_map_cat_rbm_valid(doi_def, |
1568 | &tag[4], | 1633 | &tag[4], |
1569 | tag_len - 4) < 0) { | 1634 | tag_len - 4) < 0) { |
@@ -1573,7 +1638,7 @@ int cipso_v4_validate(unsigned char **option) | |||
1573 | } | 1638 | } |
1574 | break; | 1639 | break; |
1575 | case CIPSO_V4_TAG_ENUM: | 1640 | case CIPSO_V4_TAG_ENUM: |
1576 | if (tag_len < 4) { | 1641 | if (tag_len < CIPSO_V4_TAG_ENUM_BLEN) { |
1577 | err_offset = opt_iter + 1; | 1642 | err_offset = opt_iter + 1; |
1578 | goto validate_return_locked; | 1643 | goto validate_return_locked; |
1579 | } | 1644 | } |
@@ -1583,7 +1648,7 @@ int cipso_v4_validate(unsigned char **option) | |||
1583 | err_offset = opt_iter + 3; | 1648 | err_offset = opt_iter + 3; |
1584 | goto validate_return_locked; | 1649 | goto validate_return_locked; |
1585 | } | 1650 | } |
1586 | if (tag_len > 4 && | 1651 | if (tag_len > CIPSO_V4_TAG_ENUM_BLEN && |
1587 | cipso_v4_map_cat_enum_valid(doi_def, | 1652 | cipso_v4_map_cat_enum_valid(doi_def, |
1588 | &tag[4], | 1653 | &tag[4], |
1589 | tag_len - 4) < 0) { | 1654 | tag_len - 4) < 0) { |
@@ -1592,7 +1657,7 @@ int cipso_v4_validate(unsigned char **option) | |||
1592 | } | 1657 | } |
1593 | break; | 1658 | break; |
1594 | case CIPSO_V4_TAG_RANGE: | 1659 | case CIPSO_V4_TAG_RANGE: |
1595 | if (tag_len < 4) { | 1660 | if (tag_len < CIPSO_V4_TAG_RNG_BLEN) { |
1596 | err_offset = opt_iter + 1; | 1661 | err_offset = opt_iter + 1; |
1597 | goto validate_return_locked; | 1662 | goto validate_return_locked; |
1598 | } | 1663 | } |
@@ -1602,7 +1667,7 @@ int cipso_v4_validate(unsigned char **option) | |||
1602 | err_offset = opt_iter + 3; | 1667 | err_offset = opt_iter + 3; |
1603 | goto validate_return_locked; | 1668 | goto validate_return_locked; |
1604 | } | 1669 | } |
1605 | if (tag_len > 4 && | 1670 | if (tag_len > CIPSO_V4_TAG_RNG_BLEN && |
1606 | cipso_v4_map_cat_rng_valid(doi_def, | 1671 | cipso_v4_map_cat_rng_valid(doi_def, |
1607 | &tag[4], | 1672 | &tag[4], |
1608 | tag_len - 4) < 0) { | 1673 | tag_len - 4) < 0) { |
@@ -1610,6 +1675,19 @@ int cipso_v4_validate(unsigned char **option) | |||
1610 | goto validate_return_locked; | 1675 | goto validate_return_locked; |
1611 | } | 1676 | } |
1612 | break; | 1677 | break; |
1678 | case CIPSO_V4_TAG_LOCAL: | ||
1679 | /* This is a non-standard tag that we only allow for | ||
1680 | * local connections, so if the incoming interface is | ||
1681 | * not the loopback device drop the packet. */ | ||
1682 | if (!(skb->dev->flags & IFF_LOOPBACK)) { | ||
1683 | err_offset = opt_iter; | ||
1684 | goto validate_return_locked; | ||
1685 | } | ||
1686 | if (tag_len != CIPSO_V4_TAG_LOC_BLEN) { | ||
1687 | err_offset = opt_iter + 1; | ||
1688 | goto validate_return_locked; | ||
1689 | } | ||
1690 | break; | ||
1613 | default: | 1691 | default: |
1614 | err_offset = opt_iter; | 1692 | err_offset = opt_iter; |
1615 | goto validate_return_locked; | 1693 | goto validate_return_locked; |
@@ -1712,6 +1790,12 @@ static int cipso_v4_genopt(unsigned char *buf, u32 buf_len, | |||
1712 | &buf[CIPSO_V4_HDR_LEN], | 1790 | &buf[CIPSO_V4_HDR_LEN], |
1713 | buf_len - CIPSO_V4_HDR_LEN); | 1791 | buf_len - CIPSO_V4_HDR_LEN); |
1714 | break; | 1792 | break; |
1793 | case CIPSO_V4_TAG_LOCAL: | ||
1794 | ret_val = cipso_v4_gentag_loc(doi_def, | ||
1795 | secattr, | ||
1796 | &buf[CIPSO_V4_HDR_LEN], | ||
1797 | buf_len - CIPSO_V4_HDR_LEN); | ||
1798 | break; | ||
1715 | default: | 1799 | default: |
1716 | return -EPERM; | 1800 | return -EPERM; |
1717 | } | 1801 | } |
@@ -1921,6 +2005,9 @@ static int cipso_v4_getattr(const unsigned char *cipso, | |||
1921 | case CIPSO_V4_TAG_RANGE: | 2005 | case CIPSO_V4_TAG_RANGE: |
1922 | ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr); | 2006 | ret_val = cipso_v4_parsetag_rng(doi_def, &cipso[6], secattr); |
1923 | break; | 2007 | break; |
2008 | case CIPSO_V4_TAG_LOCAL: | ||
2009 | ret_val = cipso_v4_parsetag_loc(doi_def, &cipso[6], secattr); | ||
2010 | break; | ||
1924 | } | 2011 | } |
1925 | if (ret_val == 0) | 2012 | if (ret_val == 0) |
1926 | secattr->type = NETLBL_NLTYPE_CIPSOV4; | 2013 | secattr->type = NETLBL_NLTYPE_CIPSOV4; |