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.c127
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 */
1515static 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 */
1541static 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 */
1505int cipso_v4_validate(unsigned char **option) 1570int 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;