aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2008-10-10 10:16:34 -0400
committerPaul Moore <paul.moore@hp.com>2008-10-10 10:16:34 -0400
commit15c45f7b2e81655f6eb500ec949c8bd70a04325a (patch)
tree46037ccd3f3c83cb140abdf5d10af73888bdd362 /net/ipv4
parent8d75899d033617316e06296b7c0729612f56aba0 (diff)
cipso: Add support for native local labeling and fixup mapping names
This patch accomplishes three minor tasks: add a new tag type for local labeling, rename the CIPSO_V4_MAP_STD define to CIPSO_V4_MAP_TRANS and replace some of the CIPSO "magic numbers" with constants from the header file. The first change allows CIPSO to support full LSM labels/contexts, not just MLS attributes. The second change brings the mapping names inline with what userspace is using, compatibility is preserved since we don't actually change the value. The last change is to aid readability and help prevent mistakes. Signed-off-by: Paul Moore <paul.moore@hp.com>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/cipso_ipv4.c127
-rw-r--r--net/ipv4/ip_options.c2
2 files changed, 108 insertions, 21 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;
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index be3f18a7a40e..2c88da6e7862 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -438,7 +438,7 @@ int ip_options_compile(struct net *net,
438 goto error; 438 goto error;
439 } 439 }
440 opt->cipso = optptr - iph; 440 opt->cipso = optptr - iph;
441 if (cipso_v4_validate(&optptr)) { 441 if (cipso_v4_validate(skb, &optptr)) {
442 pp_ptr = optptr; 442 pp_ptr = optptr;
443 goto error; 443 goto error;
444 } 444 }