Commit ae9711f0 authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Greg Kroah-Hartman

cifs: fix credits leak for SMB1 oplock breaks

commit d69cb728 upstream.

For SMB1 oplock breaks we would grab one credit while sending the PDU
but we would never relese the credit back since we will never receive a
response to this from the server. Eventuallt this would lead to a hang
once all credits are leaked.

Fix this by defining a new flag CIFS_NO_SRV_RSP which indicates that there
is no server response to this command and thus we need to add any credits back
immediately after sending the PDU.

CC: Stable <stable@vger.kernel.org> #v5.0+
Signed-off-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Reviewed-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6e3e47a8
...@@ -1687,6 +1687,7 @@ static inline bool is_retryable_error(int error) ...@@ -1687,6 +1687,7 @@ static inline bool is_retryable_error(int error)
#define CIFS_HAS_CREDITS 0x0400 /* already has credits */ #define CIFS_HAS_CREDITS 0x0400 /* already has credits */
#define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */ #define CIFS_TRANSFORM_REQ 0x0800 /* transform request before sending */
#define CIFS_NO_SRV_RSP 0x1000 /* there is no server response */
/* Security Flags: indicate type of session setup needed */ /* Security Flags: indicate type of session setup needed */
#define CIFSSEC_MAY_SIGN 0x00001 #define CIFSSEC_MAY_SIGN 0x00001
......
...@@ -2540,7 +2540,7 @@ CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2540,7 +2540,7 @@ CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
/* no response expected */ /* no response expected */
flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP; flags = CIFS_NO_SRV_RSP | CIFS_ASYNC_OP | CIFS_OBREAK_OP;
pSMB->Timeout = 0; pSMB->Timeout = 0;
} else if (waitFlag) { } else if (waitFlag) {
flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
......
...@@ -1054,8 +1054,11 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -1054,8 +1054,11 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
mutex_unlock(&ses->server->srv_mutex); mutex_unlock(&ses->server->srv_mutex);
if (rc < 0) { /*
/* Sending failed for some reason - return credits back */ * If sending failed for some reason or it is an oplock break that we
* will not receive a response to - return credits back
*/
if (rc < 0 || (flags & CIFS_NO_SRV_RSP)) {
for (i = 0; i < num_rqst; i++) for (i = 0; i < num_rqst; i++)
add_credits(ses->server, &credits[i], optype); add_credits(ses->server, &credits[i], optype);
goto out; goto out;
...@@ -1076,9 +1079,6 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -1076,9 +1079,6 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
smb311_update_preauth_hash(ses, rqst[0].rq_iov, smb311_update_preauth_hash(ses, rqst[0].rq_iov,
rqst[0].rq_nvec); rqst[0].rq_nvec);
if ((flags & CIFS_TIMEOUT_MASK) == CIFS_ASYNC_OP)
goto out;
for (i = 0; i < num_rqst; i++) { for (i = 0; i < num_rqst; i++) {
rc = wait_for_response(ses->server, midQ[i]); rc = wait_for_response(ses->server, midQ[i]);
if (rc != 0) if (rc != 0)
......
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