Skip to content

Commit 8ce79ec

Browse files
Ronnie Sahlbergsmfrench
authored andcommitted
cifs: update multiplex loop to handle compounded responses
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
1 parent 1fc6ad2 commit 8ce79ec

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

fs/cifs/cifsglob.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ struct smb_version_operations {
458458
struct mid_q_entry **);
459459
enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
460460
enum securityEnum);
461-
461+
int (*next_header)(char *);
462462
};
463463

464464
struct smb_version_values {

fs/cifs/connect.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,7 @@ cifs_demultiplex_thread(void *p)
856856
int length;
857857
struct TCP_Server_Info *server = p;
858858
unsigned int pdu_length;
859+
unsigned int next_offset;
859860
char *buf = NULL;
860861
struct task_struct *task_to_wake = NULL;
861862
struct mid_q_entry *mid_entry;
@@ -893,17 +894,18 @@ cifs_demultiplex_thread(void *p)
893894
* so we can now interpret the length field.
894895
*/
895896
pdu_length = get_rfc1002_length(buf);
896-
server->pdu_size = pdu_length;
897897

898898
cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
899899
if (!is_smb_response(server, buf[0]))
900900
continue;
901+
next_pdu:
902+
server->pdu_size = pdu_length;
901903

902904
/* make sure we have enough to get to the MID */
903-
if (pdu_length < HEADER_SIZE(server) - 1 -
905+
if (server->pdu_size < HEADER_SIZE(server) - 1 -
904906
server->vals->header_preamble_size) {
905907
cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
906-
pdu_length);
908+
server->pdu_size);
907909
cifs_reconnect(server);
908910
wake_up(&server->response_q);
909911
continue;
@@ -918,6 +920,12 @@ cifs_demultiplex_thread(void *p)
918920
continue;
919921
server->total_read += length;
920922

923+
if (server->ops->next_header) {
924+
next_offset = server->ops->next_header(buf);
925+
if (next_offset)
926+
server->pdu_size = next_offset;
927+
}
928+
921929
if (server->ops->is_transform_hdr &&
922930
server->ops->receive_transform &&
923931
server->ops->is_transform_hdr(buf)) {
@@ -963,7 +971,15 @@ cifs_demultiplex_thread(void *p)
963971
server->ops->dump_detail(buf, server);
964972
cifs_dump_mids(server);
965973
#endif /* CIFS_DEBUG2 */
966-
974+
}
975+
if (pdu_length > server->pdu_size) {
976+
if (!allocate_buffers(server))
977+
continue;
978+
pdu_length -= server->pdu_size;
979+
server->total_read = 0;
980+
server->large_buf = false;
981+
buf = server->smallbuf;
982+
goto next_pdu;
967983
}
968984
} /* end while !EXITING */
969985

fs/cifs/smb2misc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
244244
* MacOS server pads after SMB2.1 write response with 3 bytes
245245
* of junk. Other servers match RFC1001 len to actual
246246
* SMB2/SMB3 frame length (header + smb2 response specific data)
247+
* Some windows servers do too when compounding is used.
247248
* Log the server error (once), but allow it and continue
248249
* since the frame is parseable.
249250
*/

fs/cifs/smb2ops.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2807,6 +2807,19 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
28072807
NULL, 0, 0);
28082808
}
28092809

2810+
static int
2811+
smb2_next_header(char *buf)
2812+
{
2813+
struct smb2_sync_hdr *hdr = (struct smb2_sync_hdr *)buf;
2814+
struct smb2_transform_hdr *t_hdr = (struct smb2_transform_hdr *)buf;
2815+
2816+
if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM)
2817+
return sizeof(struct smb2_transform_hdr) +
2818+
le32_to_cpu(t_hdr->OriginalMessageSize);
2819+
2820+
return le32_to_cpu(hdr->NextCommand);
2821+
}
2822+
28102823
struct smb_version_operations smb20_operations = {
28112824
.compare_fids = smb2_compare_fids,
28122825
.setup_request = smb2_setup_request,
@@ -2898,6 +2911,7 @@ struct smb_version_operations smb20_operations = {
28982911
.get_acl_by_fid = get_smb2_acl_by_fid,
28992912
.set_acl = set_smb2_acl,
29002913
#endif /* CIFS_ACL */
2914+
.next_header = smb2_next_header,
29012915
};
29022916

29032917
struct smb_version_operations smb21_operations = {
@@ -2992,6 +3006,7 @@ struct smb_version_operations smb21_operations = {
29923006
.get_acl_by_fid = get_smb2_acl_by_fid,
29933007
.set_acl = set_smb2_acl,
29943008
#endif /* CIFS_ACL */
3009+
.next_header = smb2_next_header,
29953010
};
29963011

29973012
struct smb_version_operations smb30_operations = {
@@ -3096,6 +3111,7 @@ struct smb_version_operations smb30_operations = {
30963111
.get_acl_by_fid = get_smb2_acl_by_fid,
30973112
.set_acl = set_smb2_acl,
30983113
#endif /* CIFS_ACL */
3114+
.next_header = smb2_next_header,
30993115
};
31003116

31013117
#ifdef CONFIG_CIFS_SMB311
@@ -3196,6 +3212,7 @@ struct smb_version_operations smb311_operations = {
31963212
.query_all_EAs = smb2_query_eas,
31973213
.set_EA = smb2_set_ea,
31983214
#endif /* CIFS_XATTR */
3215+
.next_header = smb2_next_header,
31993216
};
32003217
#endif /* CIFS_SMB311 */
32013218

0 commit comments

Comments
 (0)