summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2018-12-20 14:35:33 -0500
committerDaniel Borkmann <daniel@iogearbox.net>2018-12-20 17:47:09 -0500
commit552de91068828daef50a227a665068cf8dde835e (patch)
treea85f552adba93a72b5b66d0127a05a77927faa13
parent51199405f967207de372d9b60989eb87d7ae8809 (diff)
bpf: sk_msg, fix socket data_ready events
When a skb verdict program is in-use and either another BPF program redirects to that socket or the new SK_PASS support is used the data_ready callback does not wake up application. Instead because the stream parser/verdict is using the sk data_ready callback we wake up the stream parser/verdict block. Fix this by adding a helper to check if the stream parser block is enabled on the sk and if so call the saved pointer which is the upper layers wake up function. This fixes application stalls observed when an application is waiting for data in a blocking read(). Fixes: d829e9c4112b ("tls: convert to generic sk_msg interface") Signed-off-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--include/linux/skmsg.h8
-rw-r--r--net/core/skmsg.c6
-rw-r--r--net/ipv4/tcp_bpf.c2
3 files changed, 12 insertions, 4 deletions
diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
index dd57e6f408b1..178a3933a71b 100644
--- a/include/linux/skmsg.h
+++ b/include/linux/skmsg.h
@@ -417,6 +417,14 @@ static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock)
417 sk_psock_drop(sk, psock); 417 sk_psock_drop(sk, psock);
418} 418}
419 419
420static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock)
421{
422 if (psock->parser.enabled)
423 psock->parser.saved_data_ready(sk);
424 else
425 sk->sk_data_ready(sk);
426}
427
420static inline void psock_set_prog(struct bpf_prog **pprog, 428static inline void psock_set_prog(struct bpf_prog **pprog,
421 struct bpf_prog *prog) 429 struct bpf_prog *prog)
422{ 430{
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index 8a91a460de8f..3df7627db4bb 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -403,7 +403,7 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb)
403 msg->skb = skb; 403 msg->skb = skb;
404 404
405 sk_psock_queue_msg(psock, msg); 405 sk_psock_queue_msg(psock, msg);
406 sk->sk_data_ready(sk); 406 sk_psock_data_ready(sk, psock);
407 return copied; 407 return copied;
408} 408}
409 409
@@ -751,7 +751,7 @@ static int sk_psock_strp_parse(struct strparser *strp, struct sk_buff *skb)
751} 751}
752 752
753/* Called with socket lock held. */ 753/* Called with socket lock held. */
754static void sk_psock_data_ready(struct sock *sk) 754static void sk_psock_strp_data_ready(struct sock *sk)
755{ 755{
756 struct sk_psock *psock; 756 struct sk_psock *psock;
757 757
@@ -799,7 +799,7 @@ void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)
799 return; 799 return;
800 800
801 parser->saved_data_ready = sk->sk_data_ready; 801 parser->saved_data_ready = sk->sk_data_ready;
802 sk->sk_data_ready = sk_psock_data_ready; 802 sk->sk_data_ready = sk_psock_strp_data_ready;
803 sk->sk_write_space = sk_psock_write_space; 803 sk->sk_write_space = sk_psock_write_space;
804 parser->enabled = true; 804 parser->enabled = true;
805} 805}
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index a47c1cdf90fc..87503343743d 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -198,7 +198,7 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock,
198 msg->sg.start = i; 198 msg->sg.start = i;
199 msg->sg.size -= apply_bytes; 199 msg->sg.size -= apply_bytes;
200 sk_psock_queue_msg(psock, tmp); 200 sk_psock_queue_msg(psock, tmp);
201 sk->sk_data_ready(sk); 201 sk_psock_data_ready(sk, psock);
202 } else { 202 } else {
203 sk_msg_free(sk, tmp); 203 sk_msg_free(sk, tmp);
204 kfree(tmp); 204 kfree(tmp);