xfrm4: Fix uninitialized memory read in _decode_session4
commit 8742dc86d0c7a9628117a989c11f04a9b6b898f3 upstream.
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: 1da177e4c3
("Linux-2.6.12-rc2")
Change-Id: I8da27fd751dfe161d39054a332b5c4cc898eaf52
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
This commit is contained in:
parent
52f6738728
commit
e992ec0e55
|
@ -106,12 +106,18 @@ 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;
|
||||
|
||||
memset(fl4, 0, sizeof(struct flowi4));
|
||||
fl4->flowi4_mark = skb->mark;
|
||||
|
||||
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:
|
||||
|
@ -123,7 +129,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];
|
||||
|
@ -136,7 +142,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];
|
||||
|
@ -149,7 +155,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];
|
||||
|
@ -161,7 +167,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];
|
||||
|
@ -173,7 +179,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]));
|
||||
|
@ -186,7 +192,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;
|
||||
|
||||
|
@ -203,10 +209,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)
|
||||
|
|
Loading…
Reference in New Issue