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 | |
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>
-rw-r--r-- | fs/cifs/README | 8 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 89 | ||||
-rw-r--r-- | fs/cifs/connect.c | 62 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 11 |
4 files changed, 102 insertions, 68 deletions
diff --git a/fs/cifs/README b/fs/cifs/README index 48c37a6e9c3f..bec7b3fc8a72 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -420,7 +420,7 @@ Misc /proc/fs/cifs Flags and Debug Info | |||
420 | ======================================= | 420 | ======================================= |
421 | Informational pseudo-files: | 421 | Informational pseudo-files: |
422 | DebugData Displays information about active CIFS sessions | 422 | DebugData Displays information about active CIFS sessions |
423 | and shares. | 423 | and shares, as well as the cifs.ko version. |
424 | Stats Lists summary resource usage information as well as per | 424 | Stats Lists summary resource usage information as well as per |
425 | share statistics, if CONFIG_CIFS_STATS in enabled | 425 | share statistics, if CONFIG_CIFS_STATS in enabled |
426 | in the kernel configuration. | 426 | in the kernel configuration. |
@@ -477,7 +477,7 @@ and for more extensive tracing including the start of smb requests and responses | |||
477 | Two other experimental features are under development and to test | 477 | Two other experimental features are under development and to test |
478 | require enabling CONFIG_CIFS_EXPERIMENTAL | 478 | require enabling CONFIG_CIFS_EXPERIMENTAL |
479 | 479 | ||
480 | More efficient write operations and SMB buffer handling | 480 | More efficient write operations |
481 | 481 | ||
482 | DNOTIFY fcntl: needed for support of directory change | 482 | DNOTIFY fcntl: needed for support of directory change |
483 | notification and perhaps later for file leases) | 483 | notification and perhaps later for file leases) |
@@ -495,8 +495,8 @@ returned success. | |||
495 | 495 | ||
496 | Also note that "cat /proc/fs/cifs/DebugData" will display information about | 496 | Also note that "cat /proc/fs/cifs/DebugData" will display information about |
497 | the active sessions and the shares that are mounted. Note: NTLMv2 enablement | 497 | the active sessions and the shares that are mounted. Note: NTLMv2 enablement |
498 | will not work since they its implementation is not quite complete yet. | 498 | will not work since its implementation is not quite complete yet. Do not alter |
499 | Do not alter these configuration values unless you are doing specific testing. | 499 | the ExtendedSecurity configuration value unless you are doing specific testing. |
500 | Enabling extended security works to Windows 2000 Workstations and XP but not to | 500 | Enabling extended security works to Windows 2000 Workstations and XP but not to |
501 | Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" | 501 | Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" |
502 | (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not | 502 | (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not |
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); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8a8aa785e7b7..d5d49b584db4 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -157,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
157 | qhead); | 157 | qhead); |
158 | if(mid_entry) { | 158 | if(mid_entry) { |
159 | if(mid_entry->midState == MID_REQUEST_SUBMITTED) { | 159 | if(mid_entry->midState == MID_REQUEST_SUBMITTED) { |
160 | /* Mark other intransit requests as needing retry so | 160 | /* Mark other intransit requests as needing |
161 | we do not immediately mark the session bad again | 161 | retry so we do not immediately mark the |
162 | (ie after we reconnect below) as they timeout too */ | 162 | session bad again (ie after we reconnect |
163 | below) as they timeout too */ | ||
163 | mid_entry->midState = MID_RETRY_NEEDED; | 164 | mid_entry->midState = MID_RETRY_NEEDED; |
164 | } | 165 | } |
165 | } | 166 | } |
@@ -278,9 +279,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
278 | } else if (length <= 0) { | 279 | } else if (length <= 0) { |
279 | if(server->tcpStatus == CifsNew) { | 280 | if(server->tcpStatus == CifsNew) { |
280 | cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); | 281 | cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); |
281 | /* some servers kill tcp session rather than returning | 282 | /* some servers kill the TCP session rather than |
282 | smb negprot error in which case reconnecting here is | 283 | returning an SMB negprot error, in which |
283 | not going to help - return error to mount */ | 284 | case reconnecting here is not going to help, |
285 | and so simply return error to mount */ | ||
284 | break; | 286 | break; |
285 | } | 287 | } |
286 | if(length == -EINTR) { | 288 | if(length == -EINTR) { |
@@ -296,15 +298,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
296 | pdu_length = ntohl(smb_buffer->smb_buf_length); | 298 | pdu_length = ntohl(smb_buffer->smb_buf_length); |
297 | /* Only read pdu_length after below checks for too short (due | 299 | /* Only read pdu_length after below checks for too short (due |
298 | to e.g. int overflow) and too long ie beyond end of buf */ | 300 | to e.g. int overflow) and too long ie beyond end of buf */ |
299 | cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); | 301 | cFYI(1,("rfc1002 length(big endian)0x%x)", |
302 | pdu_length+4)); | ||
300 | 303 | ||
301 | temp = (char *) smb_buffer; | 304 | temp = (char *) smb_buffer; |
302 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { | 305 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { |
303 | cFYI(0,("Received 4 byte keep alive packet")); | 306 | cFYI(0,("Received 4 byte keep alive packet")); |
304 | } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) { | 307 | } else if (temp[0] == |
308 | (char) RFC1002_POSITIVE_SESSION_RESPONSE) { | ||
305 | cFYI(1,("Good RFC 1002 session rsp")); | 309 | cFYI(1,("Good RFC 1002 session rsp")); |
306 | } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { | 310 | } else if (temp[0] == |
307 | /* we get this from Windows 98 instead of error on SMB negprot response */ | 311 | (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { |
312 | /* we get this from Windows 98 instead of | ||
313 | an error on SMB negprot response */ | ||
308 | cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); | 314 | cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); |
309 | if(server->tcpStatus == CifsNew) { | 315 | if(server->tcpStatus == CifsNew) { |
310 | /* if nack on negprot (rather than | 316 | /* if nack on negprot (rather than |
@@ -320,7 +326,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
320 | connected to port 139 (the NACK is | 326 | connected to port 139 (the NACK is |
321 | since we do not begin with RFC1001 | 327 | since we do not begin with RFC1001 |
322 | session initialize frame) */ | 328 | session initialize frame) */ |
323 | server->addr.sockAddr.sin_port = htons(CIFS_PORT); | 329 | server->addr.sockAddr.sin_port = |
330 | htons(CIFS_PORT); | ||
324 | cifs_reconnect(server); | 331 | cifs_reconnect(server); |
325 | csocket = server->ssocket; | 332 | csocket = server->ssocket; |
326 | wake_up(&server->response_q); | 333 | wake_up(&server->response_q); |
@@ -333,8 +340,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
333 | csocket = server->ssocket; | 340 | csocket = server->ssocket; |
334 | continue; | 341 | continue; |
335 | } else { | 342 | } else { |
336 | if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) | 343 | if((pdu_length > CIFSMaxBufSize + |
337 | || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { | 344 | MAX_CIFS_HDR_SIZE - 4) || |
345 | (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { | ||
338 | cERROR(1, | 346 | cERROR(1, |
339 | ("Invalid size SMB length %d and pdu_length %d", | 347 | ("Invalid size SMB length %d and pdu_length %d", |
340 | length, pdu_length+4)); | 348 | length, pdu_length+4)); |
@@ -377,6 +385,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
377 | continue; | 385 | continue; |
378 | } | 386 | } |
379 | 387 | ||
388 | /* BB FIXME - add checkTrans2SMBSecondary() */ | ||
389 | |||
380 | task_to_wake = NULL; | 390 | task_to_wake = NULL; |
381 | spin_lock(&GlobalMid_Lock); | 391 | spin_lock(&GlobalMid_Lock); |
382 | list_for_each(tmp, &server->pending_mid_q) { | 392 | list_for_each(tmp, &server->pending_mid_q) { |
@@ -408,7 +418,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
408 | bigbuf = NULL; | 418 | bigbuf = NULL; |
409 | else | 419 | else |
410 | smallbuf = NULL; | 420 | smallbuf = NULL; |
411 | smb_buffer = NULL; /* will be freed by users thread after he is done */ | 421 | smb_buffer = NULL; /* will be freed by users thread after he is done */ |
412 | wake_up_process(task_to_wake); | 422 | wake_up_process(task_to_wake); |
413 | } else if (is_valid_oplock_break(smb_buffer) == FALSE) { | 423 | } else if (is_valid_oplock_break(smb_buffer) == FALSE) { |
414 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | 424 | cERROR(1, ("No task to wake, unknown frame rcvd!")); |
@@ -432,7 +442,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
432 | spin_unlock(&GlobalMid_Lock); | 442 | spin_unlock(&GlobalMid_Lock); |
433 | /* Although there should not be any requests blocked on | 443 | /* Although there should not be any requests blocked on |
434 | this queue it can not hurt to be paranoid and try to wake up requests | 444 | this queue it can not hurt to be paranoid and try to wake up requests |
435 | that may haven been blocked when more than 50 at time were on the wire | 445 | that may haven been blocked when more than 50 at time were on the wire |
436 | to the same server - they now will see the session is in exit state | 446 | to the same server - they now will see the session is in exit state |
437 | and get out of SendReceive. */ | 447 | and get out of SendReceive. */ |
438 | wake_up_all(&server->request_q); | 448 | wake_up_all(&server->request_q); |
@@ -451,7 +461,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
451 | 461 | ||
452 | read_lock(&GlobalSMBSeslock); | 462 | read_lock(&GlobalSMBSeslock); |
453 | if (list_empty(&server->pending_mid_q)) { | 463 | if (list_empty(&server->pending_mid_q)) { |
454 | /* loop through server session structures attached to this and mark them dead */ | 464 | /* loop through server session structures attached to this and |
465 | mark them dead */ | ||
455 | list_for_each(tmp, &GlobalSMBSessionList) { | 466 | list_for_each(tmp, &GlobalSMBSessionList) { |
456 | ses = | 467 | ses = |
457 | list_entry(tmp, struct cifsSesInfo, | 468 | list_entry(tmp, struct cifsSesInfo, |
@@ -468,7 +479,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
468 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 479 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
469 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { | 480 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { |
470 | cFYI(1, | 481 | cFYI(1, |
471 | (" Clearing Mid 0x%x - waking up ",mid_entry->mid)); | 482 | ("Clearing Mid 0x%x - waking up ",mid_entry->mid)); |
472 | task_to_wake = mid_entry->tsk; | 483 | task_to_wake = mid_entry->tsk; |
473 | if(task_to_wake) { | 484 | if(task_to_wake) { |
474 | wake_up_process(task_to_wake); | 485 | wake_up_process(task_to_wake); |
@@ -521,7 +532,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
521 | /* does not have to be a perfect mapping since the field is | 532 | /* does not have to be a perfect mapping since the field is |
522 | informational, only used for servers that do not support | 533 | informational, only used for servers that do not support |
523 | port 445 and it can be overridden at mount time */ | 534 | port 445 and it can be overridden at mount time */ |
524 | vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]); | 535 | vol->source_rfc1001_name[i] = |
536 | toupper(system_utsname.nodename[i]); | ||
525 | } | 537 | } |
526 | vol->source_rfc1001_name[15] = 0; | 538 | vol->source_rfc1001_name[15] = 0; |
527 | 539 | ||
@@ -596,14 +608,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
596 | /* NB: password legally can have multiple commas and | 608 | /* NB: password legally can have multiple commas and |
597 | the only illegal character in a password is null */ | 609 | the only illegal character in a password is null */ |
598 | 610 | ||
599 | if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) { | 611 | if ((value[temp_len] == 0) && |
612 | (value[temp_len+1] == separator[0])) { | ||
600 | /* reinsert comma */ | 613 | /* reinsert comma */ |
601 | value[temp_len] = separator[0]; | 614 | value[temp_len] = separator[0]; |
602 | temp_len+=2; /* move after the second comma */ | 615 | temp_len+=2; /* move after the second comma */ |
603 | while(value[temp_len] != 0) { | 616 | while(value[temp_len] != 0) { |
604 | if (value[temp_len] == separator[0]) { | 617 | if (value[temp_len] == separator[0]) { |
605 | if (value[temp_len+1] == separator[0]) { | 618 | if (value[temp_len+1] == |
606 | temp_len++; /* skip second comma */ | 619 | separator[0]) { |
620 | /* skip second comma */ | ||
621 | temp_len++; | ||
607 | } else { | 622 | } else { |
608 | /* single comma indicating start | 623 | /* single comma indicating start |
609 | of next parm */ | 624 | of next parm */ |
@@ -629,14 +644,15 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
629 | } | 644 | } |
630 | for(i=0,j=0;i<temp_len;i++,j++) { | 645 | for(i=0,j=0;i<temp_len;i++,j++) { |
631 | vol->password[j] = value[i]; | 646 | vol->password[j] = value[i]; |
632 | if(value[i] == separator[0] && value[i+1] == separator[0]) { | 647 | if(value[i] == separator[0] |
648 | && value[i+1] == separator[0]) { | ||
633 | /* skip second comma */ | 649 | /* skip second comma */ |
634 | i++; | 650 | i++; |
635 | } | 651 | } |
636 | } | 652 | } |
637 | vol->password[j] = 0; | 653 | vol->password[j] = 0; |
638 | } else { | 654 | } else { |
639 | vol->password = kcalloc(1, temp_len + 1, GFP_KERNEL); | 655 | vol->password = kcalloc(1, temp_len+1, GFP_KERNEL); |
640 | if(vol->password == NULL) { | 656 | if(vol->password == NULL) { |
641 | printk("CIFS: no memory for pass\n"); | 657 | printk("CIFS: no memory for pass\n"); |
642 | return 1; | 658 | return 1; |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 39170cffcad8..22557716f9af 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -409,10 +409,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb) | |||
409 | cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); | 409 | cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); |
410 | /* validate that new_entry is not past end of SMB */ | 410 | /* validate that new_entry is not past end of SMB */ |
411 | if(new_entry >= end_of_smb) { | 411 | if(new_entry >= end_of_smb) { |
412 | cFYI(1,("search entry %p began after end of SMB %p old entry %p", | 412 | cERROR(1, |
413 | new_entry,end_of_smb,old_entry)); | 413 | ("search entry %p began after end of SMB %p old entry %p", |
414 | new_entry, end_of_smb, old_entry)); | ||
414 | return NULL; | 415 | return NULL; |
415 | } else | 416 | } else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) { |
417 | cERROR(1,("search entry %p extends after end of SMB %p", | ||
418 | new_entry, end_of_smb)); | ||
419 | return NULL; | ||
420 | } else | ||
416 | return new_entry; | 421 | return new_entry; |
417 | 422 | ||
418 | } | 423 | } |