Message ID | 156036023770.7273.14464005268434910852.stgit@ubuntu-kvm1 |
---|---|
State | Accepted |
Delegated to: | David Miller |
Headers | show |
Series | [net,v2] net: tls, correctly account for copied bytes with multiple sk_msgs | expand |
From: John Fastabend <john.fastabend@gmail.com> Date: Wed, 12 Jun 2019 17:23:57 +0000 > tls_sw_do_sendpage needs to return the total number of bytes sent > regardless of how many sk_msgs are allocated. Unfortunately, copied > (the value we return up the stack) is zero'd before each new sk_msg > is allocated so we only return the copied size of the last sk_msg used. > > The caller (splice, etc.) of sendpage will then believe only part > of its data was sent and send the missing chunks again. However, > because the data actually was sent the receiver will get multiple > copies of the same data. > > To reproduce this do multiple sendfile calls with a length close to > the max record size. This will in turn call splice/sendpage, sendpage > may use multiple sk_msg in this case and then returns the incorrect > number of bytes. This will cause splice to resend creating duplicate > data on the receiver. Andre created a C program that can easily > generate this case so we will push a similar selftest for this to > bpf-next shortly. > > The fix is to _not_ zero the copied field so that the total sent > bytes is returned. > > Reported-by: Steinar H. Gunderson <steinar+kernel@gunderson.no> > Reported-by: Andre Tomt <andre@tomt.net> > Tested-by: Andre Tomt <andre@tomt.net> > Fixes: d829e9c4112b ("tls: convert to generic sk_msg interface") > Signed-off-by: John Fastabend <john.fastabend@gmail.com> Applied and queued up for -stable.
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 960494f437ac..455a782c7658 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -1143,7 +1143,6 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page, full_record = false; record_room = TLS_MAX_PAYLOAD_SIZE - msg_pl->sg.size; - copied = 0; copy = size; if (copy >= record_room) { copy = record_room;