diff options
| author | Kazunori Miyazawa <kazunori@miyazawa.org> | 2003-08-07 07:49:41 -0700 |
|---|---|---|
| committer | Stephen Hemminger <shemminger@osdl.org> | 2003-08-07 07:49:41 -0700 |
| commit | 99c2a90294b7734b80de6f1650356df3f5879462 (patch) | |
| tree | 85b525f316fa3e87528165b7d33cb752ff2823a8 | |
| parent | e8830aa5f1f50656ff7614ae3b21e40805795786 (diff) | |
[IPV6]: Fix clearing in ah6 input.
This patch fixes zero-clear in ah6_input.
If calling pskb_expand_head, the kernel clears wrong memory.
| -rw-r--r-- | net/ipv6/ah6.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 07d92a2e48a3..c13efb13eaf9 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -265,13 +265,12 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu * There is offset of AH before IPv6 header after the process. */ - struct ipv6hdr *iph = skb->nh.ipv6h; struct ipv6_auth_hdr *ah; struct ah_data *ahp; unsigned char *tmp_hdr = NULL; - u16 hdr_len = skb->data - skb->nh.raw; + u16 hdr_len; u16 ah_hlen; - u16 cleared_hlen = hdr_len; + u16 cleared_hlen; u16 nh_offset = 0; u8 nexthdr = 0; u8 *prevhdr; @@ -279,6 +278,14 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) goto out; + /* We are going to _remove_ AH header to keep sockets happy, + * so... Later this can change. */ + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto out; + + hdr_len = skb->data - skb->nh.raw; + cleared_hlen = hdr_len; ah = (struct ipv6_auth_hdr*)skb->data; ahp = x->data; nexthdr = ah->nexthdr; @@ -297,27 +304,22 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu if (!pskb_may_pull(skb, ah_hlen)) goto out; - /* We are going to _remove_ AH header to keep sockets happy, - * so... Later this can change. */ - if (skb_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) - goto out; - tmp_hdr = kmalloc(cleared_hlen, GFP_ATOMIC); if (!tmp_hdr) goto out; memcpy(tmp_hdr, skb->nh.raw, cleared_hlen); ipv6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN); - iph->priority = 0; - iph->flow_lbl[0] = 0; - iph->flow_lbl[1] = 0; - iph->flow_lbl[2] = 0; - iph->hop_limit = 0; + skb->nh.ipv6h->priority = 0; + skb->nh.ipv6h->flow_lbl[0] = 0; + skb->nh.ipv6h->flow_lbl[1] = 0; + skb->nh.ipv6h->flow_lbl[2] = 0; + skb->nh.ipv6h->hop_limit = 0; { u8 auth_data[ahp->icv_trunc_len]; memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); + memset(ah->auth_data, 0, ahp->icv_trunc_len); skb_push(skb, skb->data - skb->nh.raw); ahp->icv(ahp, skb, ah->auth_data); if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { |
