diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 111 |
1 files changed, 93 insertions, 18 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d5a712976004..6106b72826d3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -446,6 +446,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, | |||
446 | goto error; | 446 | goto error; |
447 | } | 447 | } |
448 | 448 | ||
449 | xfrm_mark_get(attrs, &x->mark); | ||
450 | |||
449 | err = xfrm_init_state(x); | 451 | err = xfrm_init_state(x); |
450 | if (err) | 452 | if (err) |
451 | goto error; | 453 | goto error; |
@@ -526,11 +528,13 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, | |||
526 | int *errp) | 528 | int *errp) |
527 | { | 529 | { |
528 | struct xfrm_state *x = NULL; | 530 | struct xfrm_state *x = NULL; |
531 | struct xfrm_mark m; | ||
529 | int err; | 532 | int err; |
533 | u32 mark = xfrm_mark_get(attrs, &m); | ||
530 | 534 | ||
531 | if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { | 535 | if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { |
532 | err = -ESRCH; | 536 | err = -ESRCH; |
533 | x = xfrm_state_lookup(net, &p->daddr, p->spi, p->proto, p->family); | 537 | x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family); |
534 | } else { | 538 | } else { |
535 | xfrm_address_t *saddr = NULL; | 539 | xfrm_address_t *saddr = NULL; |
536 | 540 | ||
@@ -541,7 +545,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, | |||
541 | } | 545 | } |
542 | 546 | ||
543 | err = -ESRCH; | 547 | err = -ESRCH; |
544 | x = xfrm_state_lookup_byaddr(net, &p->daddr, saddr, | 548 | x = xfrm_state_lookup_byaddr(net, mark, |
549 | &p->daddr, saddr, | ||
545 | p->proto, p->family); | 550 | p->proto, p->family); |
546 | } | 551 | } |
547 | 552 | ||
@@ -683,6 +688,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x, | |||
683 | if (x->encap) | 688 | if (x->encap) |
684 | NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); | 689 | NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); |
685 | 690 | ||
691 | if (xfrm_mark_put(skb, &x->mark)) | ||
692 | goto nla_put_failure; | ||
693 | |||
686 | if (x->security && copy_sec_ctx(x->security, skb) < 0) | 694 | if (x->security && copy_sec_ctx(x->security, skb) < 0) |
687 | goto nla_put_failure; | 695 | goto nla_put_failure; |
688 | 696 | ||
@@ -947,6 +955,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
947 | xfrm_address_t *daddr; | 955 | xfrm_address_t *daddr; |
948 | int family; | 956 | int family; |
949 | int err; | 957 | int err; |
958 | u32 mark; | ||
959 | struct xfrm_mark m; | ||
950 | 960 | ||
951 | p = nlmsg_data(nlh); | 961 | p = nlmsg_data(nlh); |
952 | err = verify_userspi_info(p); | 962 | err = verify_userspi_info(p); |
@@ -957,8 +967,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
957 | daddr = &p->info.id.daddr; | 967 | daddr = &p->info.id.daddr; |
958 | 968 | ||
959 | x = NULL; | 969 | x = NULL; |
970 | |||
971 | mark = xfrm_mark_get(attrs, &m); | ||
960 | if (p->info.seq) { | 972 | if (p->info.seq) { |
961 | x = xfrm_find_acq_byseq(net, p->info.seq); | 973 | x = xfrm_find_acq_byseq(net, mark, p->info.seq); |
962 | if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { | 974 | if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { |
963 | xfrm_state_put(x); | 975 | xfrm_state_put(x); |
964 | x = NULL; | 976 | x = NULL; |
@@ -966,7 +978,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
966 | } | 978 | } |
967 | 979 | ||
968 | if (!x) | 980 | if (!x) |
969 | x = xfrm_find_acq(net, p->info.mode, p->info.reqid, | 981 | x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid, |
970 | p->info.id.proto, daddr, | 982 | p->info.id.proto, daddr, |
971 | &p->info.saddr, 1, | 983 | &p->info.saddr, 1, |
972 | family); | 984 | family); |
@@ -1220,6 +1232,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us | |||
1220 | if (err) | 1232 | if (err) |
1221 | goto error; | 1233 | goto error; |
1222 | 1234 | ||
1235 | xfrm_mark_get(attrs, &xp->mark); | ||
1236 | |||
1223 | return xp; | 1237 | return xp; |
1224 | error: | 1238 | error: |
1225 | *errp = err; | 1239 | *errp = err; |
@@ -1366,10 +1380,13 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr | |||
1366 | goto nlmsg_failure; | 1380 | goto nlmsg_failure; |
1367 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 1381 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
1368 | goto nlmsg_failure; | 1382 | goto nlmsg_failure; |
1383 | if (xfrm_mark_put(skb, &xp->mark)) | ||
1384 | goto nla_put_failure; | ||
1369 | 1385 | ||
1370 | nlmsg_end(skb, nlh); | 1386 | nlmsg_end(skb, nlh); |
1371 | return 0; | 1387 | return 0; |
1372 | 1388 | ||
1389 | nla_put_failure: | ||
1373 | nlmsg_failure: | 1390 | nlmsg_failure: |
1374 | nlmsg_cancel(skb, nlh); | 1391 | nlmsg_cancel(skb, nlh); |
1375 | return -EMSGSIZE; | 1392 | return -EMSGSIZE; |
@@ -1441,6 +1458,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1441 | int err; | 1458 | int err; |
1442 | struct km_event c; | 1459 | struct km_event c; |
1443 | int delete; | 1460 | int delete; |
1461 | struct xfrm_mark m; | ||
1462 | u32 mark = xfrm_mark_get(attrs, &m); | ||
1444 | 1463 | ||
1445 | p = nlmsg_data(nlh); | 1464 | p = nlmsg_data(nlh); |
1446 | delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; | 1465 | delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; |
@@ -1454,7 +1473,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1454 | return err; | 1473 | return err; |
1455 | 1474 | ||
1456 | if (p->index) | 1475 | if (p->index) |
1457 | xp = xfrm_policy_byid(net, type, p->dir, p->index, delete, &err); | 1476 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err); |
1458 | else { | 1477 | else { |
1459 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1478 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1460 | struct xfrm_sec_ctx *ctx; | 1479 | struct xfrm_sec_ctx *ctx; |
@@ -1471,8 +1490,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1471 | if (err) | 1490 | if (err) |
1472 | return err; | 1491 | return err; |
1473 | } | 1492 | } |
1474 | xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, | 1493 | xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel, |
1475 | delete, &err); | 1494 | ctx, delete, &err); |
1476 | security_xfrm_policy_free(ctx); | 1495 | security_xfrm_policy_free(ctx); |
1477 | } | 1496 | } |
1478 | if (xp == NULL) | 1497 | if (xp == NULL) |
@@ -1524,8 +1543,11 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1524 | audit_info.sessionid = NETLINK_CB(skb).sessionid; | 1543 | audit_info.sessionid = NETLINK_CB(skb).sessionid; |
1525 | audit_info.secid = NETLINK_CB(skb).sid; | 1544 | audit_info.secid = NETLINK_CB(skb).sid; |
1526 | err = xfrm_state_flush(net, p->proto, &audit_info); | 1545 | err = xfrm_state_flush(net, p->proto, &audit_info); |
1527 | if (err) | 1546 | if (err) { |
1547 | if (err == -ESRCH) /* empty table */ | ||
1548 | return 0; | ||
1528 | return err; | 1549 | return err; |
1550 | } | ||
1529 | c.data.proto = p->proto; | 1551 | c.data.proto = p->proto; |
1530 | c.event = nlh->nlmsg_type; | 1552 | c.event = nlh->nlmsg_type; |
1531 | c.seq = nlh->nlmsg_seq; | 1553 | c.seq = nlh->nlmsg_seq; |
@@ -1541,6 +1563,7 @@ static inline size_t xfrm_aevent_msgsize(void) | |||
1541 | return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) | 1563 | return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) |
1542 | + nla_total_size(sizeof(struct xfrm_replay_state)) | 1564 | + nla_total_size(sizeof(struct xfrm_replay_state)) |
1543 | + nla_total_size(sizeof(struct xfrm_lifetime_cur)) | 1565 | + nla_total_size(sizeof(struct xfrm_lifetime_cur)) |
1566 | + nla_total_size(sizeof(struct xfrm_mark)) | ||
1544 | + nla_total_size(4) /* XFRM_AE_RTHR */ | 1567 | + nla_total_size(4) /* XFRM_AE_RTHR */ |
1545 | + nla_total_size(4); /* XFRM_AE_ETHR */ | 1568 | + nla_total_size(4); /* XFRM_AE_ETHR */ |
1546 | } | 1569 | } |
@@ -1573,6 +1596,9 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve | |||
1573 | NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, | 1596 | NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, |
1574 | x->replay_maxage * 10 / HZ); | 1597 | x->replay_maxage * 10 / HZ); |
1575 | 1598 | ||
1599 | if (xfrm_mark_put(skb, &x->mark)) | ||
1600 | goto nla_put_failure; | ||
1601 | |||
1576 | return nlmsg_end(skb, nlh); | 1602 | return nlmsg_end(skb, nlh); |
1577 | 1603 | ||
1578 | nla_put_failure: | 1604 | nla_put_failure: |
@@ -1588,6 +1614,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1588 | struct sk_buff *r_skb; | 1614 | struct sk_buff *r_skb; |
1589 | int err; | 1615 | int err; |
1590 | struct km_event c; | 1616 | struct km_event c; |
1617 | u32 mark; | ||
1618 | struct xfrm_mark m; | ||
1591 | struct xfrm_aevent_id *p = nlmsg_data(nlh); | 1619 | struct xfrm_aevent_id *p = nlmsg_data(nlh); |
1592 | struct xfrm_usersa_id *id = &p->sa_id; | 1620 | struct xfrm_usersa_id *id = &p->sa_id; |
1593 | 1621 | ||
@@ -1595,7 +1623,9 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1595 | if (r_skb == NULL) | 1623 | if (r_skb == NULL) |
1596 | return -ENOMEM; | 1624 | return -ENOMEM; |
1597 | 1625 | ||
1598 | x = xfrm_state_lookup(net, &id->daddr, id->spi, id->proto, id->family); | 1626 | mark = xfrm_mark_get(attrs, &m); |
1627 | |||
1628 | x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); | ||
1599 | if (x == NULL) { | 1629 | if (x == NULL) { |
1600 | kfree_skb(r_skb); | 1630 | kfree_skb(r_skb); |
1601 | return -ESRCH; | 1631 | return -ESRCH; |
@@ -1626,6 +1656,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1626 | struct xfrm_state *x; | 1656 | struct xfrm_state *x; |
1627 | struct km_event c; | 1657 | struct km_event c; |
1628 | int err = - EINVAL; | 1658 | int err = - EINVAL; |
1659 | u32 mark = 0; | ||
1660 | struct xfrm_mark m; | ||
1629 | struct xfrm_aevent_id *p = nlmsg_data(nlh); | 1661 | struct xfrm_aevent_id *p = nlmsg_data(nlh); |
1630 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; | 1662 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; |
1631 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; | 1663 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; |
@@ -1637,7 +1669,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1637 | if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) | 1669 | if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) |
1638 | return err; | 1670 | return err; |
1639 | 1671 | ||
1640 | x = xfrm_state_lookup(net, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); | 1672 | mark = xfrm_mark_get(attrs, &m); |
1673 | |||
1674 | x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); | ||
1641 | if (x == NULL) | 1675 | if (x == NULL) |
1642 | return -ESRCH; | 1676 | return -ESRCH; |
1643 | 1677 | ||
@@ -1676,8 +1710,12 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1676 | audit_info.sessionid = NETLINK_CB(skb).sessionid; | 1710 | audit_info.sessionid = NETLINK_CB(skb).sessionid; |
1677 | audit_info.secid = NETLINK_CB(skb).sid; | 1711 | audit_info.secid = NETLINK_CB(skb).sid; |
1678 | err = xfrm_policy_flush(net, type, &audit_info); | 1712 | err = xfrm_policy_flush(net, type, &audit_info); |
1679 | if (err) | 1713 | if (err) { |
1714 | if (err == -ESRCH) /* empty table */ | ||
1715 | return 0; | ||
1680 | return err; | 1716 | return err; |
1717 | } | ||
1718 | |||
1681 | c.data.type = type; | 1719 | c.data.type = type; |
1682 | c.event = nlh->nlmsg_type; | 1720 | c.event = nlh->nlmsg_type; |
1683 | c.seq = nlh->nlmsg_seq; | 1721 | c.seq = nlh->nlmsg_seq; |
@@ -1696,13 +1734,15 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1696 | struct xfrm_userpolicy_info *p = &up->pol; | 1734 | struct xfrm_userpolicy_info *p = &up->pol; |
1697 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1735 | u8 type = XFRM_POLICY_TYPE_MAIN; |
1698 | int err = -ENOENT; | 1736 | int err = -ENOENT; |
1737 | struct xfrm_mark m; | ||
1738 | u32 mark = xfrm_mark_get(attrs, &m); | ||
1699 | 1739 | ||
1700 | err = copy_from_user_policy_type(&type, attrs); | 1740 | err = copy_from_user_policy_type(&type, attrs); |
1701 | if (err) | 1741 | if (err) |
1702 | return err; | 1742 | return err; |
1703 | 1743 | ||
1704 | if (p->index) | 1744 | if (p->index) |
1705 | xp = xfrm_policy_byid(net, type, p->dir, p->index, 0, &err); | 1745 | xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); |
1706 | else { | 1746 | else { |
1707 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1747 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1708 | struct xfrm_sec_ctx *ctx; | 1748 | struct xfrm_sec_ctx *ctx; |
@@ -1719,7 +1759,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1719 | if (err) | 1759 | if (err) |
1720 | return err; | 1760 | return err; |
1721 | } | 1761 | } |
1722 | xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, 0, &err); | 1762 | xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, |
1763 | &p->sel, ctx, 0, &err); | ||
1723 | security_xfrm_policy_free(ctx); | 1764 | security_xfrm_policy_free(ctx); |
1724 | } | 1765 | } |
1725 | if (xp == NULL) | 1766 | if (xp == NULL) |
@@ -1759,8 +1800,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1759 | int err; | 1800 | int err; |
1760 | struct xfrm_user_expire *ue = nlmsg_data(nlh); | 1801 | struct xfrm_user_expire *ue = nlmsg_data(nlh); |
1761 | struct xfrm_usersa_info *p = &ue->state; | 1802 | struct xfrm_usersa_info *p = &ue->state; |
1803 | struct xfrm_mark m; | ||
1804 | u32 mark = xfrm_mark_get(attrs, &m);; | ||
1762 | 1805 | ||
1763 | x = xfrm_state_lookup(net, &p->id.daddr, p->id.spi, p->id.proto, p->family); | 1806 | x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); |
1764 | 1807 | ||
1765 | err = -ENOENT; | 1808 | err = -ENOENT; |
1766 | if (x == NULL) | 1809 | if (x == NULL) |
@@ -1794,6 +1837,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1794 | struct xfrm_user_tmpl *ut; | 1837 | struct xfrm_user_tmpl *ut; |
1795 | int i; | 1838 | int i; |
1796 | struct nlattr *rt = attrs[XFRMA_TMPL]; | 1839 | struct nlattr *rt = attrs[XFRMA_TMPL]; |
1840 | struct xfrm_mark mark; | ||
1797 | 1841 | ||
1798 | struct xfrm_user_acquire *ua = nlmsg_data(nlh); | 1842 | struct xfrm_user_acquire *ua = nlmsg_data(nlh); |
1799 | struct xfrm_state *x = xfrm_state_alloc(net); | 1843 | struct xfrm_state *x = xfrm_state_alloc(net); |
@@ -1802,6 +1846,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1802 | if (!x) | 1846 | if (!x) |
1803 | goto nomem; | 1847 | goto nomem; |
1804 | 1848 | ||
1849 | xfrm_mark_get(attrs, &mark); | ||
1850 | |||
1805 | err = verify_newpolicy_info(&ua->policy); | 1851 | err = verify_newpolicy_info(&ua->policy); |
1806 | if (err) | 1852 | if (err) |
1807 | goto bad_policy; | 1853 | goto bad_policy; |
@@ -1814,7 +1860,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1814 | memcpy(&x->id, &ua->id, sizeof(ua->id)); | 1860 | memcpy(&x->id, &ua->id, sizeof(ua->id)); |
1815 | memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); | 1861 | memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); |
1816 | memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); | 1862 | memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); |
1817 | 1863 | xp->mark.m = x->mark.m = mark.m; | |
1864 | xp->mark.v = x->mark.v = mark.v; | ||
1818 | ut = nla_data(rt); | 1865 | ut = nla_data(rt); |
1819 | /* extract the templates and for each call km_key */ | 1866 | /* extract the templates and for each call km_key */ |
1820 | for (i = 0; i < xp->xfrm_nr; i++, ut++) { | 1867 | for (i = 0; i < xp->xfrm_nr; i++, ut++) { |
@@ -2054,6 +2101,10 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { | |||
2054 | #undef XMSGSIZE | 2101 | #undef XMSGSIZE |
2055 | 2102 | ||
2056 | static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | 2103 | static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { |
2104 | [XFRMA_SA] = { .len = sizeof(struct xfrm_usersa_info)}, | ||
2105 | [XFRMA_POLICY] = { .len = sizeof(struct xfrm_userpolicy_info)}, | ||
2106 | [XFRMA_LASTUSED] = { .type = NLA_U64}, | ||
2107 | [XFRMA_ALG_AUTH_TRUNC] = { .len = sizeof(struct xfrm_algo_auth)}, | ||
2057 | [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, | 2108 | [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, |
2058 | [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, | 2109 | [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, |
2059 | [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, | 2110 | [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, |
@@ -2070,6 +2121,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
2070 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, | 2121 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, |
2071 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, | 2122 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, |
2072 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, | 2123 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, |
2124 | [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, | ||
2073 | }; | 2125 | }; |
2074 | 2126 | ||
2075 | static struct xfrm_link { | 2127 | static struct xfrm_link { |
@@ -2149,7 +2201,8 @@ static void xfrm_netlink_rcv(struct sk_buff *skb) | |||
2149 | 2201 | ||
2150 | static inline size_t xfrm_expire_msgsize(void) | 2202 | static inline size_t xfrm_expire_msgsize(void) |
2151 | { | 2203 | { |
2152 | return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)); | 2204 | return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)) |
2205 | + nla_total_size(sizeof(struct xfrm_mark)); | ||
2153 | } | 2206 | } |
2154 | 2207 | ||
2155 | static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) | 2208 | static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) |
@@ -2165,7 +2218,13 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve | |||
2165 | copy_to_user_state(x, &ue->state); | 2218 | copy_to_user_state(x, &ue->state); |
2166 | ue->hard = (c->data.hard != 0) ? 1 : 0; | 2219 | ue->hard = (c->data.hard != 0) ? 1 : 0; |
2167 | 2220 | ||
2221 | if (xfrm_mark_put(skb, &x->mark)) | ||
2222 | goto nla_put_failure; | ||
2223 | |||
2168 | return nlmsg_end(skb, nlh); | 2224 | return nlmsg_end(skb, nlh); |
2225 | |||
2226 | nla_put_failure: | ||
2227 | return -EMSGSIZE; | ||
2169 | } | 2228 | } |
2170 | 2229 | ||
2171 | static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) | 2230 | static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) |
@@ -2177,8 +2236,10 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) | |||
2177 | if (skb == NULL) | 2236 | if (skb == NULL) |
2178 | return -ENOMEM; | 2237 | return -ENOMEM; |
2179 | 2238 | ||
2180 | if (build_expire(skb, x, c) < 0) | 2239 | if (build_expire(skb, x, c) < 0) { |
2181 | BUG(); | 2240 | kfree_skb(skb); |
2241 | return -EMSGSIZE; | ||
2242 | } | ||
2182 | 2243 | ||
2183 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); | 2244 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
2184 | } | 2245 | } |
@@ -2266,6 +2327,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) | |||
2266 | if (c->event == XFRM_MSG_DELSA) { | 2327 | if (c->event == XFRM_MSG_DELSA) { |
2267 | len += nla_total_size(headlen); | 2328 | len += nla_total_size(headlen); |
2268 | headlen = sizeof(*id); | 2329 | headlen = sizeof(*id); |
2330 | len += nla_total_size(sizeof(struct xfrm_mark)); | ||
2269 | } | 2331 | } |
2270 | len += NLMSG_ALIGN(headlen); | 2332 | len += NLMSG_ALIGN(headlen); |
2271 | 2333 | ||
@@ -2336,6 +2398,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x, | |||
2336 | { | 2398 | { |
2337 | return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) | 2399 | return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) |
2338 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) | 2400 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) |
2401 | + nla_total_size(sizeof(struct xfrm_mark)) | ||
2339 | + nla_total_size(xfrm_user_sec_ctx_size(x->security)) | 2402 | + nla_total_size(xfrm_user_sec_ctx_size(x->security)) |
2340 | + userpolicy_type_attrsize(); | 2403 | + userpolicy_type_attrsize(); |
2341 | } | 2404 | } |
@@ -2368,9 +2431,12 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, | |||
2368 | goto nlmsg_failure; | 2431 | goto nlmsg_failure; |
2369 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2432 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2370 | goto nlmsg_failure; | 2433 | goto nlmsg_failure; |
2434 | if (xfrm_mark_put(skb, &xp->mark)) | ||
2435 | goto nla_put_failure; | ||
2371 | 2436 | ||
2372 | return nlmsg_end(skb, nlh); | 2437 | return nlmsg_end(skb, nlh); |
2373 | 2438 | ||
2439 | nla_put_failure: | ||
2374 | nlmsg_failure: | 2440 | nlmsg_failure: |
2375 | nlmsg_cancel(skb, nlh); | 2441 | nlmsg_cancel(skb, nlh); |
2376 | return -EMSGSIZE; | 2442 | return -EMSGSIZE; |
@@ -2457,6 +2523,7 @@ static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp) | |||
2457 | return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire)) | 2523 | return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire)) |
2458 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) | 2524 | + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) |
2459 | + nla_total_size(xfrm_user_sec_ctx_size(xp->security)) | 2525 | + nla_total_size(xfrm_user_sec_ctx_size(xp->security)) |
2526 | + nla_total_size(sizeof(struct xfrm_mark)) | ||
2460 | + userpolicy_type_attrsize(); | 2527 | + userpolicy_type_attrsize(); |
2461 | } | 2528 | } |
2462 | 2529 | ||
@@ -2479,10 +2546,13 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, | |||
2479 | goto nlmsg_failure; | 2546 | goto nlmsg_failure; |
2480 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2547 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2481 | goto nlmsg_failure; | 2548 | goto nlmsg_failure; |
2549 | if (xfrm_mark_put(skb, &xp->mark)) | ||
2550 | goto nla_put_failure; | ||
2482 | upe->hard = !!hard; | 2551 | upe->hard = !!hard; |
2483 | 2552 | ||
2484 | return nlmsg_end(skb, nlh); | 2553 | return nlmsg_end(skb, nlh); |
2485 | 2554 | ||
2555 | nla_put_failure: | ||
2486 | nlmsg_failure: | 2556 | nlmsg_failure: |
2487 | nlmsg_cancel(skb, nlh); | 2557 | nlmsg_cancel(skb, nlh); |
2488 | return -EMSGSIZE; | 2558 | return -EMSGSIZE; |
@@ -2519,6 +2589,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * | |||
2519 | headlen = sizeof(*id); | 2589 | headlen = sizeof(*id); |
2520 | } | 2590 | } |
2521 | len += userpolicy_type_attrsize(); | 2591 | len += userpolicy_type_attrsize(); |
2592 | len += nla_total_size(sizeof(struct xfrm_mark)); | ||
2522 | len += NLMSG_ALIGN(headlen); | 2593 | len += NLMSG_ALIGN(headlen); |
2523 | 2594 | ||
2524 | skb = nlmsg_new(len, GFP_ATOMIC); | 2595 | skb = nlmsg_new(len, GFP_ATOMIC); |
@@ -2554,10 +2625,14 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * | |||
2554 | if (copy_to_user_policy_type(xp->type, skb) < 0) | 2625 | if (copy_to_user_policy_type(xp->type, skb) < 0) |
2555 | goto nlmsg_failure; | 2626 | goto nlmsg_failure; |
2556 | 2627 | ||
2628 | if (xfrm_mark_put(skb, &xp->mark)) | ||
2629 | goto nla_put_failure; | ||
2630 | |||
2557 | nlmsg_end(skb, nlh); | 2631 | nlmsg_end(skb, nlh); |
2558 | 2632 | ||
2559 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); | 2633 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
2560 | 2634 | ||
2635 | nla_put_failure: | ||
2561 | nlmsg_failure: | 2636 | nlmsg_failure: |
2562 | kfree_skb(skb); | 2637 | kfree_skb(skb); |
2563 | return -1; | 2638 | return -1; |