Skip to content

Commit

Permalink
xfrm4: Fix uninitialized memory read in _decode_session4
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
klassert committed Apr 2, 2019
1 parent 025c65e commit 8742dc8
Showing 1 changed file with 13 additions and 11 deletions.
24 changes: 13 additions & 11 deletions net/ipv4/xfrm4_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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:
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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]));
Expand All @@ -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;

Expand All @@ -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,
Expand Down

0 comments on commit 8742dc8

Please sign in to comment.