udp: do not expect udp headers in recv cmsg IP_CMSG_CHECKSUM
authorWillem de Bruijn <willemb@google.com>
Thu, 7 Apr 2016 22:12:59 +0000 (18:12 -0400)
committerDavid S. Miller <davem@davemloft.net>
Thu, 14 Apr 2016 02:24:52 +0000 (22:24 -0400)
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 <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/ip_sockglue.c
net/ipv4/udp.c

index 89b5f3bd669436f7215703d92aaf7700145cdc8d..279471c4e58fd263a87694dc7afd66ee6ade8765 100644 (file)
@@ -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);
 }
index d2d294b0a1f1587c4290379d3c78ba9a4a8e281c..f1863136d3e40abc4dce815932be7a81d81eeec4 100644 (file)
@@ -1375,7 +1375,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)