| From 26e2b0a9f7064ac9e6169a61c60e18e12a5dd0f6 Mon Sep 17 00:00:00 2001 |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| Date: Fri, 25 Apr 2008 01:41:47 -0700 |
| Subject: IPSEC: Fix catch-22 with algorithm IDs above 31 |
| |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| |
| [ Upstream commit: c5d18e984a313adf5a1a4ae69e0b1d93cf410229 ] |
| |
| 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: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| include/net/xfrm.h | 3 +++ |
| net/key/af_key.c | 2 +- |
| net/xfrm/xfrm_policy.c | 2 +- |
| net/xfrm/xfrm_user.c | 2 ++ |
| 4 files changed, 7 insertions(+), 2 deletions(-) |
| |
| --- a/include/net/xfrm.h |
| +++ b/include/net/xfrm.h |
| @@ -435,6 +435,9 @@ struct xfrm_tmpl |
| /* May skip this transfomration if no SA is found */ |
| __u8 optional; |
| |
| +/* Skip aalgos/ealgos/calgos checks. */ |
| + __u8 allalgs; |
| + |
| /* Bit mask of algos allowed for acquisition */ |
| __u32 aalgos; |
| __u32 ealgos; |
| --- a/net/key/af_key.c |
| +++ b/net/key/af_key.c |
| @@ -1856,7 +1856,7 @@ parse_ipsecrequest(struct xfrm_policy *x |
| t->encap_family = xp->family; |
| |
| /* No way to set this via kame pfkey */ |
| - t->aalgos = t->ealgos = t->calgos = ~0; |
| + t->allalgs = 1; |
| xp->xfrm_nr++; |
| return 0; |
| } |
| --- a/net/xfrm/xfrm_policy.c |
| +++ b/net/xfrm/xfrm_policy.c |
| @@ -1772,7 +1772,7 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, st |
| (x->id.spi == tmpl->id.spi || !tmpl->id.spi) && |
| (x->props.reqid == tmpl->reqid || !tmpl->reqid) && |
| 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))) && |
| !(x->props.mode != XFRM_MODE_TRANSPORT && |
| xfrm_state_addr_cmp(tmpl, x, family)); |
| --- a/net/xfrm/xfrm_user.c |
| +++ b/net/xfrm/xfrm_user.c |
| @@ -975,6 +975,8 @@ static void copy_templates(struct xfrm_p |
| t->aalgos = ut->aalgos; |
| t->ealgos = ut->ealgos; |
| 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; |
| } |
| } |