Commit 307f77e7 authored by David Howells's avatar David Howells Committed by Steve French

cifs: Fix reversion of the iter in cifs_readv_receive().

cifs_read_iter_from_socket() copies the iterator that's passed in for the
socket to modify as and if it will, and then advances the original iterator
by the amount sent.  However, both callers revert the advancement (although
receive_encrypted_read() zeros beyond the iterator first).  The problem is,
though, that cifs_readv_receive() reverts by the original length, not the
amount transmitted which can cause an oops in iov_iter_revert().

Fix this by:

 (1) Remove the iov_iter_advance() from cifs_read_iter_from_socket().

 (2) Remove the iov_iter_revert() from both callers.  This fixes the bug in
     cifs_readv_receive().

 (3) In receive_encrypted_read(), if we didn't get back as much data as the
     buffer will hold, copy the iterator, advance the copy and use the copy
     to drive iov_iter_zero().

As a bonus, this gets rid of some unnecessary work.

This was triggered by generic/074 with the "-o sign" mount option.

Fixes: 3ee1a1fc ("cifs: Cut over to using netfslib")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Paulo Alcantara <pc@manguebit.com>
cc: Shyam Prasad N <nspmangalore@gmail.com>
cc: Rohith Surabattula <rohiths.msft@gmail.com>
cc: Jeff Layton <jlayton@kernel.org>
cc: linux-cifs@vger.kernel.org
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 2f3017e7
...@@ -811,13 +811,9 @@ cifs_read_iter_from_socket(struct TCP_Server_Info *server, struct iov_iter *iter ...@@ -811,13 +811,9 @@ cifs_read_iter_from_socket(struct TCP_Server_Info *server, struct iov_iter *iter
unsigned int to_read) unsigned int to_read)
{ {
struct msghdr smb_msg = { .msg_iter = *iter }; struct msghdr smb_msg = { .msg_iter = *iter };
int ret;
iov_iter_truncate(&smb_msg.msg_iter, to_read); iov_iter_truncate(&smb_msg.msg_iter, to_read);
ret = cifs_readv_from_socket(server, &smb_msg); return cifs_readv_from_socket(server, &smb_msg);
if (ret > 0)
iov_iter_advance(iter, ret);
return ret;
} }
static bool static bool
......
...@@ -4869,9 +4869,12 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, ...@@ -4869,9 +4869,12 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
goto discard_data; goto discard_data;
server->total_read += rc; server->total_read += rc;
if (rc < len) if (rc < len) {
iov_iter_zero(len - rc, &iter); struct iov_iter tmp = iter;
iov_iter_revert(&iter, len);
iov_iter_advance(&tmp, rc);
iov_iter_zero(len - rc, &tmp);
}
iov_iter_truncate(&iter, dw->len); iov_iter_truncate(&iter, dw->len);
rc = cifs_discard_remaining_data(server); rc = cifs_discard_remaining_data(server);
......
...@@ -1817,11 +1817,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1817,11 +1817,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
length = data_len; /* An RDMA read is already done. */ length = data_len; /* An RDMA read is already done. */
else else
#endif #endif
{
length = cifs_read_iter_from_socket(server, &rdata->subreq.io_iter, length = cifs_read_iter_from_socket(server, &rdata->subreq.io_iter,
data_len); data_len);
iov_iter_revert(&rdata->subreq.io_iter, data_len);
}
if (length > 0) if (length > 0)
rdata->got_bytes += length; rdata->got_bytes += length;
server->total_read += length; server->total_read += length;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment