aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-11-08 20:58:35 -0500
committerDavid S. Miller <davem@davemloft.net>2017-11-08 20:58:35 -0500
commit6a17280247458ac2c302200e2d6ae36656f75bc6 (patch)
tree1063ef6609bf185e13de668e07156e795d9cafb4
parent623859ae06b85cabba79ce78f0d49e67783d4c34 (diff)
parentc9f3f813d462c72dbe412cee6a5cbacf13c4ad5e (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2017-11-09 1) Fix a use after free due to a reallocated skb head. From Florian Westphal. 2) Fix sporadic lookup failures on labeled IPSEC. From Florian Westphal. 3) Fix a stack out of bounds when a socket policy is applied to an IPv6 socket that sends IPv4 packets. Please pull or let me know if there are problems. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/xfrm/xfrm_input.c4
-rw-r--r--net/xfrm/xfrm_policy.c71
2 files changed, 37 insertions, 38 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 82d20ee34581..347ab31574d5 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -266,8 +266,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
266 goto lock; 266 goto lock;
267 } 267 }
268 268
269 daddr = (xfrm_address_t *)(skb_network_header(skb) +
270 XFRM_SPI_SKB_CB(skb)->daddroff);
271 family = XFRM_SPI_SKB_CB(skb)->family; 269 family = XFRM_SPI_SKB_CB(skb)->family;
272 270
273 /* if tunnel is present override skb->mark value with tunnel i_key */ 271 /* if tunnel is present override skb->mark value with tunnel i_key */
@@ -294,6 +292,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
294 goto drop; 292 goto drop;
295 } 293 }
296 294
295 daddr = (xfrm_address_t *)(skb_network_header(skb) +
296 XFRM_SPI_SKB_CB(skb)->daddroff);
297 do { 297 do {
298 if (skb->sp->len == XFRM_MAX_DEPTH) { 298 if (skb->sp->len == XFRM_MAX_DEPTH) {
299 XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); 299 XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8cafb3c0a4ac..6eb228a70131 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1361,36 +1361,29 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
1361 struct net *net = xp_net(policy); 1361 struct net *net = xp_net(policy);
1362 int nx; 1362 int nx;
1363 int i, error; 1363 int i, error;
1364 xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family);
1365 xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family);
1366 xfrm_address_t tmp; 1364 xfrm_address_t tmp;
1367 1365
1368 for (nx = 0, i = 0; i < policy->xfrm_nr; i++) { 1366 for (nx = 0, i = 0; i < policy->xfrm_nr; i++) {
1369 struct xfrm_state *x; 1367 struct xfrm_state *x;
1370 xfrm_address_t *remote = daddr; 1368 xfrm_address_t *local;
1371 xfrm_address_t *local = saddr; 1369 xfrm_address_t *remote;
1372 struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i]; 1370 struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
1373 1371
1374 if (tmpl->mode == XFRM_MODE_TUNNEL || 1372 remote = &tmpl->id.daddr;
1375 tmpl->mode == XFRM_MODE_BEET) { 1373 local = &tmpl->saddr;
1376 remote = &tmpl->id.daddr; 1374 if (xfrm_addr_any(local, tmpl->encap_family)) {
1377 local = &tmpl->saddr; 1375 error = xfrm_get_saddr(net, fl->flowi_oif,
1378 if (xfrm_addr_any(local, tmpl->encap_family)) { 1376 &tmp, remote,
1379 error = xfrm_get_saddr(net, fl->flowi_oif, 1377 tmpl->encap_family, 0);
1380 &tmp, remote, 1378 if (error)
1381 tmpl->encap_family, 0); 1379 goto fail;
1382 if (error) 1380 local = &tmp;
1383 goto fail;
1384 local = &tmp;
1385 }
1386 } 1381 }
1387 1382
1388 x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family); 1383 x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family);
1389 1384
1390 if (x && x->km.state == XFRM_STATE_VALID) { 1385 if (x && x->km.state == XFRM_STATE_VALID) {
1391 xfrm[nx++] = x; 1386 xfrm[nx++] = x;
1392 daddr = remote;
1393 saddr = local;
1394 continue; 1387 continue;
1395 } 1388 }
1396 if (x) { 1389 if (x) {
@@ -1787,19 +1780,23 @@ void xfrm_policy_cache_flush(void)
1787 put_online_cpus(); 1780 put_online_cpus();
1788} 1781}
1789 1782
1790static bool xfrm_pol_dead(struct xfrm_dst *xdst) 1783static bool xfrm_xdst_can_reuse(struct xfrm_dst *xdst,
1784 struct xfrm_state * const xfrm[],
1785 int num)
1791{ 1786{
1792 unsigned int num_pols = xdst->num_pols; 1787 const struct dst_entry *dst = &xdst->u.dst;
1793 unsigned int pol_dead = 0, i; 1788 int i;
1794 1789
1795 for (i = 0; i < num_pols; i++) 1790 if (xdst->num_xfrms != num)
1796 pol_dead |= xdst->pols[i]->walk.dead; 1791 return false;
1797 1792
1798 /* Mark DST_OBSOLETE_DEAD to fail the next xfrm_dst_check() */ 1793 for (i = 0; i < num; i++) {
1799 if (pol_dead) 1794 if (!dst || dst->xfrm != xfrm[i])
1800 xdst->u.dst.obsolete = DST_OBSOLETE_DEAD; 1795 return false;
1796 dst = dst->child;
1797 }
1801 1798
1802 return pol_dead; 1799 return xfrm_bundle_ok(xdst);
1803} 1800}
1804 1801
1805static struct xfrm_dst * 1802static struct xfrm_dst *
@@ -1813,26 +1810,28 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
1813 struct dst_entry *dst; 1810 struct dst_entry *dst;
1814 int err; 1811 int err;
1815 1812
1813 /* Try to instantiate a bundle */
1814 err = xfrm_tmpl_resolve(pols, num_pols, fl, xfrm, family);
1815 if (err <= 0) {
1816 if (err != 0 && err != -EAGAIN)
1817 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
1818 return ERR_PTR(err);
1819 }
1820
1816 xdst = this_cpu_read(xfrm_last_dst); 1821 xdst = this_cpu_read(xfrm_last_dst);
1817 if (xdst && 1822 if (xdst &&
1818 xdst->u.dst.dev == dst_orig->dev && 1823 xdst->u.dst.dev == dst_orig->dev &&
1819 xdst->num_pols == num_pols && 1824 xdst->num_pols == num_pols &&
1820 !xfrm_pol_dead(xdst) &&
1821 memcmp(xdst->pols, pols, 1825 memcmp(xdst->pols, pols,
1822 sizeof(struct xfrm_policy *) * num_pols) == 0 && 1826 sizeof(struct xfrm_policy *) * num_pols) == 0 &&
1823 xfrm_bundle_ok(xdst)) { 1827 xfrm_xdst_can_reuse(xdst, xfrm, err)) {
1824 dst_hold(&xdst->u.dst); 1828 dst_hold(&xdst->u.dst);
1829 while (err > 0)
1830 xfrm_state_put(xfrm[--err]);
1825 return xdst; 1831 return xdst;
1826 } 1832 }
1827 1833
1828 old = xdst; 1834 old = xdst;
1829 /* Try to instantiate a bundle */
1830 err = xfrm_tmpl_resolve(pols, num_pols, fl, xfrm, family);
1831 if (err <= 0) {
1832 if (err != 0 && err != -EAGAIN)
1833 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
1834 return ERR_PTR(err);
1835 }
1836 1835
1837 dst = xfrm_bundle_create(pols[0], xfrm, err, fl, dst_orig); 1836 dst = xfrm_bundle_create(pols[0], xfrm, err, fl, dst_orig);
1838 if (IS_ERR(dst)) { 1837 if (IS_ERR(dst)) {