Commit 46b1ffd4 authored by Eric Dumazet's avatar Eric Dumazet Committed by Ben Hutchings

dccp: fix out of bound access in dccp_v4_err()

[ Upstream commit 6706a97f ]

dccp_v4_err() does not use pskb_may_pull() and might access garbage.

We only need 4 bytes at the beginning of the DCCP header, like TCP,
so the 8 bytes pulled in icmp_socket_deliver() are more than enough.

This patch might allow to process more ICMP messages, as some routers
are still limiting the size of reflected bytes to 28 (RFC 792), instead
of extended lengths (RFC 1812 4.3.2.3)
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: use offsetof() + sizeof() instead of
 offsetofend()]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 520ff001
...@@ -213,7 +213,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) ...@@ -213,7 +213,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
{ {
const struct iphdr *iph = (struct iphdr *)skb->data; const struct iphdr *iph = (struct iphdr *)skb->data;
const u8 offset = iph->ihl << 2; const u8 offset = iph->ihl << 2;
const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); const struct dccp_hdr *dh;
struct dccp_sock *dp; struct dccp_sock *dp;
struct inet_sock *inet; struct inet_sock *inet;
const int type = icmp_hdr(skb)->type; const int type = icmp_hdr(skb)->type;
...@@ -223,11 +223,13 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info) ...@@ -223,11 +223,13 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
int err; int err;
struct net *net = dev_net(skb->dev); struct net *net = dev_net(skb->dev);
if (skb->len < offset + sizeof(*dh) || /* Only need dccph_dport & dccph_sport which are the first
skb->len < offset + __dccp_basic_hdr_len(dh)) { * 4 bytes in dccp header.
ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); * Our caller (icmp_socket_deliver()) already pulled 8 bytes for us.
return; */
} BUILD_BUG_ON(offsetof(struct dccp_hdr, dccph_sport) + sizeof(dh->dccph_sport) > 8);
BUILD_BUG_ON(offsetof(struct dccp_hdr, dccph_dport) + sizeof(dh->dccph_dport) > 8);
dh = (struct dccp_hdr *)(skb->data + offset);
sk = inet_lookup(net, &dccp_hashinfo, sk = inet_lookup(net, &dccp_hashinfo,
iph->daddr, dh->dccph_dport, iph->daddr, dh->dccph_dport,
......
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