| From f97487dc3cd9e5f848569b998e27ac37139f4410 Mon Sep 17 00:00:00 2001 |
| From: John Fastabend <john.fastabend@gmail.com> |
| Date: Sat, 11 Jan 2020 06:12:06 +0000 |
| Subject: [PATCH] bpf: Sockmap/tls, fix pop data with SK_DROP return code |
| |
| commit 7361d44896ff20d48bdd502d1a0cd66308055d45 upstream. |
| |
| When user returns SK_DROP we need to reset the number of copied bytes |
| to indicate to the user the bytes were dropped and not sent. If we |
| don't reset the copied arg sendmsg will return as if those bytes were |
| copied giving the user a positive return value. |
| |
| This works as expected today except in the case where the user also |
| pops bytes. In the pop case the sg.size is reduced but we don't correctly |
| account for this when copied bytes is reset. The popped bytes are not |
| accounted for and we return a small positive value potentially confusing |
| the user. |
| |
| The reason this happens is due to a typo where we do the wrong comparison |
| when accounting for pop bytes. In this fix notice the if/else is not |
| needed and that we have a similar problem if we push data except its not |
| visible to the user because if delta is larger the sg.size we return a |
| negative value so it appears as an error regardless. |
| |
| Fixes: 7246d8ed4dcce ("bpf: helper to pop data from messages") |
| Signed-off-by: John Fastabend <john.fastabend@gmail.com> |
| Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> |
| Acked-by: Jonathan Lemon <jonathan.lemon@gmail.com> |
| Cc: stable@vger.kernel.org |
| Link: https://lore.kernel.org/bpf/20200111061206.8028-9-john.fastabend@gmail.com |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c |
| index e38705165ac9..587d55611814 100644 |
| --- a/net/ipv4/tcp_bpf.c |
| +++ b/net/ipv4/tcp_bpf.c |
| @@ -315,10 +315,7 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, |
| */ |
| delta = msg->sg.size; |
| psock->eval = sk_psock_msg_verdict(sk, psock, msg); |
| - if (msg->sg.size < delta) |
| - delta -= msg->sg.size; |
| - else |
| - delta = 0; |
| + delta -= msg->sg.size; |
| } |
| |
| if (msg->cork_bytes && |
| diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c |
| index 3b65e61081ad..4d7c3b5f3af2 100644 |
| --- a/net/tls/tls_sw.c |
| +++ b/net/tls/tls_sw.c |
| @@ -804,10 +804,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, |
| if (psock->eval == __SK_NONE) { |
| delta = msg->sg.size; |
| psock->eval = sk_psock_msg_verdict(sk, psock, msg); |
| - if (delta < msg->sg.size) |
| - delta -= msg->sg.size; |
| - else |
| - delta = 0; |
| + delta -= msg->sg.size; |
| } |
| if (msg->cork_bytes && msg->cork_bytes > msg->sg.size && |
| !enospc && !full_record) { |
| -- |
| 2.7.4 |
| |