Commit 09d1db5c authored by Steve French's avatar Steve French Committed by Linus Torvalds

[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: default avatarLinus Torvalds <torvalds@osdl.org>
parent 966ca923
...@@ -420,7 +420,7 @@ Misc /proc/fs/cifs Flags and Debug Info ...@@ -420,7 +420,7 @@ Misc /proc/fs/cifs Flags and Debug Info
======================================= =======================================
Informational pseudo-files: Informational pseudo-files:
DebugData Displays information about active CIFS sessions DebugData Displays information about active CIFS sessions
and shares. and shares, as well as the cifs.ko version.
Stats Lists summary resource usage information as well as per Stats Lists summary resource usage information as well as per
share statistics, if CONFIG_CIFS_STATS in enabled share statistics, if CONFIG_CIFS_STATS in enabled
in the kernel configuration. in the kernel configuration.
...@@ -477,7 +477,7 @@ and for more extensive tracing including the start of smb requests and responses ...@@ -477,7 +477,7 @@ and for more extensive tracing including the start of smb requests and responses
Two other experimental features are under development and to test Two other experimental features are under development and to test
require enabling CONFIG_CIFS_EXPERIMENTAL require enabling CONFIG_CIFS_EXPERIMENTAL
More efficient write operations and SMB buffer handling More efficient write operations
DNOTIFY fcntl: needed for support of directory change DNOTIFY fcntl: needed for support of directory change
notification and perhaps later for file leases) notification and perhaps later for file leases)
...@@ -495,8 +495,8 @@ returned success. ...@@ -495,8 +495,8 @@ returned success.
Also note that "cat /proc/fs/cifs/DebugData" will display information about Also note that "cat /proc/fs/cifs/DebugData" will display information about
the active sessions and the shares that are mounted. Note: NTLMv2 enablement the active sessions and the shares that are mounted. Note: NTLMv2 enablement
will not work since they its implementation is not quite complete yet. will not work since its implementation is not quite complete yet. Do not alter
Do not alter these configuration values unless you are doing specific testing. the ExtendedSecurity configuration value unless you are doing specific testing.
Enabling extended security works to Windows 2000 Workstations and XP but not to Enabling extended security works to Windows 2000 Workstations and XP but not to
Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" Windows 2000 server or Samba since it does not usually send "raw NTLMSSP"
(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
......
...@@ -75,7 +75,8 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon) ...@@ -75,7 +75,8 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
} }
} }
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */ /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
to this tcon */
} }
/* If the return code is zero, this function must fill in request_buf pointer */ /* 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,8 +93,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if((tcon->ses) && (tcon->ses->server)){ if((tcon->ses) && (tcon->ses->server)){
struct nls_table *nls_codepage; struct nls_table *nls_codepage;
/* Give Demultiplex thread up to 10 seconds to /* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket reconnect, should be greater than cifs socket
timeout which is 7 seconds */ timeout which is 7 seconds */
while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
wait_event_interruptible_timeout(tcon->ses->server->response_q, wait_event_interruptible_timeout(tcon->ses->server->response_q,
(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
...@@ -103,8 +104,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -103,8 +104,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
(tcon->ses->status == CifsExiting)) { (tcon->ses->status == CifsExiting)) {
cFYI(1,("gave up waiting on reconnect in smb_init")); cFYI(1,("gave up waiting on reconnect in smb_init"));
return -EHOSTDOWN; return -EHOSTDOWN;
} /* else "hard" mount - keep retrying until } /* else "hard" mount - keep retrying
process is killed or server comes back up */ until process is killed or server
comes back on-line */
} else /* TCP session is reestablished now */ } else /* TCP session is reestablished now */
break; break;
...@@ -115,23 +117,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -115,23 +117,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
simultaneously reconnect the same SMB session */ simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem); down(&tcon->ses->sesSem);
if(tcon->ses->status == CifsNeedReconnect) if(tcon->ses->status == CifsNeedReconnect)
rc = cifs_setup_session(0, tcon->ses, nls_codepage); rc = cifs_setup_session(0, tcon->ses,
nls_codepage);
if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
mark_open_files_invalid(tcon); mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
nls_codepage); , nls_codepage);
up(&tcon->ses->sesSem); up(&tcon->ses->sesSem);
if(rc == 0) if(rc == 0)
atomic_inc(&tconInfoReconnectCount); atomic_inc(&tconInfoReconnectCount);
cFYI(1, ("reconnect tcon rc = %d", rc)); cFYI(1, ("reconnect tcon rc = %d", rc));
/* Removed call to reopen open files here - /* Removed call to reopen open files here -
it is safer (and faster) to reopen files it is safer (and faster) to reopen files
one at a time as needed in read and write */ one at a time as needed in read and write */
/* Check if handle based operation so we /* Check if handle based operation so we
know whether we can continue or not without know whether we can continue or not without
returning to caller to reset file handle */ returning to caller to reset file handle */
switch(smb_command) { switch(smb_command) {
case SMB_COM_READ_ANDX: case SMB_COM_READ_ANDX:
case SMB_COM_WRITE_ANDX: case SMB_COM_WRITE_ANDX:
...@@ -184,20 +187,22 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -184,20 +187,22 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if(tcon) { if(tcon) {
if((tcon->ses) && (tcon->ses->server)){ if((tcon->ses) && (tcon->ses->server)){
struct nls_table *nls_codepage; struct nls_table *nls_codepage;
/* Give Demultiplex thread up to 10 seconds to /* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket reconnect, should be greater than cifs socket
timeout which is 7 seconds */ timeout which is 7 seconds */
while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
wait_event_interruptible_timeout(tcon->ses->server->response_q, wait_event_interruptible_timeout(tcon->ses->server->response_q,
(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
if(tcon->ses->server->tcpStatus == CifsNeedReconnect) { if(tcon->ses->server->tcpStatus ==
CifsNeedReconnect) {
/* on "soft" mounts we wait once */ /* on "soft" mounts we wait once */
if((tcon->retry == FALSE) || if((tcon->retry == FALSE) ||
(tcon->ses->status == CifsExiting)) { (tcon->ses->status == CifsExiting)) {
cFYI(1,("gave up waiting on reconnect in smb_init")); cFYI(1,("gave up waiting on reconnect in smb_init"));
return -EHOSTDOWN; return -EHOSTDOWN;
} /* else "hard" mount - keep retrying until } /* else "hard" mount - keep retrying
process is killed or server comes back up */ until process is killed or server
comes on-line */
} else /* TCP session is reestablished now */ } else /* TCP session is reestablished now */
break; break;
...@@ -208,23 +213,24 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -208,23 +213,24 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
simultaneously reconnect the same SMB session */ simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem); down(&tcon->ses->sesSem);
if(tcon->ses->status == CifsNeedReconnect) if(tcon->ses->status == CifsNeedReconnect)
rc = cifs_setup_session(0, tcon->ses, nls_codepage); rc = cifs_setup_session(0, tcon->ses,
nls_codepage);
if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
mark_open_files_invalid(tcon); mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, rc = CIFSTCon(0, tcon->ses, tcon->treeName,
nls_codepage); tcon, nls_codepage);
up(&tcon->ses->sesSem); up(&tcon->ses->sesSem);
if(rc == 0) if(rc == 0)
atomic_inc(&tconInfoReconnectCount); atomic_inc(&tconInfoReconnectCount);
cFYI(1, ("reconnect tcon rc = %d", rc)); cFYI(1, ("reconnect tcon rc = %d", rc));
/* Removed call to reopen open files here - /* Removed call to reopen open files here -
it is safer (and faster) to reopen files it is safer (and faster) to reopen files
one at a time as needed in read and write */ one at a time as needed in read and write */
/* Check if handle based operation so we /* Check if handle based operation so we
know whether we can continue or not without know whether we can continue or not without
returning to caller to reset file handle */ returning to caller to reset file handle */
switch(smb_command) { switch(smb_command) {
case SMB_COM_READ_ANDX: case SMB_COM_READ_ANDX:
case SMB_COM_WRITE_ANDX: case SMB_COM_WRITE_ANDX:
...@@ -286,7 +292,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB) ...@@ -286,7 +292,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB)
if(total_size < 512) { if(total_size < 512) {
total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount); total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
/* BCC le converted in SendReceive */ /* BCC le converted in SendReceive */
pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + pBCC = (pSMB->hdr.WordCount * 2) +
sizeof(struct smb_hdr) +
(char *)pSMB; (char *)pSMB;
if((total_size <= (*(u16 *)pBCC)) && if((total_size <= (*(u16 *)pBCC)) &&
(total_size < (total_size <
...@@ -337,8 +344,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -337,8 +344,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc == 0) { if (rc == 0) {
server->secMode = pSMBr->SecurityMode; server->secMode = pSMBr->SecurityMode;
server->secType = NTLM; /* BB override default for NTLMv2 or krb*/ server->secType = NTLM; /* BB override default for
/* one byte - no need to convert this or EncryptionKeyLen from le,*/ NTLMv2 or kerberos v5 */
/* one byte - no need to convert this or EncryptionKeyLen
from little endian */
server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
/* probably no need to store and check maxvcs */ /* probably no need to store and check maxvcs */
server->maxBuf = server->maxBuf =
...@@ -374,7 +383,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -374,7 +383,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMBr->u.extended_response. pSMBr->u.extended_response.
GUID, 16) != 0) { GUID, 16) != 0) {
cFYI(1, cFYI(1,
("UID of server does not match previous connection to same ip address")); ("UID of server does not match previous connection to same ip address"));
memcpy(server-> memcpy(server->
server_GUID, server_GUID,
pSMBr->u. pSMBr->u.
...@@ -454,7 +463,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) ...@@ -454,7 +463,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
up(&tcon->tconSem); up(&tcon->tconSem);
return -EIO; return -EIO;
} }
rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer); rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
(void **)&smb_buffer);
if (rc) { if (rc) {
up(&tcon->tconSem); up(&tcon->tconSem);
return rc; return rc;
...@@ -559,7 +569,7 @@ CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName, ...@@ -559,7 +569,7 @@ CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve check for buffer overruns BB */
name_len = strnlen(fileName, PATH_MAX); name_len = strnlen(fileName, PATH_MAX);
name_len++; /* trailing null */ name_len++; /* trailing null */
strncpy(pSMB->fileName, fileName, name_len); strncpy(pSMB->fileName, fileName, name_len);
...@@ -609,7 +619,7 @@ CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName, ...@@ -609,7 +619,7 @@ CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve check for buffer overruns BB */
name_len = strnlen(dirName, PATH_MAX); name_len = strnlen(dirName, PATH_MAX);
name_len++; /* trailing null */ name_len++; /* trailing null */
strncpy(pSMB->DirName, dirName, name_len); strncpy(pSMB->DirName, dirName, name_len);
...@@ -657,7 +667,7 @@ CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, ...@@ -657,7 +667,7 @@ CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve check for buffer overruns BB */
name_len = strnlen(name, PATH_MAX); name_len = strnlen(name, PATH_MAX);
name_len++; /* trailing null */ name_len++; /* trailing null */
strncpy(pSMB->DirName, name, name_len); strncpy(pSMB->DirName, name, name_len);
...@@ -712,7 +722,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, ...@@ -712,7 +722,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
pSMB->NameLength = cpu_to_le16(name_len); pSMB->NameLength = cpu_to_le16(name_len);
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve check for buffer overruns BB */
count = 0; /* no pad */ count = 0; /* no pad */
name_len = strnlen(fileName, PATH_MAX); name_len = strnlen(fileName, PATH_MAX);
name_len++; /* trailing null */ name_len++; /* trailing null */
...@@ -741,7 +751,8 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, ...@@ -741,7 +751,8 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
pSMB->CreateDisposition = cpu_to_le32(openDisposition); pSMB->CreateDisposition = cpu_to_le32(openDisposition);
pSMB->CreateOptions = cpu_to_le32(create_options); pSMB->CreateOptions = cpu_to_le32(create_options);
pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/ /* BB Expirement with various impersonation levels and verify */
pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
pSMB->SecurityFlags = pSMB->SecurityFlags =
SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
...@@ -755,7 +766,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, ...@@ -755,7 +766,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
if (rc) { if (rc) {
cFYI(1, ("Error in Open = %d", rc)); cFYI(1, ("Error in Open = %d", rc));
} else { } else {
*pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
*netfid = pSMBr->Fid; /* cifs fid stays in le */ *netfid = pSMBr->Fid; /* cifs fid stays in le */
/* Let caller know file was created so we can set the mode. */ /* Let caller know file was created so we can set the mode. */
/* Do we care about the CreateAction in any other cases? */ /* Do we care about the CreateAction in any other cases? */
...@@ -2504,7 +2515,9 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, ...@@ -2504,7 +2515,9 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
psrch_inf->srch_entries_start = psrch_inf->srch_entries_start =
(char *) &pSMBr->hdr.Protocol + (char *) &pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.DataOffset); le16_to_cpu(pSMBr->t2.DataOffset);
/* if(le16_to_cpu(pSMBr->t2.DataCount) != le16_to_cpu(pSMBr->t2.TotalDataCount)) {
cERROR(1,("DC: %d TDC: %d",pSMBr->t2.DataCount,pSMBr->t2.TotalDataCount));
} */ /* BB removeme BB */
parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.ParameterOffset)); le16_to_cpu(pSMBr->t2.ParameterOffset));
...@@ -2516,7 +2529,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, ...@@ -2516,7 +2529,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
psrch_inf->index_of_last_entry = psrch_inf->index_of_last_entry =
psrch_inf->entries_in_buffer; psrch_inf->entries_in_buffer;
/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ /*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ /* BB removeme BB */
*pnetfid = parms->SearchHandle; *pnetfid = parms->SearchHandle;
} else { } else {
cifs_buf_release(pSMB); cifs_buf_release(pSMB);
......
...@@ -157,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server) ...@@ -157,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
qhead); qhead);
if(mid_entry) { if(mid_entry) {
if(mid_entry->midState == MID_REQUEST_SUBMITTED) { if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
/* Mark other intransit requests as needing retry so /* Mark other intransit requests as needing
we do not immediately mark the session bad again retry so we do not immediately mark the
(ie after we reconnect below) as they timeout too */ session bad again (ie after we reconnect
below) as they timeout too */
mid_entry->midState = MID_RETRY_NEEDED; mid_entry->midState = MID_RETRY_NEEDED;
} }
} }
...@@ -278,9 +279,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -278,9 +279,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
} else if (length <= 0) { } else if (length <= 0) {
if(server->tcpStatus == CifsNew) { if(server->tcpStatus == CifsNew) {
cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
/* some servers kill tcp session rather than returning /* some servers kill the TCP session rather than
smb negprot error in which case reconnecting here is returning an SMB negprot error, in which
not going to help - return error to mount */ case reconnecting here is not going to help,
and so simply return error to mount */
break; break;
} }
if(length == -EINTR) { if(length == -EINTR) {
...@@ -296,15 +298,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -296,15 +298,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
pdu_length = ntohl(smb_buffer->smb_buf_length); pdu_length = ntohl(smb_buffer->smb_buf_length);
/* Only read pdu_length after below checks for too short (due /* Only read pdu_length after below checks for too short (due
to e.g. int overflow) and too long ie beyond end of buf */ to e.g. int overflow) and too long ie beyond end of buf */
cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); cFYI(1,("rfc1002 length(big endian)0x%x)",
pdu_length+4));
temp = (char *) smb_buffer; temp = (char *) smb_buffer;
if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
cFYI(0,("Received 4 byte keep alive packet")); cFYI(0,("Received 4 byte keep alive packet"));
} else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) { } else if (temp[0] ==
(char) RFC1002_POSITIVE_SESSION_RESPONSE) {
cFYI(1,("Good RFC 1002 session rsp")); cFYI(1,("Good RFC 1002 session rsp"));
} else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { } else if (temp[0] ==
/* we get this from Windows 98 instead of error on SMB negprot response */ (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
/* we get this from Windows 98 instead of
an error on SMB negprot response */
cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
if(server->tcpStatus == CifsNew) { if(server->tcpStatus == CifsNew) {
/* if nack on negprot (rather than /* if nack on negprot (rather than
...@@ -320,7 +326,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -320,7 +326,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
connected to port 139 (the NACK is connected to port 139 (the NACK is
since we do not begin with RFC1001 since we do not begin with RFC1001
session initialize frame) */ session initialize frame) */
server->addr.sockAddr.sin_port = htons(CIFS_PORT); server->addr.sockAddr.sin_port =
htons(CIFS_PORT);
cifs_reconnect(server); cifs_reconnect(server);
csocket = server->ssocket; csocket = server->ssocket;
wake_up(&server->response_q); wake_up(&server->response_q);
...@@ -333,8 +340,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -333,8 +340,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
csocket = server->ssocket; csocket = server->ssocket;
continue; continue;
} else { } else {
if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) if((pdu_length > CIFSMaxBufSize +
|| (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { MAX_CIFS_HDR_SIZE - 4) ||
(pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
cERROR(1, cERROR(1,
("Invalid size SMB length %d and pdu_length %d", ("Invalid size SMB length %d and pdu_length %d",
length, pdu_length+4)); length, pdu_length+4));
...@@ -377,6 +385,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -377,6 +385,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
continue; continue;
} }
/* BB FIXME - add checkTrans2SMBSecondary() */
task_to_wake = NULL; task_to_wake = NULL;
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) { list_for_each(tmp, &server->pending_mid_q) {
...@@ -408,7 +418,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -408,7 +418,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
bigbuf = NULL; bigbuf = NULL;
else else
smallbuf = NULL; smallbuf = NULL;
smb_buffer = NULL; /* will be freed by users thread after he is done */ smb_buffer = NULL; /* will be freed by users thread after he is done */
wake_up_process(task_to_wake); wake_up_process(task_to_wake);
} else if (is_valid_oplock_break(smb_buffer) == FALSE) { } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
cERROR(1, ("No task to wake, unknown frame rcvd!")); cERROR(1, ("No task to wake, unknown frame rcvd!"));
...@@ -432,7 +442,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -432,7 +442,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
/* Although there should not be any requests blocked on /* Although there should not be any requests blocked on
this queue it can not hurt to be paranoid and try to wake up requests this queue it can not hurt to be paranoid and try to wake up requests
that may haven been blocked when more than 50 at time were on the wire that may haven been blocked when more than 50 at time were on the wire
to the same server - they now will see the session is in exit state to the same server - they now will see the session is in exit state
and get out of SendReceive. */ and get out of SendReceive. */
wake_up_all(&server->request_q); wake_up_all(&server->request_q);
...@@ -451,7 +461,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -451,7 +461,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
if (list_empty(&server->pending_mid_q)) { if (list_empty(&server->pending_mid_q)) {
/* loop through server session structures attached to this and mark them dead */ /* loop through server session structures attached to this and
mark them dead */
list_for_each(tmp, &GlobalSMBSessionList) { list_for_each(tmp, &GlobalSMBSessionList) {
ses = ses =
list_entry(tmp, struct cifsSesInfo, list_entry(tmp, struct cifsSesInfo,
...@@ -468,7 +479,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -468,7 +479,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
mid_entry = list_entry(tmp, struct mid_q_entry, qhead); mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if (mid_entry->midState == MID_REQUEST_SUBMITTED) { if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
cFYI(1, cFYI(1,
(" Clearing Mid 0x%x - waking up ",mid_entry->mid)); ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
task_to_wake = mid_entry->tsk; task_to_wake = mid_entry->tsk;
if(task_to_wake) { if(task_to_wake) {
wake_up_process(task_to_wake); wake_up_process(task_to_wake);
...@@ -521,7 +532,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) ...@@ -521,7 +532,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
/* does not have to be a perfect mapping since the field is /* does not have to be a perfect mapping since the field is
informational, only used for servers that do not support informational, only used for servers that do not support
port 445 and it can be overridden at mount time */ port 445 and it can be overridden at mount time */
vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]); vol->source_rfc1001_name[i] =
toupper(system_utsname.nodename[i]);
} }
vol->source_rfc1001_name[15] = 0; vol->source_rfc1001_name[15] = 0;
...@@ -596,14 +608,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) ...@@ -596,14 +608,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
/* NB: password legally can have multiple commas and /* NB: password legally can have multiple commas and
the only illegal character in a password is null */ the only illegal character in a password is null */
if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) { if ((value[temp_len] == 0) &&
(value[temp_len+1] == separator[0])) {
/* reinsert comma */ /* reinsert comma */
value[temp_len] = separator[0]; value[temp_len] = separator[0];
temp_len+=2; /* move after the second comma */ temp_len+=2; /* move after the second comma */
while(value[temp_len] != 0) { while(value[temp_len] != 0) {
if (value[temp_len] == separator[0]) { if (value[temp_len] == separator[0]) {
if (value[temp_len+1] == separator[0]) { if (value[temp_len+1] ==
temp_len++; /* skip second comma */ separator[0]) {
/* skip second comma */
temp_len++;
} else { } else {
/* single comma indicating start /* single comma indicating start
of next parm */ of next parm */
...@@ -629,14 +644,15 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) ...@@ -629,14 +644,15 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
} }
for(i=0,j=0;i<temp_len;i++,j++) { for(i=0,j=0;i<temp_len;i++,j++) {
vol->password[j] = value[i]; vol->password[j] = value[i];
if(value[i] == separator[0] && value[i+1] == separator[0]) { if(value[i] == separator[0]
&& value[i+1] == separator[0]) {
/* skip second comma */ /* skip second comma */
i++; i++;
} }
} }
vol->password[j] = 0; vol->password[j] = 0;
} else { } else {
vol->password = kcalloc(1, temp_len + 1, GFP_KERNEL); vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
if(vol->password == NULL) { if(vol->password == NULL) {
printk("CIFS: no memory for pass\n"); printk("CIFS: no memory for pass\n");
return 1; return 1;
......
...@@ -409,10 +409,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb) ...@@ -409,10 +409,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
/* validate that new_entry is not past end of SMB */ /* validate that new_entry is not past end of SMB */
if(new_entry >= end_of_smb) { if(new_entry >= end_of_smb) {
cFYI(1,("search entry %p began after end of SMB %p old entry %p", cERROR(1,
new_entry,end_of_smb,old_entry)); ("search entry %p began after end of SMB %p old entry %p",
new_entry, end_of_smb, old_entry));
return NULL; return NULL;
} else } else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) {
cERROR(1,("search entry %p extends after end of SMB %p",
new_entry, end_of_smb));
return NULL;
} else
return new_entry; return new_entry;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment