| From ad0a82646e23903711e29db3bd04179997b47a80 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 622e158a6fc40..1805413cd2251 100644 |
| --- a/net/ipv4/xfrm4_policy.c |
| +++ b/net/ipv4/xfrm4_policy.c |
| @@ -108,7 +108,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; |
| |
| @@ -119,6 +120,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: |
| @@ -130,7 +136,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]; |
| @@ -143,7 +149,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]; |
| @@ -156,7 +162,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]; |
| @@ -168,7 +174,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]; |
| @@ -180,7 +186,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])); |
| @@ -193,7 +199,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; |
| |
| @@ -210,10 +216,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 inline int xfrm4_garbage_collect(struct dst_ops *ops) |
| -- |
| 2.20.1 |
| |