Skip to content

Commit

Permalink
[PATCH] cifs: improve check for search entry going beyond end of SMB …
Browse files Browse the repository at this point in the history
…transact

Signed-off-by: Steve French (sfrench@us.ibm.com)
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Steve French authored and Linus Torvalds committed Apr 29, 2005
1 parent 966ca92 commit 09d1db5
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 68 deletions.
8 changes: 4 additions & 4 deletions fs/cifs/README
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ Misc /proc/fs/cifs Flags and Debug Info
=======================================
Informational pseudo-files:
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
share statistics, if CONFIG_CIFS_STATS in enabled
in the kernel configuration.
Expand Down Expand Up @@ -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
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
notification and perhaps later for file leases)
Expand All @@ -495,8 +495,8 @@ returned success.

Also note that "cat /proc/fs/cifs/DebugData" will display information about
the active sessions and the shares that are mounted. Note: NTLMv2 enablement
will not work since they its implementation is not quite complete yet.
Do not alter these configuration values unless you are doing specific testing.
will not work since its implementation is not quite complete yet. Do not alter
the ExtendedSecurity configuration value unless you are doing specific testing.
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"
(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not
Expand Down
89 changes: 51 additions & 38 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
}
}
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 */
Expand All @@ -92,8 +93,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if((tcon->ses) && (tcon->ses->server)){
struct nls_table *nls_codepage;
/* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket
timeout which is 7 seconds */
reconnect, should be greater than cifs socket
timeout which is 7 seconds */
while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
wait_event_interruptible_timeout(tcon->ses->server->response_q,
(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
Expand All @@ -103,8 +104,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
(tcon->ses->status == CifsExiting)) {
cFYI(1,("gave up waiting on reconnect in smb_init"));
return -EHOSTDOWN;
} /* else "hard" mount - keep retrying until
process is killed or server comes back up */
} /* else "hard" mount - keep retrying
until process is killed or server
comes back on-line */
} else /* TCP session is reestablished now */
break;

Expand All @@ -115,23 +117,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem);
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)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
nls_codepage);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
, nls_codepage);
up(&tcon->ses->sesSem);
if(rc == 0)
atomic_inc(&tconInfoReconnectCount);

cFYI(1, ("reconnect tcon rc = %d", rc));
/* Removed call to reopen open files here -
it is safer (and faster) to reopen files
one at a time as needed in read and write */
it is safer (and faster) to reopen files
one at a time as needed in read and write */

/* Check if handle based operation so we
know whether we can continue or not without
returning to caller to reset file handle */
know whether we can continue or not without
returning to caller to reset file handle */
switch(smb_command) {
case SMB_COM_READ_ANDX:
case SMB_COM_WRITE_ANDX:
Expand Down Expand Up @@ -184,20 +187,22 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
if(tcon) {
if((tcon->ses) && (tcon->ses->server)){
struct nls_table *nls_codepage;
/* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket
timeout which is 7 seconds */
/* Give Demultiplex thread up to 10 seconds to
reconnect, should be greater than cifs socket
timeout which is 7 seconds */
while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
wait_event_interruptible_timeout(tcon->ses->server->response_q,
(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 */
if((tcon->retry == FALSE) ||
(tcon->ses->status == CifsExiting)) {
cFYI(1,("gave up waiting on reconnect in smb_init"));
return -EHOSTDOWN;
} /* else "hard" mount - keep retrying until
process is killed or server comes back up */
} /* else "hard" mount - keep retrying
until process is killed or server
comes on-line */
} else /* TCP session is reestablished now */
break;

Expand All @@ -208,23 +213,24 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
simultaneously reconnect the same SMB session */
down(&tcon->ses->sesSem);
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)) {
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
nls_codepage);
rc = CIFSTCon(0, tcon->ses, tcon->treeName,
tcon, nls_codepage);
up(&tcon->ses->sesSem);
if(rc == 0)
atomic_inc(&tconInfoReconnectCount);

cFYI(1, ("reconnect tcon rc = %d", rc));
/* Removed call to reopen open files here -
it is safer (and faster) to reopen files
one at a time as needed in read and write */
it is safer (and faster) to reopen files
one at a time as needed in read and write */

/* Check if handle based operation so we
know whether we can continue or not without
returning to caller to reset file handle */
know whether we can continue or not without
returning to caller to reset file handle */
switch(smb_command) {
case SMB_COM_READ_ANDX:
case SMB_COM_WRITE_ANDX:
Expand Down Expand Up @@ -286,7 +292,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB)
if(total_size < 512) {
total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
/* 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;
if((total_size <= (*(u16 *)pBCC)) &&
(total_size <
Expand Down Expand Up @@ -337,8 +344,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc == 0) {
server->secMode = pSMBr->SecurityMode;
server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
/* one byte - no need to convert this or EncryptionKeyLen from le,*/
server->secType = NTLM; /* BB override default for
NTLMv2 or kerberos v5 */
/* one byte - no need to convert this or EncryptionKeyLen
from little endian */
server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
/* probably no need to store and check maxvcs */
server->maxBuf =
Expand Down Expand Up @@ -374,7 +383,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMBr->u.extended_response.
GUID, 16) != 0) {
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->
server_GUID,
pSMBr->u.
Expand Down Expand Up @@ -454,7 +463,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
up(&tcon->tconSem);
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) {
up(&tcon->tconSem);
return rc;
Expand Down Expand Up @@ -559,7 +569,7 @@ CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
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++; /* trailing null */
strncpy(pSMB->fileName, fileName, name_len);
Expand Down Expand Up @@ -609,7 +619,7 @@ CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
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++; /* trailing null */
strncpy(pSMB->DirName, dirName, name_len);
Expand Down Expand Up @@ -657,7 +667,7 @@ CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
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++; /* trailing null */
strncpy(pSMB->DirName, name, name_len);
Expand Down Expand Up @@ -712,7 +722,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
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 */
name_len = strnlen(fileName, PATH_MAX);
name_len++; /* trailing null */
Expand Down Expand Up @@ -741,7 +751,8 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
pSMB->CreateDisposition = cpu_to_le32(openDisposition);
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 =
SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;

Expand All @@ -755,7 +766,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
if (rc) {
cFYI(1, ("Error in Open = %d", rc));
} 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 */
/* Let caller know file was created so we can set the mode. */
/* Do we care about the CreateAction in any other cases? */
Expand Down Expand Up @@ -2504,7 +2515,9 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
psrch_inf->srch_entries_start =
(char *) &pSMBr->hdr.Protocol +
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 +
le16_to_cpu(pSMBr->t2.ParameterOffset));

Expand All @@ -2516,7 +2529,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
psrch_inf->index_of_last_entry =
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;
} else {
cifs_buf_release(pSMB);
Expand Down
Loading

0 comments on commit 09d1db5

Please sign in to comment.