Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ce79ec3 authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Steve French
Browse files

cifs: update multiplex loop to handle compounded responses

parent 1fc6ad2f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -458,7 +458,7 @@ struct smb_version_operations {
				 struct mid_q_entry **);
	enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
			    enum securityEnum);

	int (*next_header)(char *);
};

struct smb_version_values {
+20 −4
Original line number Diff line number Diff line
@@ -856,6 +856,7 @@ cifs_demultiplex_thread(void *p)
	int length;
	struct TCP_Server_Info *server = p;
	unsigned int pdu_length;
	unsigned int next_offset;
	char *buf = NULL;
	struct task_struct *task_to_wake = NULL;
	struct mid_q_entry *mid_entry;
@@ -893,17 +894,18 @@ cifs_demultiplex_thread(void *p)
		 * so we can now interpret the length field.
		 */
		pdu_length = get_rfc1002_length(buf);
		server->pdu_size = pdu_length;

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

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

		if (server->ops->next_header) {
			next_offset = server->ops->next_header(buf);
			if (next_offset)
				server->pdu_size = next_offset;
		}

		if (server->ops->is_transform_hdr &&
		    server->ops->receive_transform &&
		    server->ops->is_transform_hdr(buf)) {
@@ -963,7 +971,15 @@ cifs_demultiplex_thread(void *p)
				server->ops->dump_detail(buf, server);
			cifs_dump_mids(server);
#endif /* CIFS_DEBUG2 */

		}
		if (pdu_length > server->pdu_size) {
			if (!allocate_buffers(server))
				continue;
			pdu_length -= server->pdu_size;
			server->total_read = 0;
			server->large_buf = false;
			buf = server->smallbuf;
			goto next_pdu;
		}
	} /* end while !EXITING */

+1 −0
Original line number Diff line number Diff line
@@ -244,6 +244,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
		 * MacOS server pads after SMB2.1 write response with 3 bytes
		 * of junk. Other servers match RFC1001 len to actual
		 * SMB2/SMB3 frame length (header + smb2 response specific data)
		 * Some windows servers do too when compounding is used.
		 * Log the server error (once), but allow it and continue
		 * since the frame is parseable.
		 */
+17 −0
Original line number Diff line number Diff line
@@ -2807,6 +2807,19 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
				NULL, 0, 0);
}

static int
smb2_next_header(char *buf)
{
	struct smb2_sync_hdr *hdr = (struct smb2_sync_hdr *)buf;
	struct smb2_transform_hdr *t_hdr = (struct smb2_transform_hdr *)buf;

	if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM)
		return sizeof(struct smb2_transform_hdr) +
		  le32_to_cpu(t_hdr->OriginalMessageSize);

	return le32_to_cpu(hdr->NextCommand);
}

struct smb_version_operations smb20_operations = {
	.compare_fids = smb2_compare_fids,
	.setup_request = smb2_setup_request,
@@ -2898,6 +2911,7 @@ struct smb_version_operations smb20_operations = {
	.get_acl_by_fid = get_smb2_acl_by_fid,
	.set_acl = set_smb2_acl,
#endif /* CIFS_ACL */
	.next_header = smb2_next_header,
};

struct smb_version_operations smb21_operations = {
@@ -2992,6 +3006,7 @@ struct smb_version_operations smb21_operations = {
	.get_acl_by_fid = get_smb2_acl_by_fid,
	.set_acl = set_smb2_acl,
#endif /* CIFS_ACL */
	.next_header = smb2_next_header,
};

struct smb_version_operations smb30_operations = {
@@ -3096,6 +3111,7 @@ struct smb_version_operations smb30_operations = {
	.get_acl_by_fid = get_smb2_acl_by_fid,
	.set_acl = set_smb2_acl,
#endif /* CIFS_ACL */
	.next_header = smb2_next_header,
};

#ifdef CONFIG_CIFS_SMB311
@@ -3196,6 +3212,7 @@ struct smb_version_operations smb311_operations = {
	.query_all_EAs = smb2_query_eas,
	.set_EA = smb2_set_ea,
#endif /* CIFS_XATTR */
	.next_header = smb2_next_header,
};
#endif /* CIFS_SMB311 */