diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-11-13 21:45:58 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 14:53:52 -0800 |
commit | 0ebea8ef3559b545c37b016f44e84c3b33e47c39 (patch) | |
tree | 7a47787c1b830084ac2d36371490b9e2574e2472 /net/ipv4 | |
parent | 668dc8af3150f837f7f0461001bbbc0ce25d7bdf (diff) | |
download | linux-0ebea8ef3559b545c37b016f44e84c3b33e47c39.tar.bz2 |
[IPSEC]: Move state lock into x->type->input
This patch releases the lock on the state before calling
x->type->input. It also adds the lock to the spots where they're
currently needed.
Most of those places (all except mip6) are expected to disappear with
async crypto.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/ah4.c | 14 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 24 |
2 files changed, 25 insertions, 13 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index a989d29b44ea..d76803a3dcae 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -169,6 +169,8 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) if (ip_clear_mutable_options(iph, &dummy)) goto out; } + + spin_lock(&x->lock); { u8 auth_data[MAX_AH_AUTH_LEN]; @@ -176,12 +178,16 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) skb_push(skb, ihl); err = ah_mac_digest(ahp, skb, ah->auth_data); if (err) - goto out; - if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { + goto unlock; + if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) err = -EBADMSG; - goto out; - } } +unlock: + spin_unlock(&x->lock); + + if (err) + goto out; + skb->network_header += ah_hlen; memcpy(skb_network_header(skb), work_buf, ihl); skb->transport_header = skb->network_header; diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 3350a7d50669..28ea5c77ca23 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -171,29 +171,31 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) if (elen <= 0 || (elen & (blksize-1))) goto out; + if ((err = skb_cow_data(skb, 0, &trailer)) < 0) + goto out; + nfrags = err; + + skb->ip_summed = CHECKSUM_NONE; + + spin_lock(&x->lock); + /* If integrity check is required, do this. */ if (esp->auth.icv_full_len) { u8 sum[alen]; err = esp_mac_digest(esp, skb, 0, skb->len - alen); if (err) - goto out; + goto unlock; if (skb_copy_bits(skb, skb->len - alen, sum, alen)) BUG(); if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { err = -EBADMSG; - goto out; + goto unlock; } } - if ((err = skb_cow_data(skb, 0, &trailer)) < 0) - goto out; - nfrags = err; - - skb->ip_summed = CHECKSUM_NONE; - esph = (struct ip_esp_hdr *)skb->data; /* Get ivec. This can be wrong, check against another impls. */ @@ -206,7 +208,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) err = -ENOMEM; sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); if (!sg) - goto out; + goto unlock; } sg_init_table(sg, nfrags); skb_to_sgvec(skb, sg, @@ -215,6 +217,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) err = crypto_blkcipher_decrypt(&desc, sg, sg, elen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); + +unlock: + spin_unlock(&x->lock); + if (unlikely(err)) goto out; |