mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 03:50:53 +07:00
[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>
This commit is contained in:
parent
966ca92347
commit
09d1db5c61
@ -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.
|
||||
@ -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)
|
||||
@ -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
|
||||
|
@ -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 */
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
||||
@ -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:
|
||||
@ -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;
|
||||
|
||||
@ -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:
|
||||
@ -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 <
|
||||
@ -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 =
|
||||
@ -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.
|
||||
@ -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;
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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 */
|
||||
@ -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;
|
||||
|
||||
@ -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? */
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
|
@ -157,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
qhead);
|
||||
if(mid_entry) {
|
||||
if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
|
||||
/* Mark other intransit requests as needing retry so
|
||||
we do not immediately mark the session bad again
|
||||
(ie after we reconnect below) as they timeout too */
|
||||
/* Mark other intransit requests as needing
|
||||
retry so we do not immediately mark the
|
||||
session bad again (ie after we reconnect
|
||||
below) as they timeout too */
|
||||
mid_entry->midState = MID_RETRY_NEEDED;
|
||||
}
|
||||
}
|
||||
@ -278,9 +279,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
} else if (length <= 0) {
|
||||
if(server->tcpStatus == CifsNew) {
|
||||
cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
|
||||
/* some servers kill tcp session rather than returning
|
||||
smb negprot error in which case reconnecting here is
|
||||
not going to help - return error to mount */
|
||||
/* some servers kill the TCP session rather than
|
||||
returning an SMB negprot error, in which
|
||||
case reconnecting here is not going to help,
|
||||
and so simply return error to mount */
|
||||
break;
|
||||
}
|
||||
if(length == -EINTR) {
|
||||
@ -296,15 +298,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
pdu_length = ntohl(smb_buffer->smb_buf_length);
|
||||
/* Only read pdu_length after below checks for too short (due
|
||||
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;
|
||||
if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
|
||||
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"));
|
||||
} else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
|
||||
/* we get this from Windows 98 instead of error on SMB negprot response */
|
||||
} else if (temp[0] ==
|
||||
(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]));
|
||||
if(server->tcpStatus == CifsNew) {
|
||||
/* if nack on negprot (rather than
|
||||
@ -320,7 +326,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
connected to port 139 (the NACK is
|
||||
since we do not begin with RFC1001
|
||||
session initialize frame) */
|
||||
server->addr.sockAddr.sin_port = htons(CIFS_PORT);
|
||||
server->addr.sockAddr.sin_port =
|
||||
htons(CIFS_PORT);
|
||||
cifs_reconnect(server);
|
||||
csocket = server->ssocket;
|
||||
wake_up(&server->response_q);
|
||||
@ -333,8 +340,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
csocket = server->ssocket;
|
||||
continue;
|
||||
} else {
|
||||
if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
|
||||
|| (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
|
||||
if((pdu_length > CIFSMaxBufSize +
|
||||
MAX_CIFS_HDR_SIZE - 4) ||
|
||||
(pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
|
||||
cERROR(1,
|
||||
("Invalid size SMB length %d and pdu_length %d",
|
||||
length, pdu_length+4));
|
||||
@ -377,6 +385,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* BB FIXME - add checkTrans2SMBSecondary() */
|
||||
|
||||
task_to_wake = NULL;
|
||||
spin_lock(&GlobalMid_Lock);
|
||||
list_for_each(tmp, &server->pending_mid_q) {
|
||||
@ -408,7 +418,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
bigbuf = NULL;
|
||||
else
|
||||
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);
|
||||
} else if (is_valid_oplock_break(smb_buffer) == FALSE) {
|
||||
cERROR(1, ("No task to wake, unknown frame rcvd!"));
|
||||
@ -432,7 +442,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
/* Although there should not be any requests blocked on
|
||||
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
|
||||
and get out of SendReceive. */
|
||||
wake_up_all(&server->request_q);
|
||||
@ -451,7 +461,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
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) {
|
||||
ses =
|
||||
list_entry(tmp, struct cifsSesInfo,
|
||||
@ -468,7 +479,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
|
||||
if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
|
||||
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;
|
||||
if(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)
|
||||
/* does not have to be a perfect mapping since the field is
|
||||
informational, only used for servers that do not support
|
||||
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;
|
||||
|
||||
@ -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
|
||||
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 */
|
||||
value[temp_len] = separator[0];
|
||||
temp_len+=2; /* move after the second comma */
|
||||
while(value[temp_len] != 0) {
|
||||
if (value[temp_len] == separator[0]) {
|
||||
if (value[temp_len+1] == separator[0]) {
|
||||
temp_len++; /* skip second comma */
|
||||
if (value[temp_len+1] ==
|
||||
separator[0]) {
|
||||
/* skip second comma */
|
||||
temp_len++;
|
||||
} else {
|
||||
/* single comma indicating start
|
||||
of next parm */
|
||||
@ -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++) {
|
||||
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 */
|
||||
i++;
|
||||
}
|
||||
}
|
||||
vol->password[j] = 0;
|
||||
} else {
|
||||
vol->password = kcalloc(1, temp_len + 1, GFP_KERNEL);
|
||||
vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
|
||||
if(vol->password == NULL) {
|
||||
printk("CIFS: no memory for pass\n");
|
||||
return 1;
|
||||
|
@ -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));
|
||||
/* validate that new_entry is not past end of SMB */
|
||||
if(new_entry >= end_of_smb) {
|
||||
cFYI(1,("search entry %p began after end of SMB %p old entry %p",
|
||||
new_entry,end_of_smb,old_entry));
|
||||
cERROR(1,
|
||||
("search entry %p began after end of SMB %p old entry %p",
|
||||
new_entry, end_of_smb, old_entry));
|
||||
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;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user