summaryrefslogtreecommitdiff
path: root/kernel/bpf
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2018-08-22 08:37:37 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-10-03 17:00:58 -0700
commit92935e1c2a7e27795456f5058759dbb3acf67e2c (patch)
treecc0b1c47194aea3f48805387b019c386d7369b10 /kernel/bpf
parentf0a8c1257fc3e8310a14c8f9d654620370cf568f (diff)
bpf: sockmap: write_space events need to be passed to TCP handler
[ Upstream commit 9b2e0388bec8ec5427403e23faff3b58dd1c3200 ] When sockmap code is using the stream parser it also handles the write space events in order to handle the case where (a) verdict redirects skb to another socket and (b) the sockmap then sends the skb but due to memory constraints (or other EAGAIN errors) needs to do a retry. But the initial code missed a third case where the skb_send_sock_locked() triggers an sk_wait_event(). A typically case would be when sndbuf size is exceeded. If this happens because we do not pass the write_space event to the lower layers we never wake up the event and it will wait for sndtimeo. Which as noted in ktls fix may be rather large and look like a hang to the user. To reproduce the best test is to reduce the sndbuf size and send 1B data chunks to stress the memory handling. To fix this pass the event from the upper layer to the lower layer. Signed-off-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel/bpf')
-rw-r--r--kernel/bpf/sockmap.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index 53a4787c08d8..20eaddfa691c 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -313,12 +313,15 @@ out:
static void smap_write_space(struct sock *sk)
{
struct smap_psock *psock;
+ void (*write_space)(struct sock *sk);
rcu_read_lock();
psock = smap_psock_sk(sk);
if (likely(psock && test_bit(SMAP_TX_RUNNING, &psock->state)))
schedule_work(&psock->tx_work);
+ write_space = psock->save_write_space;
rcu_read_unlock();
+ write_space(sk);
}
static void smap_stop_sock(struct smap_psock *psock, struct sock *sk)