Commit 5b28db54 authored by Steffen Klassert's avatar Steffen Klassert Committed by Greg Kroah-Hartman

xfrm4: Fix uninitialized memory read in _decode_session4

[ Upstream commit 8742dc86 ]

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: 1da177e4 ("Linux-2.6.12-rc2")
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent eb490b31
...@@ -108,7 +108,8 @@ static void ...@@ -108,7 +108,8 @@ static void
_decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
{ {
const struct iphdr *iph = ip_hdr(skb); 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; struct flowi4 *fl4 = &fl->u.ip4;
int oif = 0; int oif = 0;
...@@ -119,6 +120,11 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -119,6 +120,11 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
fl4->flowi4_mark = skb->mark; fl4->flowi4_mark = skb->mark;
fl4->flowi4_oif = reverse ? skb->skb_iif : oif; 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)) { if (!ip_is_fragment(iph)) {
switch (iph->protocol) { switch (iph->protocol) {
case IPPROTO_UDP: case IPPROTO_UDP:
...@@ -130,7 +136,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -130,7 +136,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 4 - skb->data)) { pskb_may_pull(skb, xprth + 4 - skb->data)) {
__be16 *ports; __be16 *ports;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
ports = (__be16 *)xprth; ports = (__be16 *)xprth;
fl4->fl4_sport = ports[!!reverse]; fl4->fl4_sport = ports[!!reverse];
...@@ -143,7 +149,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -143,7 +149,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 2 - skb->data)) { pskb_may_pull(skb, xprth + 2 - skb->data)) {
u8 *icmp; u8 *icmp;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
icmp = xprth; icmp = xprth;
fl4->fl4_icmp_type = icmp[0]; fl4->fl4_icmp_type = icmp[0];
...@@ -156,7 +162,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -156,7 +162,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 4 - skb->data)) { pskb_may_pull(skb, xprth + 4 - skb->data)) {
__be32 *ehdr; __be32 *ehdr;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
ehdr = (__be32 *)xprth; ehdr = (__be32 *)xprth;
fl4->fl4_ipsec_spi = ehdr[0]; fl4->fl4_ipsec_spi = ehdr[0];
...@@ -168,7 +174,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -168,7 +174,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 8 - skb->data)) { pskb_may_pull(skb, xprth + 8 - skb->data)) {
__be32 *ah_hdr; __be32 *ah_hdr;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
ah_hdr = (__be32 *)xprth; ah_hdr = (__be32 *)xprth;
fl4->fl4_ipsec_spi = ah_hdr[1]; fl4->fl4_ipsec_spi = ah_hdr[1];
...@@ -180,7 +186,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -180,7 +186,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
pskb_may_pull(skb, xprth + 4 - skb->data)) { pskb_may_pull(skb, xprth + 4 - skb->data)) {
__be16 *ipcomp_hdr; __be16 *ipcomp_hdr;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
ipcomp_hdr = (__be16 *)xprth; ipcomp_hdr = (__be16 *)xprth;
fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1])); fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
...@@ -193,7 +199,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -193,7 +199,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
__be16 *greflags; __be16 *greflags;
__be32 *gre_hdr; __be32 *gre_hdr;
xprth = skb_network_header(skb) + iph->ihl * 4; xprth = skb_network_header(skb) + ihl * 4;
greflags = (__be16 *)xprth; greflags = (__be16 *)xprth;
gre_hdr = (__be32 *)xprth; gre_hdr = (__be32 *)xprth;
...@@ -210,10 +216,6 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) ...@@ -210,10 +216,6 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
break; 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) static inline int xfrm4_garbage_collect(struct dst_ops *ops)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment