diff options
Diffstat (limited to 'net/ipv4/esp4.c')
| -rw-r--r-- | net/ipv4/esp4.c | 24 |
1 files changed, 15 insertions, 9 deletions
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) | |||
| 171 | if (elen <= 0 || (elen & (blksize-1))) | 171 | if (elen <= 0 || (elen & (blksize-1))) |
| 172 | goto out; | 172 | goto out; |
| 173 | 173 | ||
| 174 | if ((err = skb_cow_data(skb, 0, &trailer)) < 0) | ||
| 175 | goto out; | ||
| 176 | nfrags = err; | ||
| 177 | |||
| 178 | skb->ip_summed = CHECKSUM_NONE; | ||
| 179 | |||
| 180 | spin_lock(&x->lock); | ||
| 181 | |||
| 174 | /* If integrity check is required, do this. */ | 182 | /* If integrity check is required, do this. */ |
| 175 | if (esp->auth.icv_full_len) { | 183 | if (esp->auth.icv_full_len) { |
| 176 | u8 sum[alen]; | 184 | u8 sum[alen]; |
| 177 | 185 | ||
| 178 | err = esp_mac_digest(esp, skb, 0, skb->len - alen); | 186 | err = esp_mac_digest(esp, skb, 0, skb->len - alen); |
| 179 | if (err) | 187 | if (err) |
| 180 | goto out; | 188 | goto unlock; |
| 181 | 189 | ||
| 182 | if (skb_copy_bits(skb, skb->len - alen, sum, alen)) | 190 | if (skb_copy_bits(skb, skb->len - alen, sum, alen)) |
| 183 | BUG(); | 191 | BUG(); |
| 184 | 192 | ||
| 185 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { | 193 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { |
| 186 | err = -EBADMSG; | 194 | err = -EBADMSG; |
| 187 | goto out; | 195 | goto unlock; |
| 188 | } | 196 | } |
| 189 | } | 197 | } |
| 190 | 198 | ||
| 191 | if ((err = skb_cow_data(skb, 0, &trailer)) < 0) | ||
| 192 | goto out; | ||
| 193 | nfrags = err; | ||
| 194 | |||
| 195 | skb->ip_summed = CHECKSUM_NONE; | ||
| 196 | |||
| 197 | esph = (struct ip_esp_hdr *)skb->data; | 199 | esph = (struct ip_esp_hdr *)skb->data; |
| 198 | 200 | ||
| 199 | /* Get ivec. This can be wrong, check against another impls. */ | 201 | /* 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) | |||
| 206 | err = -ENOMEM; | 208 | err = -ENOMEM; |
| 207 | sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); | 209 | sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); |
| 208 | if (!sg) | 210 | if (!sg) |
| 209 | goto out; | 211 | goto unlock; |
| 210 | } | 212 | } |
| 211 | sg_init_table(sg, nfrags); | 213 | sg_init_table(sg, nfrags); |
| 212 | skb_to_sgvec(skb, sg, | 214 | skb_to_sgvec(skb, sg, |
| @@ -215,6 +217,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 215 | err = crypto_blkcipher_decrypt(&desc, sg, sg, elen); | 217 | err = crypto_blkcipher_decrypt(&desc, sg, sg, elen); |
| 216 | if (unlikely(sg != &esp->sgbuf[0])) | 218 | if (unlikely(sg != &esp->sgbuf[0])) |
| 217 | kfree(sg); | 219 | kfree(sg); |
| 220 | |||
| 221 | unlock: | ||
| 222 | spin_unlock(&x->lock); | ||
| 223 | |||
| 218 | if (unlikely(err)) | 224 | if (unlikely(err)) |
| 219 | goto out; | 225 | goto out; |
| 220 | 226 | ||
