]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
cifs`: handle ERRBaduid for SMB1
authorRoberto Bergantinos Corpas <rbergant@redhat.com>
Fri, 3 Jul 2020 09:29:32 +0000 (11:29 +0200)
committerSteve French <stfrench@microsoft.com>
Sun, 2 Aug 2020 23:00:25 +0000 (18:00 -0500)
If server returns ERRBaduid but does not reset transport connection,
we'll keep sending command with a non-valid UID for the server as long
as transport is healthy, without actually recovering. This have been
observed on the field.

This patch adds ERRBaduid handling so that we set CifsNeedReconnect.

map_and_check_smb_error() can be modified to extend use cases.

Signed-off-by: Roberto Bergantinos Corpas <rbergant@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
fs/cifs/cifsproto.h
fs/cifs/netmisc.c
fs/cifs/transport.c

index 7a836ec0438e810ca3b39ea2e57960c30e124833..ed13be38a2659a6ed0ebc0be59dad244dee6d797 100644 (file)
@@ -154,6 +154,7 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length,
 extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
 extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port);
 extern int map_smb_to_linux_error(char *buf, bool logErr);
+extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr);
 extern void header_assemble(struct smb_hdr *, char /* command */ ,
                            const struct cifs_tcon *, int /* length of
                            fixed section (word count) in two byte units */);
index b7ca4960d4ca654713247c9a1c2efd8eb4a30e73..0e728aac67e9f26c1294a95279d2d7a92139cc19 100644 (file)
@@ -881,6 +881,33 @@ map_smb_to_linux_error(char *buf, bool logErr)
        return rc;
 }
 
+int
+map_and_check_smb_error(struct mid_q_entry *mid, bool logErr)
+{
+       int rc;
+       struct smb_hdr *smb = (struct smb_hdr *)mid->resp_buf;
+
+       rc = map_smb_to_linux_error((char *)smb, logErr);
+       if (rc == -EACCES && !(smb->Flags2 & SMBFLG2_ERR_STATUS)) {
+               /* possible ERRBaduid */
+               __u8 class = smb->Status.DosError.ErrorClass;
+               __u16 code = le16_to_cpu(smb->Status.DosError.Error);
+
+               /* switch can be used to handle different errors */
+               if (class == ERRSRV && code == ERRbaduid) {
+                       cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n",
+                               code);
+                       spin_lock(&GlobalMid_Lock);
+                       if (mid->server->tcpStatus != CifsExiting)
+                               mid->server->tcpStatus = CifsNeedReconnect;
+                       spin_unlock(&GlobalMid_Lock);
+               }
+       }
+
+       return rc;
+}
+
+
 /*
  * calculate the size of the SMB message based on the fixed header
  * portion, the number of word parameters and the data portion of the message
index 84433d0653f92a896eba0a063eecdec1b3321b6d..ac7632482736711b33a468de8986eb6173578373 100644 (file)
@@ -936,7 +936,7 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
        }
 
        /* BB special case reconnect tid and uid here? */
-       return map_smb_to_linux_error(mid->resp_buf, log_error);
+       return map_and_check_smb_error(mid, log_error);
 }
 
 struct mid_q_entry *