Commit 340625e6 authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Steve French

cifs: replace various strncpy with strscpy and similar

Using strscpy is cleaner, and avoids some problems with
handling maximum length strings.  Linus noticed the
original problem and Aurelien pointed out some additional
problems. Fortunately most of this is SMB1 code (and
in particular the ASCII string handling older, which
is less common).
Reported-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: default avatarAurelien Aptel <aaptel@suse.com>
Signed-off-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 478228e5
...@@ -579,6 +579,7 @@ extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page, ...@@ -579,6 +579,7 @@ extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
unsigned int *len, unsigned int *offset); unsigned int *len, unsigned int *offset);
void extract_unc_hostname(const char *unc, const char **h, size_t *len); void extract_unc_hostname(const char *unc, const char **h, size_t *len);
int copy_path_name(char *dst, const char *src);
#ifdef CONFIG_CIFS_DFS_UPCALL #ifdef CONFIG_CIFS_DFS_UPCALL
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
......
...@@ -942,10 +942,8 @@ CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -942,10 +942,8 @@ CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *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 add path length overrun check */ } else {
name_len = strnlen(fileName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, fileName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
...@@ -1015,10 +1013,8 @@ CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name, ...@@ -1015,10 +1013,8 @@ CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
remap); remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve check for buffer overruns BB */ } else {
name_len = strnlen(name, PATH_MAX); name_len = copy_path_name(pSMB->fileName, name);
name_len++; /* trailing null */
strncpy(pSMB->fileName, name, name_len);
} }
pSMB->SearchAttributes = pSMB->SearchAttributes =
cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
...@@ -1062,10 +1058,8 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, ...@@ -1062,10 +1058,8 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
remap); remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve check for buffer overruns BB */ } else {
name_len = strnlen(name, PATH_MAX); name_len = copy_path_name(pSMB->DirName, name);
name_len++; /* trailing null */
strncpy(pSMB->DirName, name, name_len);
} }
pSMB->BufferFormat = 0x04; pSMB->BufferFormat = 0x04;
...@@ -1107,10 +1101,8 @@ CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, ...@@ -1107,10 +1101,8 @@ CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
remap); remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve check for buffer overruns BB */ } else {
name_len = strnlen(name, PATH_MAX); name_len = copy_path_name(pSMB->DirName, name);
name_len++; /* trailing null */
strncpy(pSMB->DirName, name, name_len);
} }
pSMB->BufferFormat = 0x04; pSMB->BufferFormat = 0x04;
...@@ -1157,10 +1149,8 @@ CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -1157,10 +1149,8 @@ CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *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 {
name_len = strnlen(name, PATH_MAX); name_len = copy_path_name(pSMB->FileName, name);
name_len++; /* trailing null */
strncpy(pSMB->FileName, name, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
...@@ -1324,11 +1314,9 @@ SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -1324,11 +1314,9 @@ SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
fileName, PATH_MAX, nls_codepage, remap); fileName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve check for buffer overruns BB */ } else {
count = 0; /* no pad */ count = 0; /* no pad */
name_len = strnlen(fileName, PATH_MAX); name_len = copy_path_name(pSMB->fileName, fileName);
name_len++; /* trailing null */
strncpy(pSMB->fileName, fileName, name_len);
} }
if (*pOplock & REQ_OPLOCK) if (*pOplock & REQ_OPLOCK)
pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
...@@ -1442,11 +1430,8 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, ...@@ -1442,11 +1430,8 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
/* BB improve check for buffer overruns BB */ /* BB improve check for buffer overruns BB */
/* no pad */ /* no pad */
count = 0; count = 0;
name_len = strnlen(path, PATH_MAX); name_len = copy_path_name(req->fileName, path);
/* trailing null */
name_len++;
req->NameLength = cpu_to_le16(name_len); req->NameLength = cpu_to_le16(name_len);
strncpy(req->fileName, path, name_len);
} }
if (*oplock & REQ_OPLOCK) if (*oplock & REQ_OPLOCK)
...@@ -2812,15 +2797,10 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2812,15 +2797,10 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
remap); remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */ name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len = strnlen(from_name, PATH_MAX); name_len = copy_path_name(pSMB->OldFileName, from_name);
name_len++; /* trailing null */ name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
strncpy(pSMB->OldFileName, from_name, name_len);
name_len2 = strnlen(to_name, PATH_MAX);
name_len2++; /* trailing null */
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
name_len2++; /* trailing null */
name_len2++; /* signature byte */ name_len2++; /* signature byte */
} }
...@@ -2962,15 +2942,10 @@ CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2962,15 +2942,10 @@ CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
toName, PATH_MAX, nls_codepage, remap); toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */ name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len = strnlen(fromName, PATH_MAX); name_len = copy_path_name(pSMB->OldFileName, fromName);
name_len++; /* trailing null */
strncpy(pSMB->OldFileName, fromName, name_len);
name_len2 = strnlen(toName, PATH_MAX);
name_len2++; /* trailing null */
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
name_len2++; /* trailing null */
name_len2++; /* signature byte */ name_len2++; /* signature byte */
} }
...@@ -3021,10 +2996,8 @@ CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3021,10 +2996,8 @@ CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len = strnlen(fromName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, fromName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fromName, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
pSMB->MaxSetupCount = 0; pSMB->MaxSetupCount = 0;
...@@ -3044,10 +3017,8 @@ CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3044,10 +3017,8 @@ CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len_target++; /* trailing null */ name_len_target++; /* trailing null */
name_len_target *= 2; name_len_target *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len_target = strnlen(toName, PATH_MAX); name_len_target = copy_path_name(data_offset, toName);
name_len_target++; /* trailing null */
strncpy(data_offset, toName, name_len_target);
} }
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le16(2);
...@@ -3109,10 +3080,8 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3109,10 +3080,8 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len = strnlen(toName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, toName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, toName, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
pSMB->MaxSetupCount = 0; pSMB->MaxSetupCount = 0;
...@@ -3131,10 +3100,8 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3131,10 +3100,8 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len_target++; /* trailing null */ name_len_target++; /* trailing null */
name_len_target *= 2; name_len_target *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len_target = strnlen(fromName, PATH_MAX); name_len_target = copy_path_name(data_offset, fromName);
name_len_target++; /* trailing null */
strncpy(data_offset, fromName, name_len_target);
} }
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le16(2);
...@@ -3213,15 +3180,10 @@ CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3213,15 +3180,10 @@ CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
remap); remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */ name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len = strnlen(from_name, PATH_MAX); name_len = copy_path_name(pSMB->OldFileName, from_name);
name_len++; /* trailing null */
strncpy(pSMB->OldFileName, from_name, name_len);
name_len2 = strnlen(to_name, PATH_MAX);
name_len2++; /* trailing null */
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2); name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
name_len2++; /* trailing null */
name_len2++; /* signature byte */ name_len2++; /* signature byte */
} }
...@@ -3271,10 +3233,8 @@ CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3271,10 +3233,8 @@ CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
remap); 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 {
name_len = strnlen(searchName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, searchName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
} }
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
...@@ -3691,10 +3651,8 @@ CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3691,10 +3651,8 @@ CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
name_len *= 2; name_len *= 2;
pSMB->FileName[name_len] = 0; pSMB->FileName[name_len] = 0;
pSMB->FileName[name_len+1] = 0; pSMB->FileName[name_len+1] = 0;
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len = strnlen(searchName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, searchName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
} }
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
...@@ -3776,10 +3734,8 @@ CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3776,10 +3734,8 @@ CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *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 {
name_len = strnlen(fileName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, fileName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxParameterCount = cpu_to_le16(2);
...@@ -4184,9 +4140,7 @@ SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4184,9 +4140,7 @@ SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { } else {
name_len = strnlen(search_name, PATH_MAX); name_len = copy_path_name(pSMB->FileName, search_name);
name_len++; /* trailing null */
strncpy(pSMB->FileName, search_name, name_len);
} }
pSMB->BufferFormat = 0x04; pSMB->BufferFormat = 0x04;
name_len++; /* account for buffer type byte */ name_len++; /* account for buffer type byte */
...@@ -4321,10 +4275,8 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4321,10 +4275,8 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *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 {
name_len = strnlen(search_name, PATH_MAX); name_len = copy_path_name(pSMB->FileName, search_name);
name_len++; /* trailing null */
strncpy(pSMB->FileName, search_name, name_len);
} }
params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
...@@ -4490,10 +4442,8 @@ CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4490,10 +4442,8 @@ CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *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 {
name_len = strnlen(searchName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, searchName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
} }
params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
...@@ -4593,17 +4543,16 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4593,17 +4543,16 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
pSMB->FileName[name_len+1] = 0; pSMB->FileName[name_len+1] = 0;
name_len += 2; name_len += 2;
} }
} else { /* BB add check for overrun of SMB buf BB */ } else {
name_len = strnlen(searchName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, searchName);
/* BB fix here and in unicode clause above ie
if (name_len > buffersize-header)
free buffer exit; BB */
strncpy(pSMB->FileName, searchName, name_len);
if (msearch) { if (msearch) {
pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb); if (WARN_ON_ONCE(name_len > PATH_MAX-2))
pSMB->FileName[name_len+1] = '*'; name_len = PATH_MAX-2;
pSMB->FileName[name_len+2] = 0; /* overwrite nul byte */
name_len += 3; pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
pSMB->FileName[name_len] = '*';
pSMB->FileName[name_len+1] = 0;
name_len += 2;
} }
} }
...@@ -4898,10 +4847,8 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4898,10 +4847,8 @@ CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
remap); 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 {
name_len = strnlen(search_name, PATH_MAX); name_len = copy_path_name(pSMB->FileName, search_name);
name_len++; /* trailing null */
strncpy(pSMB->FileName, search_name, name_len);
} }
params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
...@@ -5008,9 +4955,7 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses, ...@@ -5008,9 +4955,7 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
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 the check for buffer overruns BB */
name_len = strnlen(search_name, PATH_MAX); name_len = copy_path_name(pSMB->RequestFileName, search_name);
name_len++; /* trailing null */
strncpy(pSMB->RequestFileName, search_name, name_len);
} }
if (ses->server->sign) if (ses->server->sign)
...@@ -5663,10 +5608,8 @@ CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -5663,10 +5608,8 @@ CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
PATH_MAX, cifs_sb->local_nls, remap); PATH_MAX, cifs_sb->local_nls, 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 {
name_len = strnlen(file_name, PATH_MAX); name_len = copy_path_name(pSMB->FileName, file_name);
name_len++; /* trailing null */
strncpy(pSMB->FileName, file_name, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
data_count = sizeof(struct file_end_of_file_info); data_count = sizeof(struct file_end_of_file_info);
...@@ -5959,10 +5902,8 @@ CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -5959,10 +5902,8 @@ CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *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 {
name_len = strnlen(fileName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, fileName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
...@@ -6040,10 +5981,8 @@ CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName, ...@@ -6040,10 +5981,8 @@ CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
PATH_MAX, nls_codepage); PATH_MAX, nls_codepage);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else {
name_len = strnlen(fileName, PATH_MAX); name_len = copy_path_name(pSMB->fileName, fileName);
name_len++; /* trailing null */
strncpy(pSMB->fileName, fileName, name_len);
} }
pSMB->attr = cpu_to_le16(dos_attrs); pSMB->attr = cpu_to_le16(dos_attrs);
pSMB->BufferFormat = 0x04; pSMB->BufferFormat = 0x04;
...@@ -6203,10 +6142,8 @@ CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -6203,10 +6142,8 @@ CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *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 {
name_len = strnlen(file_name, PATH_MAX); name_len = copy_path_name(pSMB->FileName, file_name);
name_len++; /* trailing null */
strncpy(pSMB->FileName, file_name, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
...@@ -6298,10 +6235,8 @@ CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -6298,10 +6235,8 @@ CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
list_len++; /* trailing null */ list_len++; /* trailing null */
list_len *= 2; list_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else {
list_len = strnlen(searchName, PATH_MAX); list_len = copy_path_name(pSMB->FileName, searchName);
list_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, list_len);
} }
params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */; params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
...@@ -6480,10 +6415,8 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -6480,10 +6415,8 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *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 {
name_len = strnlen(fileName, PATH_MAX); name_len = copy_path_name(pSMB->FileName, fileName);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
} }
params = 6 + name_len; params = 6 + name_len;
......
...@@ -4231,16 +4231,19 @@ build_unc_path_to_root(const struct smb_vol *vol, ...@@ -4231,16 +4231,19 @@ build_unc_path_to_root(const struct smb_vol *vol,
strlen(vol->prepath) + 1 : 0; strlen(vol->prepath) + 1 : 0;
unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1); unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
if (unc_len > MAX_TREE_SIZE)
return ERR_PTR(-EINVAL);
full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL); full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
if (full_path == NULL) if (full_path == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
strncpy(full_path, vol->UNC, unc_len); memcpy(full_path, vol->UNC, unc_len);
pos = full_path + unc_len; pos = full_path + unc_len;
if (pplen) { if (pplen) {
*pos = CIFS_DIR_SEP(cifs_sb); *pos = CIFS_DIR_SEP(cifs_sb);
strncpy(pos + 1, vol->prepath, pplen); memcpy(pos + 1, vol->prepath, pplen);
pos += pplen; pos += pplen;
} }
......
...@@ -69,11 +69,10 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb, ...@@ -69,11 +69,10 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
return full_path; return full_path;
if (dfsplen) if (dfsplen)
strncpy(full_path, tcon->treeName, dfsplen); memcpy(full_path, tcon->treeName, dfsplen);
full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb); full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb);
strncpy(full_path + dfsplen + 1, vol->prepath, pplen); memcpy(full_path + dfsplen + 1, vol->prepath, pplen);
convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
full_path[dfsplen + pplen] = 0; /* add trailing null */
return full_path; return full_path;
} }
......
...@@ -1011,3 +1011,25 @@ void extract_unc_hostname(const char *unc, const char **h, size_t *len) ...@@ -1011,3 +1011,25 @@ void extract_unc_hostname(const char *unc, const char **h, size_t *len)
*h = unc; *h = unc;
*len = end - unc; *len = end - unc;
} }
/**
* copy_path_name - copy src path to dst, possibly truncating
*
* returns number of bytes written (including trailing nul)
*/
int copy_path_name(char *dst, const char *src)
{
int name_len;
/*
* PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it
* will truncate and strlen(dst) will be PATH_MAX-1
*/
name_len = strscpy(dst, src, PATH_MAX);
if (WARN_ON_ONCE(name_len < 0))
name_len = PATH_MAX-1;
/* we count the trailing nul */