]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mptcp: sendmsg: reset iter on error
authorFlorian Westphal <fw@strlen.de>
Fri, 14 Aug 2020 13:56:34 +0000 (15:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Sep 2020 10:59:48 +0000 (12:59 +0200)
commit 35759383133f64d90eba120a0d3efe8f71241650 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/mptcp/protocol.c

index 939e445d5188c3cd4047b49a6b83d4efe6c4c870..5542e8061955f6f6a9a6c0011d2ad65be888e918 100644 (file)
@@ -605,8 +605,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);
@@ -617,8 +619,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) {