xfrm: Forbid state updates from changing encap type
authorHerbert Xu <herbert@gondor.apana.org.au>
Tue, 26 Dec 2017 06:34:44 +0000 (17:34 +1100)
committerSteffen Klassert <steffen.klassert@secunet.com>
Sat, 30 Dec 2017 08:18:47 +0000 (09:18 +0100)
Currently we allow state updates to competely replace the contents
of x->encap.  This is bad because on the user side ESP only sets up
header lengths depending on encap_type once when the state is first
created.  This could result in the header lengths getting out of
sync with the actual state configuration.

In practice key managers will never do a state update to change the
encapsulation type.  Only the port numbers need to be changed as the
peer NAT entry is updated.

Therefore this patch adds a check in xfrm_state_update to forbid
any changes to the encap_type.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
net/xfrm/xfrm_state.c

index 500b3391f474b96fe273060ff8eae16f1e23f3c2..1e80f68e226665e5393dd07eeeaaf9fa7090ca9b 100644 (file)
@@ -1534,8 +1534,12 @@ out:
        err = -EINVAL;
        spin_lock_bh(&x1->lock);
        if (likely(x1->km.state == XFRM_STATE_VALID)) {
-               if (x->encap && x1->encap)
+               if (x->encap && x1->encap &&
+                   x->encap->encap_type == x1->encap->encap_type)
                        memcpy(x1->encap, x->encap, sizeof(*x1->encap));
+               else if (x->encap || x1->encap)
+                       goto fail;
+
                if (x->coaddr && x1->coaddr) {
                        memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr));
                }
@@ -1552,6 +1556,8 @@ out:
                x->km.state = XFRM_STATE_DEAD;
                __xfrm_state_put(x);
        }
+
+fail:
        spin_unlock_bh(&x1->lock);
 
        xfrm_state_put(x1);