summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2020-08-14 15:56:34 +0200
committerDavid S. Miller <davem@davemloft.net>2020-08-14 14:11:37 -0700
commit35759383133f64d90eba120a0d3efe8f71241650 (patch)
tree08b0435c11e611b15290e3afdedbd9182d8b41ed /net
parent068885434ccb20542e0d759aebbefe7a6724d85f (diff)
downloadlinux-stable-35759383133f64d90eba120a0d3efe8f71241650.tar.gz
linux-stable-35759383133f64d90eba120a0d3efe8f71241650.tar.bz2
linux-stable-35759383133f64d90eba120a0d3efe8f71241650.zip
mptcp: sendmsg: reset iter on error
Once we've copied data from the iterator we need to revert in case we end up not sending any data. This bug doesn't trigger with normal 'poll' based tests, because we only feed a small chunk of data to kernel after poll indicated POLLOUT. With blocking IO and large writes this triggers. Receiver ends up with less data than it should get. Fixes: 72511aab95c94d ("mptcp: avoid blocking in tcp_sendpages") Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/mptcp/protocol.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 8c1d1a595701..c84b4051c2a4 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -725,8 +725,10 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
if (!psize)
return -EINVAL;
- if (!sk_wmem_schedule(sk, psize + dfrag->overhead))
+ if (!sk_wmem_schedule(sk, psize + dfrag->overhead)) {
+ iov_iter_revert(&msg->msg_iter, psize);
return -ENOMEM;
+ }
} else {
offset = dfrag->offset;
psize = min_t(size_t, dfrag->data_len, avail_size);
@@ -737,8 +739,10 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
*/
ret = do_tcp_sendpages(ssk, page, offset, psize,
msg->msg_flags | MSG_SENDPAGE_NOTLAST | MSG_DONTWAIT);
- if (ret <= 0)
+ if (ret <= 0) {
+ iov_iter_revert(&msg->msg_iter, psize);
return ret;
+ }
frag_truesize += ret;
if (!retransmission) {