From 9f9a45beaa96188085d52d273c2ecb052c7d8d27 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 7 Apr 2016 18:12:58 -0400 Subject: [PATCH 1/2] udp: do not expect udp headers on ioctl SIOCINQ On udp sockets, ioctl SIOCINQ returns the payload size of the first packet. Since commit e6afc8ace6dd pulled the headers, the result is incorrect when subtracting header length. Remove that operation. Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing") Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/ipv4/udp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 3563788d064f..d2d294b0a1f1 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1282,8 +1282,6 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) * of this packet since that is all * that will be read. */ - amount -= sizeof(struct udphdr); - return put_user(amount, (int __user *)arg); } From 31c2e4926fe912f88388bcaa8450fcaa8f2ece47 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 7 Apr 2016 18:12:59 -0400 Subject: [PATCH 2/2] 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 --- 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 89b5f3bd6694..279471c4e58f 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 d2d294b0a1f1..f1863136d3e4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -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)