Commit c5d18e98 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[IPSEC]: Fix catch-22 with algorithm IDs above 31

As it stands it's impossible to use any authentication algorithms
with an ID above 31 portably.  It just happens to work on x86 but
fails miserably on ppc64.

The reason is that we're using a bit mask to check the algorithm
ID but the mask is only 32 bits wide.

After looking at how this is used in the field, I have concluded
that in the long term we should phase out state matching by IDs
because this is made superfluous by the reqid feature.  For current
applications, the best solution IMHO is to allow all algorithms when
the bit masks are all ~0.

The following patch does exactly that.

This bug was identified by IBM when testing on the ppc64 platform
using the NULL authentication algorithm which has an ID of 251.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c3f944e
...@@ -436,6 +436,9 @@ struct xfrm_tmpl ...@@ -436,6 +436,9 @@ struct xfrm_tmpl
/* May skip this transfomration if no SA is found */ /* May skip this transfomration if no SA is found */
__u8 optional; __u8 optional;
/* Skip aalgos/ealgos/calgos checks. */
__u8 allalgs;
/* Bit mask of algos allowed for acquisition */ /* Bit mask of algos allowed for acquisition */
__u32 aalgos; __u32 aalgos;
__u32 ealgos; __u32 ealgos;
......
...@@ -1907,7 +1907,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) ...@@ -1907,7 +1907,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
t->encap_family = xp->family; t->encap_family = xp->family;
/* No way to set this via kame pfkey */ /* No way to set this via kame pfkey */
t->aalgos = t->ealgos = t->calgos = ~0; t->allalgs = 1;
xp->xfrm_nr++; xp->xfrm_nr++;
return 0; return 0;
} }
......
...@@ -1819,7 +1819,7 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x, ...@@ -1819,7 +1819,7 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
(x->id.spi == tmpl->id.spi || !tmpl->id.spi) && (x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
(x->props.reqid == tmpl->reqid || !tmpl->reqid) && (x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
x->props.mode == tmpl->mode && x->props.mode == tmpl->mode &&
((tmpl->aalgos & (1<<x->props.aalgo)) || (tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) ||
!(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) && !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) &&
!(x->props.mode != XFRM_MODE_TRANSPORT && !(x->props.mode != XFRM_MODE_TRANSPORT &&
xfrm_state_addr_cmp(tmpl, x, family)); xfrm_state_addr_cmp(tmpl, x, family));
......
...@@ -981,6 +981,8 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, ...@@ -981,6 +981,8 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
t->aalgos = ut->aalgos; t->aalgos = ut->aalgos;
t->ealgos = ut->ealgos; t->ealgos = ut->ealgos;
t->calgos = ut->calgos; t->calgos = ut->calgos;
/* If all masks are ~0, then we allow all algorithms. */
t->allalgs = !~(t->aalgos & t->ealgos & t->calgos);
t->encap_family = ut->family; t->encap_family = ut->family;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment