Skip to content

Commit b24df3e

Browse files
Ronnie SahlbergSteve French
authored andcommitted
cifs: update receive_encrypted_standard to handle compounded responses
Signed-off-by: Ronnie Sahlberg <[email protected]> Signed-off-by: Steve French <[email protected]> Reviewed-by: Paulo Alcantara <[email protected]> Reviewed-by: Pavel Shilovsky <[email protected]>
1 parent 1eb9fb5 commit b24df3e

File tree

4 files changed

+107
-43
lines changed

4 files changed

+107
-43
lines changed

fs/cifs/cifsglob.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@
7676
#define SMB_ECHO_INTERVAL_MAX 600
7777
#define SMB_ECHO_INTERVAL_DEFAULT 60
7878

79+
/* maximum number of PDUs in one compound */
80+
#define MAX_COMPOUND 5
81+
7982
/*
8083
* Default number of credits to keep available for SMB3.
8184
* This value is chosen somewhat arbitrarily. The Windows client
@@ -458,7 +461,7 @@ struct smb_version_operations {
458461
struct smb_rqst *, struct smb_rqst *);
459462
int (*is_transform_hdr)(void *buf);
460463
int (*receive_transform)(struct TCP_Server_Info *,
461-
struct mid_q_entry **);
464+
struct mid_q_entry **, char **, int *);
462465
enum securityEnum (*select_sectype)(struct TCP_Server_Info *,
463466
enum securityEnum);
464467
int (*next_header)(char *);

fs/cifs/connect.c

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -850,13 +850,14 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
850850
static int
851851
cifs_demultiplex_thread(void *p)
852852
{
853-
int length;
853+
int i, num_mids, length;
854854
struct TCP_Server_Info *server = p;
855855
unsigned int pdu_length;
856856
unsigned int next_offset;
857857
char *buf = NULL;
858858
struct task_struct *task_to_wake = NULL;
859-
struct mid_q_entry *mid_entry;
859+
struct mid_q_entry *mids[MAX_COMPOUND];
860+
char *bufs[MAX_COMPOUND];
860861

861862
current->flags |= PF_MEMALLOC;
862863
cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
@@ -923,58 +924,75 @@ cifs_demultiplex_thread(void *p)
923924
server->pdu_size = next_offset;
924925
}
925926

926-
mid_entry = NULL;
927+
memset(mids, 0, sizeof(mids));
928+
memset(bufs, 0, sizeof(bufs));
929+
num_mids = 0;
930+
927931
if (server->ops->is_transform_hdr &&
928932
server->ops->receive_transform &&
929933
server->ops->is_transform_hdr(buf)) {
930934
length = server->ops->receive_transform(server,
931-
&mid_entry);
935+
mids,
936+
bufs,
937+
&num_mids);
932938
} else {
933-
mid_entry = server->ops->find_mid(server, buf);
939+
mids[0] = server->ops->find_mid(server, buf);
940+
bufs[0] = buf;
941+
if (mids[0])
942+
num_mids = 1;
934943

935-
if (!mid_entry || !mid_entry->receive)
936-
length = standard_receive3(server, mid_entry);
944+
if (!mids[0] || !mids[0]->receive)
945+
length = standard_receive3(server, mids[0]);
937946
else
938-
length = mid_entry->receive(server, mid_entry);
947+
length = mids[0]->receive(server, mids[0]);
939948
}
940949

941950
if (length < 0) {
942-
if (mid_entry)
943-
cifs_mid_q_entry_release(mid_entry);
951+
for (i = 0; i < num_mids; i++)
952+
if (mids[i])
953+
cifs_mid_q_entry_release(mids[i]);
944954
continue;
945955
}
946956

947957
if (server->large_buf)
948958
buf = server->bigbuf;
949959

960+
950961
server->lstrp = jiffies;
951-
if (mid_entry != NULL) {
952-
mid_entry->resp_buf_size = server->pdu_size;
953-
if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
954-
mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
955-
server->ops->handle_cancelled_mid)
956-
server->ops->handle_cancelled_mid(
957-
mid_entry->resp_buf,
958-
server);
959962

960-
if (!mid_entry->multiRsp || mid_entry->multiEnd)
961-
mid_entry->callback(mid_entry);
963+
for (i = 0; i < num_mids; i++) {
964+
if (mids[i] != NULL) {
965+
mids[i]->resp_buf_size = server->pdu_size;
966+
if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
967+
mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
968+
server->ops->handle_cancelled_mid)
969+
server->ops->handle_cancelled_mid(
970+
mids[i]->resp_buf,
971+
server);
962972

963-
cifs_mid_q_entry_release(mid_entry);
964-
} else if (server->ops->is_oplock_break &&
965-
server->ops->is_oplock_break(buf, server)) {
966-
cifs_dbg(FYI, "Received oplock break\n");
967-
} else {
968-
cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
969-
atomic_read(&midCount));
970-
cifs_dump_mem("Received Data is: ", buf,
971-
HEADER_SIZE(server));
973+
if (!mids[i]->multiRsp || mids[i]->multiEnd)
974+
mids[i]->callback(mids[i]);
975+
976+
cifs_mid_q_entry_release(mids[i]);
977+
} else if (server->ops->is_oplock_break &&
978+
server->ops->is_oplock_break(bufs[i],
979+
server)) {
980+
cifs_dbg(FYI, "Received oplock break\n");
981+
} else {
982+
cifs_dbg(VFS, "No task to wake, unknown frame "
983+
"received! NumMids %d\n",
984+
atomic_read(&midCount));
985+
cifs_dump_mem("Received Data is: ", bufs[i],
986+
HEADER_SIZE(server));
972987
#ifdef CONFIG_CIFS_DEBUG2
973-
if (server->ops->dump_detail)
974-
server->ops->dump_detail(buf, server);
975-
cifs_dump_mids(server);
988+
if (server->ops->dump_detail)
989+
server->ops->dump_detail(bufs[i],
990+
server);
991+
cifs_dump_mids(server);
976992
#endif /* CIFS_DEBUG2 */
993+
}
977994
}
995+
978996
if (pdu_length > server->pdu_size) {
979997
if (!allocate_buffers(server))
980998
continue;

fs/cifs/smb2ops.c

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2942,13 +2942,20 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
29422942

29432943
static int
29442944
receive_encrypted_standard(struct TCP_Server_Info *server,
2945-
struct mid_q_entry **mid)
2945+
struct mid_q_entry **mids, char **bufs,
2946+
int *num_mids)
29462947
{
2947-
int length;
2948+
int ret, length;
29482949
char *buf = server->smallbuf;
2950+
char *tmpbuf;
2951+
struct smb2_sync_hdr *shdr;
29492952
unsigned int pdu_length = server->pdu_size;
29502953
unsigned int buf_size;
29512954
struct mid_q_entry *mid_entry;
2955+
int next_is_large;
2956+
char *next_buffer = NULL;
2957+
2958+
*num_mids = 0;
29522959

29532960
/* switch to large buffer if too big for a small one */
29542961
if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE) {
@@ -2969,24 +2976,61 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
29692976
if (length)
29702977
return length;
29712978

2979+
next_is_large = server->large_buf;
2980+
one_more:
2981+
shdr = (struct smb2_sync_hdr *)buf;
2982+
if (shdr->NextCommand) {
2983+
if (next_is_large) {
2984+
tmpbuf = server->bigbuf;
2985+
next_buffer = (char *)cifs_buf_get();
2986+
} else {
2987+
tmpbuf = server->smallbuf;
2988+
next_buffer = (char *)cifs_small_buf_get();
2989+
}
2990+
memcpy(next_buffer,
2991+
tmpbuf + le32_to_cpu(shdr->NextCommand),
2992+
pdu_length - le32_to_cpu(shdr->NextCommand));
2993+
}
2994+
29722995
mid_entry = smb2_find_mid(server, buf);
29732996
if (mid_entry == NULL)
29742997
cifs_dbg(FYI, "mid not found\n");
29752998
else {
29762999
cifs_dbg(FYI, "mid found\n");
29773000
mid_entry->decrypted = true;
3001+
mid_entry->resp_buf_size = server->pdu_size;
29783002
}
29793003

2980-
*mid = mid_entry;
3004+
if (*num_mids >= MAX_COMPOUND) {
3005+
cifs_dbg(VFS, "too many PDUs in compound\n");
3006+
return -1;
3007+
}
3008+
bufs[*num_mids] = buf;
3009+
mids[(*num_mids)++] = mid_entry;
29813010

29823011
if (mid_entry && mid_entry->handle)
2983-
return mid_entry->handle(server, mid_entry);
3012+
ret = mid_entry->handle(server, mid_entry);
3013+
else
3014+
ret = cifs_handle_standard(server, mid_entry);
3015+
3016+
if (ret == 0 && shdr->NextCommand) {
3017+
pdu_length -= le32_to_cpu(shdr->NextCommand);
3018+
server->large_buf = next_is_large;
3019+
if (next_is_large)
3020+
server->bigbuf = next_buffer;
3021+
else
3022+
server->smallbuf = next_buffer;
3023+
3024+
buf += le32_to_cpu(shdr->NextCommand);
3025+
goto one_more;
3026+
}
29843027

2985-
return cifs_handle_standard(server, mid_entry);
3028+
return ret;
29863029
}
29873030

29883031
static int
2989-
smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
3032+
smb3_receive_transform(struct TCP_Server_Info *server,
3033+
struct mid_q_entry **mids, char **bufs, int *num_mids)
29903034
{
29913035
char *buf = server->smallbuf;
29923036
unsigned int pdu_length = server->pdu_size;
@@ -3009,10 +3053,11 @@ smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
30093053
return -ECONNABORTED;
30103054
}
30113055

3056+
/* TODO: add support for compounds containing READ. */
30123057
if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server))
3013-
return receive_encrypted_read(server, mid);
3058+
return receive_encrypted_read(server, &mids[0]);
30143059

3015-
return receive_encrypted_standard(server, mid);
3060+
return receive_encrypted_standard(server, mids, bufs, num_mids);
30163061
}
30173062

30183063
int

fs/cifs/transport.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,6 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
383383
return rc;
384384
}
385385

386-
#define MAX_COMPOUND 5
387-
388386
static int
389387
smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
390388
struct smb_rqst *rqst, int flags)

0 commit comments

Comments
 (0)