Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cifs`: handle ERRBaduid for SMB1

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>

authored by

Roberto Bergantinos Corpas and committed by
Steve French
a3713ec3 66a4bbc3

+29 -1
+1
fs/cifs/cifsproto.h
··· 154 154 extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); 155 155 extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port); 156 156 extern int map_smb_to_linux_error(char *buf, bool logErr); 157 + extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr); 157 158 extern void header_assemble(struct smb_hdr *, char /* command */ , 158 159 const struct cifs_tcon *, int /* length of 159 160 fixed section (word count) in two byte units */);
+27
fs/cifs/netmisc.c
··· 881 881 return rc; 882 882 } 883 883 884 + int 885 + map_and_check_smb_error(struct mid_q_entry *mid, bool logErr) 886 + { 887 + int rc; 888 + struct smb_hdr *smb = (struct smb_hdr *)mid->resp_buf; 889 + 890 + rc = map_smb_to_linux_error((char *)smb, logErr); 891 + if (rc == -EACCES && !(smb->Flags2 & SMBFLG2_ERR_STATUS)) { 892 + /* possible ERRBaduid */ 893 + __u8 class = smb->Status.DosError.ErrorClass; 894 + __u16 code = le16_to_cpu(smb->Status.DosError.Error); 895 + 896 + /* switch can be used to handle different errors */ 897 + if (class == ERRSRV && code == ERRbaduid) { 898 + cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n", 899 + code); 900 + spin_lock(&GlobalMid_Lock); 901 + if (mid->server->tcpStatus != CifsExiting) 902 + mid->server->tcpStatus = CifsNeedReconnect; 903 + spin_unlock(&GlobalMid_Lock); 904 + } 905 + } 906 + 907 + return rc; 908 + } 909 + 910 + 884 911 /* 885 912 * calculate the size of the SMB message based on the fixed header 886 913 * portion, the number of word parameters and the data portion of the message
+1 -1
fs/cifs/transport.c
··· 936 936 } 937 937 938 938 /* BB special case reconnect tid and uid here? */ 939 - return map_smb_to_linux_error(mid->resp_buf, log_error); 939 + return map_and_check_smb_error(mid, log_error); 940 940 } 941 941 942 942 struct mid_q_entry *