| From b05870b9fd94e9d63e9f37843aa2ed971ff3fe31 Mon Sep 17 00:00:00 2001 |
| From: Steffen Klassert <steffen.klassert@secunet.com> |
| Date: Tue, 26 Feb 2019 07:04:50 +0100 |
| Subject: xfrm4: Fix uninitialized memory read in _decode_session4 |
| |
| [ Upstream commit 8742dc86d0c7a9628117a989c11f04a9b6b898f3 ] |
| |
| We currently don't reload pointers pointing into skb header |
| after doing pskb_may_pull() in _decode_session4(). So in case |
| pskb_may_pull() changed the pointers, we read from random |
| memory. Fix this by putting all the needed infos on the |
| stack, so that we don't need to access the header pointers |
| after doing pskb_may_pull(). |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/ipv4/xfrm4_policy.c | 24 +++++++++++++----------- |
| 1 file changed, 13 insertions(+), 11 deletions(-) |
| |
| diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c |
| index d73a6d6652f60..2b144b92ae46a 100644 |
| --- a/net/ipv4/xfrm4_policy.c |
| +++ b/net/ipv4/xfrm4_policy.c |
| @@ -111,7 +111,8 @@ static void |
| _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| { |
| const struct iphdr *iph = ip_hdr(skb); |
| - u8 *xprth = skb_network_header(skb) + iph->ihl * 4; |
| + int ihl = iph->ihl; |
| + u8 *xprth = skb_network_header(skb) + ihl * 4; |
| struct flowi4 *fl4 = &fl->u.ip4; |
| int oif = 0; |
| |
| @@ -122,6 +123,11 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| fl4->flowi4_mark = skb->mark; |
| fl4->flowi4_oif = reverse ? skb->skb_iif : oif; |
| |
| + fl4->flowi4_proto = iph->protocol; |
| + fl4->daddr = reverse ? iph->saddr : iph->daddr; |
| + fl4->saddr = reverse ? iph->daddr : iph->saddr; |
| + fl4->flowi4_tos = iph->tos; |
| + |
| if (!ip_is_fragment(iph)) { |
| switch (iph->protocol) { |
| case IPPROTO_UDP: |
| @@ -133,7 +139,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| pskb_may_pull(skb, xprth + 4 - skb->data)) { |
| __be16 *ports; |
| |
| - xprth = skb_network_header(skb) + iph->ihl * 4; |
| + xprth = skb_network_header(skb) + ihl * 4; |
| ports = (__be16 *)xprth; |
| |
| fl4->fl4_sport = ports[!!reverse]; |
| @@ -146,7 +152,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| pskb_may_pull(skb, xprth + 2 - skb->data)) { |
| u8 *icmp; |
| |
| - xprth = skb_network_header(skb) + iph->ihl * 4; |
| + xprth = skb_network_header(skb) + ihl * 4; |
| icmp = xprth; |
| |
| fl4->fl4_icmp_type = icmp[0]; |
| @@ -159,7 +165,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| pskb_may_pull(skb, xprth + 4 - skb->data)) { |
| __be32 *ehdr; |
| |
| - xprth = skb_network_header(skb) + iph->ihl * 4; |
| + xprth = skb_network_header(skb) + ihl * 4; |
| ehdr = (__be32 *)xprth; |
| |
| fl4->fl4_ipsec_spi = ehdr[0]; |
| @@ -171,7 +177,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| pskb_may_pull(skb, xprth + 8 - skb->data)) { |
| __be32 *ah_hdr; |
| |
| - xprth = skb_network_header(skb) + iph->ihl * 4; |
| + xprth = skb_network_header(skb) + ihl * 4; |
| ah_hdr = (__be32 *)xprth; |
| |
| fl4->fl4_ipsec_spi = ah_hdr[1]; |
| @@ -183,7 +189,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| pskb_may_pull(skb, xprth + 4 - skb->data)) { |
| __be16 *ipcomp_hdr; |
| |
| - xprth = skb_network_header(skb) + iph->ihl * 4; |
| + xprth = skb_network_header(skb) + ihl * 4; |
| ipcomp_hdr = (__be16 *)xprth; |
| |
| fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1])); |
| @@ -196,7 +202,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| __be16 *greflags; |
| __be32 *gre_hdr; |
| |
| - xprth = skb_network_header(skb) + iph->ihl * 4; |
| + xprth = skb_network_header(skb) + ihl * 4; |
| greflags = (__be16 *)xprth; |
| gre_hdr = (__be32 *)xprth; |
| |
| @@ -213,10 +219,6 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
| break; |
| } |
| } |
| - fl4->flowi4_proto = iph->protocol; |
| - fl4->daddr = reverse ? iph->saddr : iph->daddr; |
| - fl4->saddr = reverse ? iph->daddr : iph->saddr; |
| - fl4->flowi4_tos = iph->tos; |
| } |
| |
| static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk, |
| -- |
| 2.20.1 |
| |