Handle mismatched open calls

A signal can interrupt a SendReceive call which result in incoming
responses to the call being ignored. This is a problem for calls such as
open which results in the successful response being ignored. This
results in an open file resource on the server.

The patch looks into responses which were cancelled after being sent and
in case of successful open closes the open fids.

For this patch, the check is only done in SendReceive2()

RH-bz: 1403319

Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
Cc: Stable <stable@vger.kernel.org>
This commit is contained in:
Sachin Prabhu
2017-03-03 15:41:38 -08:00
committad av Steve French
förälder 269c930e66
incheckning 38bd49064a
9 ändrade filer med 145 tillägg och 15 borttagningar

Visa fil

@@ -1400,9 +1400,9 @@ openRetry:
* current bigbuf.
*/
int
cifs_discard_remaining_data(struct TCP_Server_Info *server)
cifs_discard_remaining_data(struct TCP_Server_Info *server, char *buf)
{
unsigned int rfclen = get_rfc1002_length(server->smallbuf);
unsigned int rfclen = get_rfc1002_length(buf);
int remaining = rfclen + 4 - server->total_read;
while (remaining > 0) {
@@ -1426,7 +1426,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
int length;
struct cifs_readdata *rdata = mid->callback_data;
length = cifs_discard_remaining_data(server);
length = cifs_discard_remaining_data(server, mid->resp_buf);
dequeue_mid(mid, rdata->result);
return length;
}
@@ -1459,7 +1459,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
if (server->ops->is_status_pending &&
server->ops->is_status_pending(buf, server, 0)) {
cifs_discard_remaining_data(server);
cifs_discard_remaining_data(server, buf);
return -1;
}
@@ -1519,6 +1519,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
rdata->iov[0].iov_base, server->total_read);
mid->resp_buf = server->smallbuf;
server->smallbuf = NULL;
/* how much data is in the response? */
data_len = server->ops->read_data_length(buf);
if (data_offset + data_len > buflen) {