Revert "xfrm: Fix stack-out-of-bounds read in xfrm_state_find."
authorSteffen Klassert <steffen.klassert@secunet.com>
Wed, 15 Nov 2017 05:40:57 +0000 (06:40 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 5 Jan 2018 14:48:58 +0000 (15:48 +0100)
commit 94802151894d482e82c324edf2c658f8e6b96508 upstream.

This reverts commit c9f3f813d462c72dbe412cee6a5cbacf13c4ad5e.

This commit breaks transport mode when the policy template
has widlcard addresses configured, so revert it.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Cc: From: Derek Robson <robsonde@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/xfrm/xfrm_policy.c

index 2a6093840e7e856e48f3502fa7c69f223041649c..6bc16bb61b5533ef6fa925b6f9a5d67341f2ee48 100644 (file)
@@ -1362,29 +1362,36 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
        struct net *net = xp_net(policy);
        int nx;
        int i, error;
+       xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family);
+       xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family);
        xfrm_address_t tmp;
 
        for (nx = 0, i = 0; i < policy->xfrm_nr; i++) {
                struct xfrm_state *x;
-               xfrm_address_t *local;
-               xfrm_address_t *remote;
+               xfrm_address_t *remote = daddr;
+               xfrm_address_t *local  = saddr;
                struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
 
-               remote = &tmpl->id.daddr;
-               local = &tmpl->saddr;
-               if (xfrm_addr_any(local, tmpl->encap_family)) {
-                       error = xfrm_get_saddr(net, fl->flowi_oif,
-                                              &tmp, remote,
-                                              tmpl->encap_family, 0);
-                       if (error)
-                               goto fail;
-                       local = &tmp;
+               if (tmpl->mode == XFRM_MODE_TUNNEL ||
+                   tmpl->mode == XFRM_MODE_BEET) {
+                       remote = &tmpl->id.daddr;
+                       local = &tmpl->saddr;
+                       if (xfrm_addr_any(local, tmpl->encap_family)) {
+                               error = xfrm_get_saddr(net, fl->flowi_oif,
+                                                      &tmp, remote,
+                                                      tmpl->encap_family, 0);
+                               if (error)
+                                       goto fail;
+                               local = &tmp;
+                       }
                }
 
                x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family);
 
                if (x && x->km.state == XFRM_STATE_VALID) {
                        xfrm[nx++] = x;
+                       daddr = remote;
+                       saddr = local;
                        continue;
                }
                if (x) {