From aec744990c48a57c04f2f01af61a1d8aefd79066 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 7 Apr 2016 18:12:59 -0400 Subject: [PATCH] udp: do not expect udp headers in recv cmsg IP_CMSG_CHECKSUM On udp sockets, recv cmsg IP_CMSG_CHECKSUM returns a checksum over the packet payload. Since commit e6afc8ace6dd pulled the headers, taking skb->data as the start of transport header is incorrect. Use the transport header pointer. Also, when peeking at an offset from the start of the packet, only return a checksum from the start of the peeked data. Note that the cmsg does not subtract a tail checkum when reading truncated data. Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing") Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller (cherry picked from commit 31c2e4926fe912f88388bcaa8450fcaa8f2ece47) Orabug: 25802576 CVE-2017-6347 Signed-off-by: Kirtikar Kashyap Reviewed-by: Jack Vogel --- net/ipv4/ip_sockglue.c | 3 ++- net/ipv4/udp.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 6a06a3d0f28c..84b90edf524a 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -106,7 +106,8 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, return; if (offset != 0) - csum = csum_sub(csum, csum_partial(skb->data, offset, 0)); + csum = csum_sub(csum, csum_partial(skb_transport_header(skb), + offset, 0)); put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index a277b5ba3800..1de3f999a44b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1344,7 +1344,7 @@ try_again: *addr_len = sizeof(*sin); } if (inet->cmsg_flags) - ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr)); + ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr) + off); err = copied; if (flags & MSG_TRUNC) -- 2.49.0