bpf: sockmap, fix skmsg recvmsg handler to track size correctly
authorJohn Fastabend <john.fastabend@gmail.com>
Tue, 16 Oct 2018 17:36:01 +0000 (10:36 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 17 Oct 2018 00:29:15 +0000 (02:29 +0200)
When converting sockmap to new skmsg generic data structures we missed
that the recvmsg handler did not correctly use sg.size and instead was
using individual elements length. The result is if a sock is closed
with outstanding data we omit the call to sk_mem_uncharge() and can
get the warning below.

[   66.728282] WARNING: CPU: 6 PID: 5783 at net/core/stream.c:206 sk_stream_kill_queues+0x1fa/0x210

To fix this correct the redirect handler to xfer the size along with
the scatterlist and also decrement the size from the recvmsg handler.
Now when a sock is closed the remaining 'size' will be decremented
with sk_mem_uncharge().

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
include/linux/skmsg.h
net/ipv4/tcp_bpf.c

index 0b919f0bc6d661ca4b2011176cd28c28c55c880a..31df0d9fa5361160b06dd2cbfa3131d8022aa5d0 100644 (file)
@@ -176,6 +176,7 @@ static inline void sk_msg_xfer(struct sk_msg *dst, struct sk_msg *src,
 {
        dst->sg.data[which] = src->sg.data[which];
        dst->sg.data[which].length  = size;
+       dst->sg.size               += size;
        src->sg.data[which].length -= size;
        src->sg.data[which].offset += size;
 }
index 80debb0daf3741393ddf452837ae0ad7866232cb..f9d3cf18582782d72e28bd0324a317cee96b05f6 100644 (file)
@@ -73,6 +73,7 @@ int __tcp_bpf_recvmsg(struct sock *sk, struct sk_psock *psock,
                        sge->offset += copy;
                        sge->length -= copy;
                        sk_mem_uncharge(sk, copy);
+                       msg_rx->sg.size -= copy;
                        if (!sge->length) {
                                i++;
                                if (i == MAX_SKB_FRAGS)