diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 04c41504f84c..4a8a1abb59ee 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1102,7 +1102,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, | |||
1102 | return xp; | 1102 | return xp; |
1103 | error: | 1103 | error: |
1104 | *errp = err; | 1104 | *errp = err; |
1105 | xp->dead = 1; | 1105 | xp->walk.dead = 1; |
1106 | xfrm_policy_destroy(xp); | 1106 | xfrm_policy_destroy(xp); |
1107 | return NULL; | 1107 | return NULL; |
1108 | } | 1108 | } |
@@ -1595,7 +1595,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1595 | return -ENOENT; | 1595 | return -ENOENT; |
1596 | 1596 | ||
1597 | read_lock(&xp->lock); | 1597 | read_lock(&xp->lock); |
1598 | if (xp->dead) { | 1598 | if (xp->walk.dead) { |
1599 | read_unlock(&xp->lock); | 1599 | read_unlock(&xp->lock); |
1600 | goto out; | 1600 | goto out; |
1601 | } | 1601 | } |
@@ -1710,12 +1710,23 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1710 | 1710 | ||
1711 | #ifdef CONFIG_XFRM_MIGRATE | 1711 | #ifdef CONFIG_XFRM_MIGRATE |
1712 | static int copy_from_user_migrate(struct xfrm_migrate *ma, | 1712 | static int copy_from_user_migrate(struct xfrm_migrate *ma, |
1713 | struct xfrm_kmaddress *k, | ||
1713 | struct nlattr **attrs, int *num) | 1714 | struct nlattr **attrs, int *num) |
1714 | { | 1715 | { |
1715 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; | 1716 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; |
1716 | struct xfrm_user_migrate *um; | 1717 | struct xfrm_user_migrate *um; |
1717 | int i, num_migrate; | 1718 | int i, num_migrate; |
1718 | 1719 | ||
1720 | if (k != NULL) { | ||
1721 | struct xfrm_user_kmaddress *uk; | ||
1722 | |||
1723 | uk = nla_data(attrs[XFRMA_KMADDRESS]); | ||
1724 | memcpy(&k->local, &uk->local, sizeof(k->local)); | ||
1725 | memcpy(&k->remote, &uk->remote, sizeof(k->remote)); | ||
1726 | k->family = uk->family; | ||
1727 | k->reserved = uk->reserved; | ||
1728 | } | ||
1729 | |||
1719 | um = nla_data(rt); | 1730 | um = nla_data(rt); |
1720 | num_migrate = nla_len(rt) / sizeof(*um); | 1731 | num_migrate = nla_len(rt) / sizeof(*um); |
1721 | 1732 | ||
@@ -1745,6 +1756,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1745 | { | 1756 | { |
1746 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); | 1757 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); |
1747 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; | 1758 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; |
1759 | struct xfrm_kmaddress km, *kmp; | ||
1748 | u8 type; | 1760 | u8 type; |
1749 | int err; | 1761 | int err; |
1750 | int n = 0; | 1762 | int n = 0; |
@@ -1752,19 +1764,20 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1752 | if (attrs[XFRMA_MIGRATE] == NULL) | 1764 | if (attrs[XFRMA_MIGRATE] == NULL) |
1753 | return -EINVAL; | 1765 | return -EINVAL; |
1754 | 1766 | ||
1767 | kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; | ||
1768 | |||
1755 | err = copy_from_user_policy_type(&type, attrs); | 1769 | err = copy_from_user_policy_type(&type, attrs); |
1756 | if (err) | 1770 | if (err) |
1757 | return err; | 1771 | return err; |
1758 | 1772 | ||
1759 | err = copy_from_user_migrate((struct xfrm_migrate *)m, | 1773 | err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n); |
1760 | attrs, &n); | ||
1761 | if (err) | 1774 | if (err) |
1762 | return err; | 1775 | return err; |
1763 | 1776 | ||
1764 | if (!n) | 1777 | if (!n) |
1765 | return 0; | 1778 | return 0; |
1766 | 1779 | ||
1767 | xfrm_migrate(&pi->sel, pi->dir, type, m, n); | 1780 | xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp); |
1768 | 1781 | ||
1769 | return 0; | 1782 | return 0; |
1770 | } | 1783 | } |
@@ -1795,16 +1808,30 @@ static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb) | |||
1795 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); | 1808 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); |
1796 | } | 1809 | } |
1797 | 1810 | ||
1798 | static inline size_t xfrm_migrate_msgsize(int num_migrate) | 1811 | static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb) |
1812 | { | ||
1813 | struct xfrm_user_kmaddress uk; | ||
1814 | |||
1815 | memset(&uk, 0, sizeof(uk)); | ||
1816 | uk.family = k->family; | ||
1817 | uk.reserved = k->reserved; | ||
1818 | memcpy(&uk.local, &k->local, sizeof(uk.local)); | ||
1819 | memcpy(&uk.remote, &k->local, sizeof(uk.remote)); | ||
1820 | |||
1821 | return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); | ||
1822 | } | ||
1823 | |||
1824 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) | ||
1799 | { | 1825 | { |
1800 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) | 1826 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) |
1801 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) | 1827 | + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) |
1802 | + userpolicy_type_attrsize(); | 1828 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) |
1829 | + userpolicy_type_attrsize(); | ||
1803 | } | 1830 | } |
1804 | 1831 | ||
1805 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | 1832 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, |
1806 | int num_migrate, struct xfrm_selector *sel, | 1833 | int num_migrate, struct xfrm_kmaddress *k, |
1807 | u8 dir, u8 type) | 1834 | struct xfrm_selector *sel, u8 dir, u8 type) |
1808 | { | 1835 | { |
1809 | struct xfrm_migrate *mp; | 1836 | struct xfrm_migrate *mp; |
1810 | struct xfrm_userpolicy_id *pol_id; | 1837 | struct xfrm_userpolicy_id *pol_id; |
@@ -1821,6 +1848,9 @@ static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | |||
1821 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); | 1848 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); |
1822 | pol_id->dir = dir; | 1849 | pol_id->dir = dir; |
1823 | 1850 | ||
1851 | if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0)) | ||
1852 | goto nlmsg_failure; | ||
1853 | |||
1824 | if (copy_to_user_policy_type(type, skb) < 0) | 1854 | if (copy_to_user_policy_type(type, skb) < 0) |
1825 | goto nlmsg_failure; | 1855 | goto nlmsg_failure; |
1826 | 1856 | ||
@@ -1836,23 +1866,25 @@ nlmsg_failure: | |||
1836 | } | 1866 | } |
1837 | 1867 | ||
1838 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1868 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
1839 | struct xfrm_migrate *m, int num_migrate) | 1869 | struct xfrm_migrate *m, int num_migrate, |
1870 | struct xfrm_kmaddress *k) | ||
1840 | { | 1871 | { |
1841 | struct sk_buff *skb; | 1872 | struct sk_buff *skb; |
1842 | 1873 | ||
1843 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate), GFP_ATOMIC); | 1874 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); |
1844 | if (skb == NULL) | 1875 | if (skb == NULL) |
1845 | return -ENOMEM; | 1876 | return -ENOMEM; |
1846 | 1877 | ||
1847 | /* build migrate */ | 1878 | /* build migrate */ |
1848 | if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0) | 1879 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) |
1849 | BUG(); | 1880 | BUG(); |
1850 | 1881 | ||
1851 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); | 1882 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); |
1852 | } | 1883 | } |
1853 | #else | 1884 | #else |
1854 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1885 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
1855 | struct xfrm_migrate *m, int num_migrate) | 1886 | struct xfrm_migrate *m, int num_migrate, |
1887 | struct xfrm_kmaddress *k) | ||
1856 | { | 1888 | { |
1857 | return -ENOPROTOOPT; | 1889 | return -ENOPROTOOPT; |
1858 | } | 1890 | } |
@@ -1901,6 +1933,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
1901 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, | 1933 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, |
1902 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, | 1934 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, |
1903 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, | 1935 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, |
1936 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, | ||
1904 | }; | 1937 | }; |
1905 | 1938 | ||
1906 | static struct xfrm_link { | 1939 | static struct xfrm_link { |