diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 191 |
1 files changed, 183 insertions, 8 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 82f36d396fca..256745321611 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -48,7 +48,7 @@ static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) | |||
48 | 48 | ||
49 | algp = RTA_DATA(rt); | 49 | algp = RTA_DATA(rt); |
50 | 50 | ||
51 | len -= (algp->alg_key_len + 7U) / 8; | 51 | len -= (algp->alg_key_len + 7U) / 8; |
52 | if (len < 0) | 52 | if (len < 0) |
53 | return -EINVAL; | 53 | return -EINVAL; |
54 | 54 | ||
@@ -1107,7 +1107,7 @@ static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) | |||
1107 | uctx->ctx_alg = s->ctx_alg; | 1107 | uctx->ctx_alg = s->ctx_alg; |
1108 | uctx->ctx_len = s->ctx_len; | 1108 | uctx->ctx_len = s->ctx_len; |
1109 | memcpy(uctx + 1, s->ctx_str, s->ctx_len); | 1109 | memcpy(uctx + 1, s->ctx_str, s->ctx_len); |
1110 | return 0; | 1110 | return 0; |
1111 | 1111 | ||
1112 | rtattr_failure: | 1112 | rtattr_failure: |
1113 | return -1; | 1113 | return -1; |
@@ -1273,10 +1273,6 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1273 | xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete); | 1273 | xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete); |
1274 | security_xfrm_policy_free(&tmp); | 1274 | security_xfrm_policy_free(&tmp); |
1275 | } | 1275 | } |
1276 | if (delete) | ||
1277 | xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, | ||
1278 | AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL); | ||
1279 | |||
1280 | if (xp == NULL) | 1276 | if (xp == NULL) |
1281 | return -ENOENT; | 1277 | return -ENOENT; |
1282 | 1278 | ||
@@ -1292,8 +1288,14 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1292 | MSG_DONTWAIT); | 1288 | MSG_DONTWAIT); |
1293 | } | 1289 | } |
1294 | } else { | 1290 | } else { |
1295 | if ((err = security_xfrm_policy_delete(xp)) != 0) | 1291 | err = security_xfrm_policy_delete(xp); |
1292 | |||
1293 | xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, | ||
1294 | AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL); | ||
1295 | |||
1296 | if (err != 0) | ||
1296 | goto out; | 1297 | goto out; |
1298 | |||
1297 | c.data.byid = p->index; | 1299 | c.data.byid = p->index; |
1298 | c.event = nlh->nlmsg_type; | 1300 | c.event = nlh->nlmsg_type; |
1299 | c.seq = nlh->nlmsg_seq; | 1301 | c.seq = nlh->nlmsg_seq; |
@@ -1632,6 +1634,176 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1632 | return 0; | 1634 | return 0; |
1633 | } | 1635 | } |
1634 | 1636 | ||
1637 | #ifdef CONFIG_XFRM_MIGRATE | ||
1638 | static int verify_user_migrate(struct rtattr **xfrma) | ||
1639 | { | ||
1640 | struct rtattr *rt = xfrma[XFRMA_MIGRATE-1]; | ||
1641 | struct xfrm_user_migrate *um; | ||
1642 | |||
1643 | if (!rt) | ||
1644 | return -EINVAL; | ||
1645 | |||
1646 | if ((rt->rta_len - sizeof(*rt)) < sizeof(*um)) | ||
1647 | return -EINVAL; | ||
1648 | |||
1649 | return 0; | ||
1650 | } | ||
1651 | |||
1652 | static int copy_from_user_migrate(struct xfrm_migrate *ma, | ||
1653 | struct rtattr **xfrma, int *num) | ||
1654 | { | ||
1655 | struct rtattr *rt = xfrma[XFRMA_MIGRATE-1]; | ||
1656 | struct xfrm_user_migrate *um; | ||
1657 | int i, num_migrate; | ||
1658 | |||
1659 | um = RTA_DATA(rt); | ||
1660 | num_migrate = (rt->rta_len - sizeof(*rt)) / sizeof(*um); | ||
1661 | |||
1662 | if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH) | ||
1663 | return -EINVAL; | ||
1664 | |||
1665 | for (i = 0; i < num_migrate; i++, um++, ma++) { | ||
1666 | memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr)); | ||
1667 | memcpy(&ma->old_saddr, &um->old_saddr, sizeof(ma->old_saddr)); | ||
1668 | memcpy(&ma->new_daddr, &um->new_daddr, sizeof(ma->new_daddr)); | ||
1669 | memcpy(&ma->new_saddr, &um->new_saddr, sizeof(ma->new_saddr)); | ||
1670 | |||
1671 | ma->proto = um->proto; | ||
1672 | ma->mode = um->mode; | ||
1673 | ma->reqid = um->reqid; | ||
1674 | |||
1675 | ma->old_family = um->old_family; | ||
1676 | ma->new_family = um->new_family; | ||
1677 | } | ||
1678 | |||
1679 | *num = i; | ||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
1683 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | ||
1684 | struct rtattr **xfrma) | ||
1685 | { | ||
1686 | struct xfrm_userpolicy_id *pi = NLMSG_DATA(nlh); | ||
1687 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; | ||
1688 | u8 type; | ||
1689 | int err; | ||
1690 | int n = 0; | ||
1691 | |||
1692 | err = verify_user_migrate((struct rtattr **)xfrma); | ||
1693 | if (err) | ||
1694 | return err; | ||
1695 | |||
1696 | err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); | ||
1697 | if (err) | ||
1698 | return err; | ||
1699 | |||
1700 | err = copy_from_user_migrate((struct xfrm_migrate *)m, | ||
1701 | (struct rtattr **)xfrma, &n); | ||
1702 | if (err) | ||
1703 | return err; | ||
1704 | |||
1705 | if (!n) | ||
1706 | return 0; | ||
1707 | |||
1708 | xfrm_migrate(&pi->sel, pi->dir, type, m, n); | ||
1709 | |||
1710 | return 0; | ||
1711 | } | ||
1712 | #else | ||
1713 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | ||
1714 | struct rtattr **xfrma) | ||
1715 | { | ||
1716 | return -ENOPROTOOPT; | ||
1717 | } | ||
1718 | #endif | ||
1719 | |||
1720 | #ifdef CONFIG_XFRM_MIGRATE | ||
1721 | static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb) | ||
1722 | { | ||
1723 | struct xfrm_user_migrate um; | ||
1724 | |||
1725 | memset(&um, 0, sizeof(um)); | ||
1726 | um.proto = m->proto; | ||
1727 | um.mode = m->mode; | ||
1728 | um.reqid = m->reqid; | ||
1729 | um.old_family = m->old_family; | ||
1730 | memcpy(&um.old_daddr, &m->old_daddr, sizeof(um.old_daddr)); | ||
1731 | memcpy(&um.old_saddr, &m->old_saddr, sizeof(um.old_saddr)); | ||
1732 | um.new_family = m->new_family; | ||
1733 | memcpy(&um.new_daddr, &m->new_daddr, sizeof(um.new_daddr)); | ||
1734 | memcpy(&um.new_saddr, &m->new_saddr, sizeof(um.new_saddr)); | ||
1735 | |||
1736 | RTA_PUT(skb, XFRMA_MIGRATE, sizeof(um), &um); | ||
1737 | return 0; | ||
1738 | |||
1739 | rtattr_failure: | ||
1740 | return -1; | ||
1741 | } | ||
1742 | |||
1743 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | ||
1744 | int num_migrate, struct xfrm_selector *sel, | ||
1745 | u8 dir, u8 type) | ||
1746 | { | ||
1747 | struct xfrm_migrate *mp; | ||
1748 | struct xfrm_userpolicy_id *pol_id; | ||
1749 | struct nlmsghdr *nlh; | ||
1750 | unsigned char *b = skb->tail; | ||
1751 | int i; | ||
1752 | |||
1753 | nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id)); | ||
1754 | pol_id = NLMSG_DATA(nlh); | ||
1755 | nlh->nlmsg_flags = 0; | ||
1756 | |||
1757 | /* copy data from selector, dir, and type to the pol_id */ | ||
1758 | memset(pol_id, 0, sizeof(*pol_id)); | ||
1759 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); | ||
1760 | pol_id->dir = dir; | ||
1761 | |||
1762 | if (copy_to_user_policy_type(type, skb) < 0) | ||
1763 | goto nlmsg_failure; | ||
1764 | |||
1765 | for (i = 0, mp = m ; i < num_migrate; i++, mp++) { | ||
1766 | if (copy_to_user_migrate(mp, skb) < 0) | ||
1767 | goto nlmsg_failure; | ||
1768 | } | ||
1769 | |||
1770 | nlh->nlmsg_len = skb->tail - b; | ||
1771 | return skb->len; | ||
1772 | nlmsg_failure: | ||
1773 | skb_trim(skb, b - skb->data); | ||
1774 | return -1; | ||
1775 | } | ||
1776 | |||
1777 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | ||
1778 | struct xfrm_migrate *m, int num_migrate) | ||
1779 | { | ||
1780 | struct sk_buff *skb; | ||
1781 | size_t len; | ||
1782 | |||
1783 | len = RTA_SPACE(sizeof(struct xfrm_user_migrate) * num_migrate); | ||
1784 | len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_id)); | ||
1785 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
1786 | len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type)); | ||
1787 | #endif | ||
1788 | skb = alloc_skb(len, GFP_ATOMIC); | ||
1789 | if (skb == NULL) | ||
1790 | return -ENOMEM; | ||
1791 | |||
1792 | /* build migrate */ | ||
1793 | if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0) | ||
1794 | BUG(); | ||
1795 | |||
1796 | NETLINK_CB(skb).dst_group = XFRMNLGRP_MIGRATE; | ||
1797 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, | ||
1798 | GFP_ATOMIC); | ||
1799 | } | ||
1800 | #else | ||
1801 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | ||
1802 | struct xfrm_migrate *m, int num_migrate) | ||
1803 | { | ||
1804 | return -ENOPROTOOPT; | ||
1805 | } | ||
1806 | #endif | ||
1635 | 1807 | ||
1636 | #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) | 1808 | #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) |
1637 | 1809 | ||
@@ -1653,6 +1825,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { | |||
1653 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), | 1825 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), |
1654 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), | 1826 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), |
1655 | [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), | 1827 | [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), |
1828 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), | ||
1656 | }; | 1829 | }; |
1657 | 1830 | ||
1658 | #undef XMSGSIZE | 1831 | #undef XMSGSIZE |
@@ -1679,6 +1852,7 @@ static struct xfrm_link { | |||
1679 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, | 1852 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, |
1680 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, | 1853 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, |
1681 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, | 1854 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, |
1855 | [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, | ||
1682 | }; | 1856 | }; |
1683 | 1857 | ||
1684 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | 1858 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) |
@@ -2285,6 +2459,7 @@ static struct xfrm_mgr netlink_mgr = { | |||
2285 | .compile_policy = xfrm_compile_policy, | 2459 | .compile_policy = xfrm_compile_policy, |
2286 | .notify_policy = xfrm_send_policy_notify, | 2460 | .notify_policy = xfrm_send_policy_notify, |
2287 | .report = xfrm_send_report, | 2461 | .report = xfrm_send_report, |
2462 | .migrate = xfrm_send_migrate, | ||
2288 | }; | 2463 | }; |
2289 | 2464 | ||
2290 | static int __init xfrm_user_init(void) | 2465 | static int __init xfrm_user_init(void) |
@@ -2294,7 +2469,7 @@ static int __init xfrm_user_init(void) | |||
2294 | printk(KERN_INFO "Initializing XFRM netlink socket\n"); | 2469 | printk(KERN_INFO "Initializing XFRM netlink socket\n"); |
2295 | 2470 | ||
2296 | nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, | 2471 | nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, |
2297 | xfrm_netlink_rcv, THIS_MODULE); | 2472 | xfrm_netlink_rcv, THIS_MODULE); |
2298 | if (nlsk == NULL) | 2473 | if (nlsk == NULL) |
2299 | return -ENOMEM; | 2474 | return -ENOMEM; |
2300 | rcu_assign_pointer(xfrm_nl, nlsk); | 2475 | rcu_assign_pointer(xfrm_nl, nlsk); |