diff options
author | Steve French <smfrench@austin.rr.com> | 2005-04-29 01:41:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-29 01:41:08 -0400 |
commit | 09d1db5c6131232f764046160c29118cd4e5e646 (patch) | |
tree | 198d0b03c0afa7974cd6dcea4e711351f4e056eb /fs/cifs/cifssmb.c | |
parent | 966ca9234754ece58870075972ef103e354de075 (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.c | 89 |
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); |