aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
authorSteve French <smfrench@austin.rr.com>2005-04-29 01:41:08 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-29 01:41:08 -0400
commit09d1db5c6131232f764046160c29118cd4e5e646 (patch)
tree198d0b03c0afa7974cd6dcea4e711351f4e056eb /fs/cifs/cifssmb.c
parent966ca9234754ece58870075972ef103e354de075 (diff)
[PATCH] cifs: improve check for search entry going beyond end of SMB transact
Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c89
1 files changed, 51 insertions, 38 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index b102ddb977ca..834297f7b5e1 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -75,7 +75,8 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
75 } 75 }
76 } 76 }
77 write_unlock(&GlobalSMBSeslock); 77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */ 78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
79 to this tcon */
79} 80}
80 81
81/* If the return code is zero, this function must fill in request_buf pointer */ 82/* If the return code is zero, this function must fill in request_buf pointer */
@@ -92,8 +93,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
92 if((tcon->ses) && (tcon->ses->server)){ 93 if((tcon->ses) && (tcon->ses->server)){
93 struct nls_table *nls_codepage; 94 struct nls_table *nls_codepage;
94 /* Give Demultiplex thread up to 10 seconds to 95 /* Give Demultiplex thread up to 10 seconds to
95 reconnect, should be greater than cifs socket 96 reconnect, should be greater than cifs socket
96 timeout which is 7 seconds */ 97 timeout which is 7 seconds */
97 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 98 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
98 wait_event_interruptible_timeout(tcon->ses->server->response_q, 99 wait_event_interruptible_timeout(tcon->ses->server->response_q,
99 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); 100 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
@@ -103,8 +104,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
103 (tcon->ses->status == CifsExiting)) { 104 (tcon->ses->status == CifsExiting)) {
104 cFYI(1,("gave up waiting on reconnect in smb_init")); 105 cFYI(1,("gave up waiting on reconnect in smb_init"));
105 return -EHOSTDOWN; 106 return -EHOSTDOWN;
106 } /* else "hard" mount - keep retrying until 107 } /* else "hard" mount - keep retrying
107 process is killed or server comes back up */ 108 until process is killed or server
109 comes back on-line */
108 } else /* TCP session is reestablished now */ 110 } else /* TCP session is reestablished now */
109 break; 111 break;
110 112
@@ -115,23 +117,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
115 simultaneously reconnect the same SMB session */ 117 simultaneously reconnect the same SMB session */
116 down(&tcon->ses->sesSem); 118 down(&tcon->ses->sesSem);
117 if(tcon->ses->status == CifsNeedReconnect) 119 if(tcon->ses->status == CifsNeedReconnect)
118 rc = cifs_setup_session(0, tcon->ses, nls_codepage); 120 rc = cifs_setup_session(0, tcon->ses,
121 nls_codepage);
119 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { 122 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
120 mark_open_files_invalid(tcon); 123 mark_open_files_invalid(tcon);
121 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, 124 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
122 nls_codepage); 125 , nls_codepage);
123 up(&tcon->ses->sesSem); 126 up(&tcon->ses->sesSem);
124 if(rc == 0) 127 if(rc == 0)
125 atomic_inc(&tconInfoReconnectCount); 128 atomic_inc(&tconInfoReconnectCount);
126 129
127 cFYI(1, ("reconnect tcon rc = %d", rc)); 130 cFYI(1, ("reconnect tcon rc = %d", rc));
128 /* Removed call to reopen open files here - 131 /* Removed call to reopen open files here -
129 it is safer (and faster) to reopen files 132 it is safer (and faster) to reopen files
130 one at a time as needed in read and write */ 133 one at a time as needed in read and write */
131 134
132 /* Check if handle based operation so we 135 /* Check if handle based operation so we
133 know whether we can continue or not without 136 know whether we can continue or not without
134 returning to caller to reset file handle */ 137 returning to caller to reset file handle */
135 switch(smb_command) { 138 switch(smb_command) {
136 case SMB_COM_READ_ANDX: 139 case SMB_COM_READ_ANDX:
137 case SMB_COM_WRITE_ANDX: 140 case SMB_COM_WRITE_ANDX:
@@ -184,20 +187,22 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
184 if(tcon) { 187 if(tcon) {
185 if((tcon->ses) && (tcon->ses->server)){ 188 if((tcon->ses) && (tcon->ses->server)){
186 struct nls_table *nls_codepage; 189 struct nls_table *nls_codepage;
187 /* Give Demultiplex thread up to 10 seconds to 190 /* Give Demultiplex thread up to 10 seconds to
188 reconnect, should be greater than cifs socket 191 reconnect, should be greater than cifs socket
189 timeout which is 7 seconds */ 192 timeout which is 7 seconds */
190 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 193 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
191 wait_event_interruptible_timeout(tcon->ses->server->response_q, 194 wait_event_interruptible_timeout(tcon->ses->server->response_q,
192 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); 195 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
193 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) { 196 if(tcon->ses->server->tcpStatus ==
197 CifsNeedReconnect) {
194 /* on "soft" mounts we wait once */ 198 /* on "soft" mounts we wait once */
195 if((tcon->retry == FALSE) || 199 if((tcon->retry == FALSE) ||
196 (tcon->ses->status == CifsExiting)) { 200 (tcon->ses->status == CifsExiting)) {
197 cFYI(1,("gave up waiting on reconnect in smb_init")); 201 cFYI(1,("gave up waiting on reconnect in smb_init"));
198 return -EHOSTDOWN; 202 return -EHOSTDOWN;
199 } /* else "hard" mount - keep retrying until 203 } /* else "hard" mount - keep retrying
200 process is killed or server comes back up */ 204 until process is killed or server
205 comes on-line */
201 } else /* TCP session is reestablished now */ 206 } else /* TCP session is reestablished now */
202 break; 207 break;
203 208
@@ -208,23 +213,24 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
208 simultaneously reconnect the same SMB session */ 213 simultaneously reconnect the same SMB session */
209 down(&tcon->ses->sesSem); 214 down(&tcon->ses->sesSem);
210 if(tcon->ses->status == CifsNeedReconnect) 215 if(tcon->ses->status == CifsNeedReconnect)
211 rc = cifs_setup_session(0, tcon->ses, nls_codepage); 216 rc = cifs_setup_session(0, tcon->ses,
217 nls_codepage);
212 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { 218 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
213 mark_open_files_invalid(tcon); 219 mark_open_files_invalid(tcon);
214 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, 220 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
215 nls_codepage); 221 tcon, nls_codepage);
216 up(&tcon->ses->sesSem); 222 up(&tcon->ses->sesSem);
217 if(rc == 0) 223 if(rc == 0)
218 atomic_inc(&tconInfoReconnectCount); 224 atomic_inc(&tconInfoReconnectCount);
219 225
220 cFYI(1, ("reconnect tcon rc = %d", rc)); 226 cFYI(1, ("reconnect tcon rc = %d", rc));
221 /* Removed call to reopen open files here - 227 /* Removed call to reopen open files here -
222 it is safer (and faster) to reopen files 228 it is safer (and faster) to reopen files
223 one at a time as needed in read and write */ 229 one at a time as needed in read and write */
224 230
225 /* Check if handle based operation so we 231 /* Check if handle based operation so we
226 know whether we can continue or not without 232 know whether we can continue or not without
227 returning to caller to reset file handle */ 233 returning to caller to reset file handle */
228 switch(smb_command) { 234 switch(smb_command) {
229 case SMB_COM_READ_ANDX: 235 case SMB_COM_READ_ANDX:
230 case SMB_COM_WRITE_ANDX: 236 case SMB_COM_WRITE_ANDX:
@@ -286,7 +292,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB)
286 if(total_size < 512) { 292 if(total_size < 512) {
287 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount); 293 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
288 /* BCC le converted in SendReceive */ 294 /* BCC le converted in SendReceive */
289 pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + 295 pBCC = (pSMB->hdr.WordCount * 2) +
296 sizeof(struct smb_hdr) +
290 (char *)pSMB; 297 (char *)pSMB;
291 if((total_size <= (*(u16 *)pBCC)) && 298 if((total_size <= (*(u16 *)pBCC)) &&
292 (total_size < 299 (total_size <
@@ -337,8 +344,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
337 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 344 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
338 if (rc == 0) { 345 if (rc == 0) {
339 server->secMode = pSMBr->SecurityMode; 346 server->secMode = pSMBr->SecurityMode;
340 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/ 347 server->secType = NTLM; /* BB override default for
341 /* one byte - no need to convert this or EncryptionKeyLen from le,*/ 348 NTLMv2 or kerberos v5 */
349 /* one byte - no need to convert this or EncryptionKeyLen
350 from little endian */
342 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); 351 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
343 /* probably no need to store and check maxvcs */ 352 /* probably no need to store and check maxvcs */
344 server->maxBuf = 353 server->maxBuf =
@@ -374,7 +383,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
374 pSMBr->u.extended_response. 383 pSMBr->u.extended_response.
375 GUID, 16) != 0) { 384 GUID, 16) != 0) {
376 cFYI(1, 385 cFYI(1,
377 ("UID of server does not match previous connection to same ip address")); 386 ("UID of server does not match previous connection to same ip address"));
378 memcpy(server-> 387 memcpy(server->
379 server_GUID, 388 server_GUID,
380 pSMBr->u. 389 pSMBr->u.
@@ -454,7 +463,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
454 up(&tcon->tconSem); 463 up(&tcon->tconSem);
455 return -EIO; 464 return -EIO;
456 } 465 }
457 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer); 466 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
467 (void **)&smb_buffer);
458 if (rc) { 468 if (rc) {
459 up(&tcon->tconSem); 469 up(&tcon->tconSem);
460 return rc; 470 return rc;
@@ -559,7 +569,7 @@ DelFileRetry:
559 PATH_MAX, nls_codepage, remap); 569 PATH_MAX, nls_codepage, remap);
560 name_len++; /* trailing null */ 570 name_len++; /* trailing null */
561 name_len *= 2; 571 name_len *= 2;
562 } else { /* BB improve the check for buffer overruns BB */ 572 } else { /* BB improve check for buffer overruns BB */
563 name_len = strnlen(fileName, PATH_MAX); 573 name_len = strnlen(fileName, PATH_MAX);
564 name_len++; /* trailing null */ 574 name_len++; /* trailing null */
565 strncpy(pSMB->fileName, fileName, name_len); 575 strncpy(pSMB->fileName, fileName, name_len);
@@ -609,7 +619,7 @@ RmDirRetry:
609 PATH_MAX, nls_codepage, remap); 619 PATH_MAX, nls_codepage, remap);
610 name_len++; /* trailing null */ 620 name_len++; /* trailing null */
611 name_len *= 2; 621 name_len *= 2;
612 } else { /* BB improve the check for buffer overruns BB */ 622 } else { /* BB improve check for buffer overruns BB */
613 name_len = strnlen(dirName, PATH_MAX); 623 name_len = strnlen(dirName, PATH_MAX);
614 name_len++; /* trailing null */ 624 name_len++; /* trailing null */
615 strncpy(pSMB->DirName, dirName, name_len); 625 strncpy(pSMB->DirName, dirName, name_len);
@@ -657,7 +667,7 @@ MkDirRetry:
657 PATH_MAX, nls_codepage, remap); 667 PATH_MAX, nls_codepage, remap);
658 name_len++; /* trailing null */ 668 name_len++; /* trailing null */
659 name_len *= 2; 669 name_len *= 2;
660 } else { /* BB improve the check for buffer overruns BB */ 670 } else { /* BB improve check for buffer overruns BB */
661 name_len = strnlen(name, PATH_MAX); 671 name_len = strnlen(name, PATH_MAX);
662 name_len++; /* trailing null */ 672 name_len++; /* trailing null */
663 strncpy(pSMB->DirName, name, name_len); 673 strncpy(pSMB->DirName, name, name_len);
@@ -712,7 +722,7 @@ openRetry:
712 name_len++; /* trailing null */ 722 name_len++; /* trailing null */
713 name_len *= 2; 723 name_len *= 2;
714 pSMB->NameLength = cpu_to_le16(name_len); 724 pSMB->NameLength = cpu_to_le16(name_len);
715 } else { /* BB improve the check for buffer overruns BB */ 725 } else { /* BB improve check for buffer overruns BB */
716 count = 0; /* no pad */ 726 count = 0; /* no pad */
717 name_len = strnlen(fileName, PATH_MAX); 727 name_len = strnlen(fileName, PATH_MAX);
718 name_len++; /* trailing null */ 728 name_len++; /* trailing null */
@@ -741,7 +751,8 @@ openRetry:
741 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); 751 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
742 pSMB->CreateDisposition = cpu_to_le32(openDisposition); 752 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
743 pSMB->CreateOptions = cpu_to_le32(create_options); 753 pSMB->CreateOptions = cpu_to_le32(create_options);
744 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/ 754 /* BB Expirement with various impersonation levels and verify */
755 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
745 pSMB->SecurityFlags = 756 pSMB->SecurityFlags =
746 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; 757 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
747 758
@@ -755,7 +766,7 @@ openRetry:
755 if (rc) { 766 if (rc) {
756 cFYI(1, ("Error in Open = %d", rc)); 767 cFYI(1, ("Error in Open = %d", rc));
757 } else { 768 } else {
758 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ 769 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
759 *netfid = pSMBr->Fid; /* cifs fid stays in le */ 770 *netfid = pSMBr->Fid; /* cifs fid stays in le */
760 /* Let caller know file was created so we can set the mode. */ 771 /* Let caller know file was created so we can set the mode. */
761 /* Do we care about the CreateAction in any other cases? */ 772 /* Do we care about the CreateAction in any other cases? */
@@ -2504,7 +2515,9 @@ findFirstRetry:
2504 psrch_inf->srch_entries_start = 2515 psrch_inf->srch_entries_start =
2505 (char *) &pSMBr->hdr.Protocol + 2516 (char *) &pSMBr->hdr.Protocol +
2506 le16_to_cpu(pSMBr->t2.DataOffset); 2517 le16_to_cpu(pSMBr->t2.DataOffset);
2507 2518/* if(le16_to_cpu(pSMBr->t2.DataCount) != le16_to_cpu(pSMBr->t2.TotalDataCount)) {
2519 cERROR(1,("DC: %d TDC: %d",pSMBr->t2.DataCount,pSMBr->t2.TotalDataCount));
2520} */ /* BB removeme BB */
2508 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + 2521 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2509 le16_to_cpu(pSMBr->t2.ParameterOffset)); 2522 le16_to_cpu(pSMBr->t2.ParameterOffset));
2510 2523
@@ -2516,7 +2529,7 @@ findFirstRetry:
2516 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); 2529 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2517 psrch_inf->index_of_last_entry = 2530 psrch_inf->index_of_last_entry =
2518 psrch_inf->entries_in_buffer; 2531 psrch_inf->entries_in_buffer;
2519/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ 2532/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ /* BB removeme BB */
2520 *pnetfid = parms->SearchHandle; 2533 *pnetfid = parms->SearchHandle;
2521 } else { 2534 } else {
2522 cifs_buf_release(pSMB); 2535 cifs_buf_release(pSMB);