aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c61
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
1712static int copy_from_user_migrate(struct xfrm_migrate *ma, 1712static 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
1798static inline size_t xfrm_migrate_msgsize(int num_migrate) 1811static 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
1824static 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
1805static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, 1832static 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
1838static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1868static 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
1854static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1885static 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
1906static struct xfrm_link { 1939static struct xfrm_link {