aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorRonnie Sahlberg <lsahlber@redhat.com>2019-08-26 19:30:14 -0400
committerSteve French <stfrench@microsoft.com>2019-08-27 18:25:12 -0400
commit340625e618e1b37a72a02f07aa7144ae0ab0b19e (patch)
tree9bac6626dd3e1477a93301a84c7c797b7db5526c /fs/cifs
parent478228e57f81f6cb60798d54fc02a74ea7dd267e (diff)
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: Linus Torvalds <torvalds@linux-foundation.org> Reviewed-by: Aurelien Aptel <aaptel@suse.com> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsproto.h1
-rw-r--r--fs/cifs/cifssmb.c197
-rw-r--r--fs/cifs/connect.c7
-rw-r--r--fs/cifs/dir.c5
-rw-r--r--fs/cifs/misc.c22
-rw-r--r--fs/cifs/sess.c26
6 files changed, 112 insertions, 146 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index e23234207fc2..592a6cea2b79 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -579,6 +579,7 @@ extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
579 unsigned int *len, unsigned int *offset); 579 unsigned int *len, unsigned int *offset);
580 580
581void extract_unc_hostname(const char *unc, const char **h, size_t *len); 581void extract_unc_hostname(const char *unc, const char **h, size_t *len);
582int copy_path_name(char *dst, const char *src);
582 583
583#ifdef CONFIG_CIFS_DFS_UPCALL 584#ifdef CONFIG_CIFS_DFS_UPCALL
584static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, 585static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index e2f95965065d..3907653e63c7 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -942,10 +942,8 @@ PsxDelete:
942 PATH_MAX, nls_codepage, remap); 942 PATH_MAX, nls_codepage, remap);
943 name_len++; /* trailing null */ 943 name_len++; /* trailing null */
944 name_len *= 2; 944 name_len *= 2;
945 } else { /* BB add path length overrun check */ 945 } else {
946 name_len = strnlen(fileName, PATH_MAX); 946 name_len = copy_path_name(pSMB->FileName, fileName);
947 name_len++; /* trailing null */
948 strncpy(pSMB->FileName, fileName, name_len);
949 } 947 }
950 948
951 params = 6 + name_len; 949 params = 6 + name_len;
@@ -1015,10 +1013,8 @@ DelFileRetry:
1015 remap); 1013 remap);
1016 name_len++; /* trailing null */ 1014 name_len++; /* trailing null */
1017 name_len *= 2; 1015 name_len *= 2;
1018 } else { /* BB improve check for buffer overruns BB */ 1016 } else {
1019 name_len = strnlen(name, PATH_MAX); 1017 name_len = copy_path_name(pSMB->fileName, name);
1020 name_len++; /* trailing null */
1021 strncpy(pSMB->fileName, name, name_len);
1022 } 1018 }
1023 pSMB->SearchAttributes = 1019 pSMB->SearchAttributes =
1024 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); 1020 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
@@ -1062,10 +1058,8 @@ RmDirRetry:
1062 remap); 1058 remap);
1063 name_len++; /* trailing null */ 1059 name_len++; /* trailing null */
1064 name_len *= 2; 1060 name_len *= 2;
1065 } else { /* BB improve check for buffer overruns BB */ 1061 } else {
1066 name_len = strnlen(name, PATH_MAX); 1062 name_len = copy_path_name(pSMB->DirName, name);
1067 name_len++; /* trailing null */
1068 strncpy(pSMB->DirName, name, name_len);
1069 } 1063 }
1070 1064
1071 pSMB->BufferFormat = 0x04; 1065 pSMB->BufferFormat = 0x04;
@@ -1107,10 +1101,8 @@ MkDirRetry:
1107 remap); 1101 remap);
1108 name_len++; /* trailing null */ 1102 name_len++; /* trailing null */
1109 name_len *= 2; 1103 name_len *= 2;
1110 } else { /* BB improve check for buffer overruns BB */ 1104 } else {
1111 name_len = strnlen(name, PATH_MAX); 1105 name_len = copy_path_name(pSMB->DirName, name);
1112 name_len++; /* trailing null */
1113 strncpy(pSMB->DirName, name, name_len);
1114 } 1106 }
1115 1107
1116 pSMB->BufferFormat = 0x04; 1108 pSMB->BufferFormat = 0x04;
@@ -1157,10 +1149,8 @@ PsxCreat:
1157 PATH_MAX, nls_codepage, remap); 1149 PATH_MAX, nls_codepage, remap);
1158 name_len++; /* trailing null */ 1150 name_len++; /* trailing null */
1159 name_len *= 2; 1151 name_len *= 2;
1160 } else { /* BB improve the check for buffer overruns BB */ 1152 } else {
1161 name_len = strnlen(name, PATH_MAX); 1153 name_len = copy_path_name(pSMB->FileName, name);
1162 name_len++; /* trailing null */
1163 strncpy(pSMB->FileName, name, name_len);
1164 } 1154 }
1165 1155
1166 params = 6 + name_len; 1156 params = 6 + name_len;
@@ -1324,11 +1314,9 @@ OldOpenRetry:
1324 fileName, PATH_MAX, nls_codepage, remap); 1314 fileName, PATH_MAX, nls_codepage, remap);
1325 name_len++; /* trailing null */ 1315 name_len++; /* trailing null */
1326 name_len *= 2; 1316 name_len *= 2;
1327 } else { /* BB improve check for buffer overruns BB */ 1317 } else {
1328 count = 0; /* no pad */ 1318 count = 0; /* no pad */
1329 name_len = strnlen(fileName, PATH_MAX); 1319 name_len = copy_path_name(pSMB->fileName, fileName);
1330 name_len++; /* trailing null */
1331 strncpy(pSMB->fileName, fileName, name_len);
1332 } 1320 }
1333 if (*pOplock & REQ_OPLOCK) 1321 if (*pOplock & REQ_OPLOCK)
1334 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); 1322 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
@@ -1442,11 +1430,8 @@ openRetry:
1442 /* BB improve check for buffer overruns BB */ 1430 /* BB improve check for buffer overruns BB */
1443 /* no pad */ 1431 /* no pad */
1444 count = 0; 1432 count = 0;
1445 name_len = strnlen(path, PATH_MAX); 1433 name_len = copy_path_name(req->fileName, path);
1446 /* trailing null */
1447 name_len++;
1448 req->NameLength = cpu_to_le16(name_len); 1434 req->NameLength = cpu_to_le16(name_len);
1449 strncpy(req->fileName, path, name_len);
1450 } 1435 }
1451 1436
1452 if (*oplock & REQ_OPLOCK) 1437 if (*oplock & REQ_OPLOCK)
@@ -2812,15 +2797,10 @@ renameRetry:
2812 remap); 2797 remap);
2813 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 2798 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2814 name_len2 *= 2; /* convert to bytes */ 2799 name_len2 *= 2; /* convert to bytes */
2815 } else { /* BB improve the check for buffer overruns BB */ 2800 } else {
2816 name_len = strnlen(from_name, PATH_MAX); 2801 name_len = copy_path_name(pSMB->OldFileName, from_name);
2817 name_len++; /* trailing null */ 2802 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
2818 strncpy(pSMB->OldFileName, from_name, name_len);
2819 name_len2 = strnlen(to_name, PATH_MAX);
2820 name_len2++; /* trailing null */
2821 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ 2803 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2822 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2823 name_len2++; /* trailing null */
2824 name_len2++; /* signature byte */ 2804 name_len2++; /* signature byte */
2825 } 2805 }
2826 2806
@@ -2962,15 +2942,10 @@ copyRetry:
2962 toName, PATH_MAX, nls_codepage, remap); 2942 toName, PATH_MAX, nls_codepage, remap);
2963 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 2943 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2964 name_len2 *= 2; /* convert to bytes */ 2944 name_len2 *= 2; /* convert to bytes */
2965 } else { /* BB improve the check for buffer overruns BB */ 2945 } else {
2966 name_len = strnlen(fromName, PATH_MAX); 2946 name_len = copy_path_name(pSMB->OldFileName, fromName);
2967 name_len++; /* trailing null */
2968 strncpy(pSMB->OldFileName, fromName, name_len);
2969 name_len2 = strnlen(toName, PATH_MAX);
2970 name_len2++; /* trailing null */
2971 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ 2947 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2972 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); 2948 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName);
2973 name_len2++; /* trailing null */
2974 name_len2++; /* signature byte */ 2949 name_len2++; /* signature byte */
2975 } 2950 }
2976 2951
@@ -3021,10 +2996,8 @@ createSymLinkRetry:
3021 name_len++; /* trailing null */ 2996 name_len++; /* trailing null */
3022 name_len *= 2; 2997 name_len *= 2;
3023 2998
3024 } else { /* BB improve the check for buffer overruns BB */ 2999 } else {
3025 name_len = strnlen(fromName, PATH_MAX); 3000 name_len = copy_path_name(pSMB->FileName, fromName);
3026 name_len++; /* trailing null */
3027 strncpy(pSMB->FileName, fromName, name_len);
3028 } 3001 }
3029 params = 6 + name_len; 3002 params = 6 + name_len;
3030 pSMB->MaxSetupCount = 0; 3003 pSMB->MaxSetupCount = 0;
@@ -3044,10 +3017,8 @@ createSymLinkRetry:
3044 PATH_MAX, nls_codepage, remap); 3017 PATH_MAX, nls_codepage, remap);
3045 name_len_target++; /* trailing null */ 3018 name_len_target++; /* trailing null */
3046 name_len_target *= 2; 3019 name_len_target *= 2;
3047 } else { /* BB improve the check for buffer overruns BB */ 3020 } else {
3048 name_len_target = strnlen(toName, PATH_MAX); 3021 name_len_target = copy_path_name(data_offset, toName);
3049 name_len_target++; /* trailing null */
3050 strncpy(data_offset, toName, name_len_target);
3051 } 3022 }
3052 3023
3053 pSMB->MaxParameterCount = cpu_to_le16(2); 3024 pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -3109,10 +3080,8 @@ createHardLinkRetry:
3109 name_len++; /* trailing null */ 3080 name_len++; /* trailing null */
3110 name_len *= 2; 3081 name_len *= 2;
3111 3082
3112 } else { /* BB improve the check for buffer overruns BB */ 3083 } else {
3113 name_len = strnlen(toName, PATH_MAX); 3084 name_len = copy_path_name(pSMB->FileName, toName);
3114 name_len++; /* trailing null */
3115 strncpy(pSMB->FileName, toName, name_len);
3116 } 3085 }
3117 params = 6 + name_len; 3086 params = 6 + name_len;
3118 pSMB->MaxSetupCount = 0; 3087 pSMB->MaxSetupCount = 0;
@@ -3131,10 +3100,8 @@ createHardLinkRetry:
3131 PATH_MAX, nls_codepage, remap); 3100 PATH_MAX, nls_codepage, remap);
3132 name_len_target++; /* trailing null */ 3101 name_len_target++; /* trailing null */
3133 name_len_target *= 2; 3102 name_len_target *= 2;
3134 } else { /* BB improve the check for buffer overruns BB */ 3103 } else {
3135 name_len_target = strnlen(fromName, PATH_MAX); 3104 name_len_target = copy_path_name(data_offset, fromName);
3136 name_len_target++; /* trailing null */
3137 strncpy(data_offset, fromName, name_len_target);
3138 } 3105 }
3139 3106
3140 pSMB->MaxParameterCount = cpu_to_le16(2); 3107 pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -3213,15 +3180,10 @@ winCreateHardLinkRetry:
3213 remap); 3180 remap);
3214 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 3181 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3215 name_len2 *= 2; /* convert to bytes */ 3182 name_len2 *= 2; /* convert to bytes */
3216 } else { /* BB improve the check for buffer overruns BB */ 3183 } else {
3217 name_len = strnlen(from_name, PATH_MAX); 3184 name_len = copy_path_name(pSMB->OldFileName, from_name);
3218 name_len++; /* trailing null */
3219 strncpy(pSMB->OldFileName, from_name, name_len);
3220 name_len2 = strnlen(to_name, PATH_MAX);
3221 name_len2++; /* trailing null */
3222 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ 3185 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3223 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2); 3186 name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name);
3224 name_len2++; /* trailing null */
3225 name_len2++; /* signature byte */ 3187 name_len2++; /* signature byte */
3226 } 3188 }
3227 3189
@@ -3271,10 +3233,8 @@ querySymLinkRetry:
3271 remap); 3233 remap);
3272 name_len++; /* trailing null */ 3234 name_len++; /* trailing null */
3273 name_len *= 2; 3235 name_len *= 2;
3274 } else { /* BB improve the check for buffer overruns BB */ 3236 } else {
3275 name_len = strnlen(searchName, PATH_MAX); 3237 name_len = copy_path_name(pSMB->FileName, searchName);
3276 name_len++; /* trailing null */
3277 strncpy(pSMB->FileName, searchName, name_len);
3278 } 3238 }
3279 3239
3280 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; 3240 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
@@ -3691,10 +3651,8 @@ queryAclRetry:
3691 name_len *= 2; 3651 name_len *= 2;
3692 pSMB->FileName[name_len] = 0; 3652 pSMB->FileName[name_len] = 0;
3693 pSMB->FileName[name_len+1] = 0; 3653 pSMB->FileName[name_len+1] = 0;
3694 } else { /* BB improve the check for buffer overruns BB */ 3654 } else {
3695 name_len = strnlen(searchName, PATH_MAX); 3655 name_len = copy_path_name(pSMB->FileName, searchName);
3696 name_len++; /* trailing null */
3697 strncpy(pSMB->FileName, searchName, name_len);
3698 } 3656 }
3699 3657
3700 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; 3658 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
@@ -3776,10 +3734,8 @@ setAclRetry:
3776 PATH_MAX, nls_codepage, remap); 3734 PATH_MAX, nls_codepage, remap);
3777 name_len++; /* trailing null */ 3735 name_len++; /* trailing null */
3778 name_len *= 2; 3736 name_len *= 2;
3779 } else { /* BB improve the check for buffer overruns BB */ 3737 } else {
3780 name_len = strnlen(fileName, PATH_MAX); 3738 name_len = copy_path_name(pSMB->FileName, fileName);
3781 name_len++; /* trailing null */
3782 strncpy(pSMB->FileName, fileName, name_len);
3783 } 3739 }
3784 params = 6 + name_len; 3740 params = 6 + name_len;
3785 pSMB->MaxParameterCount = cpu_to_le16(2); 3741 pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -4184,9 +4140,7 @@ QInfRetry:
4184 name_len++; /* trailing null */ 4140 name_len++; /* trailing null */
4185 name_len *= 2; 4141 name_len *= 2;
4186 } else { 4142 } else {
4187 name_len = strnlen(search_name, PATH_MAX); 4143 name_len = copy_path_name(pSMB->FileName, search_name);
4188 name_len++; /* trailing null */
4189 strncpy(pSMB->FileName, search_name, name_len);
4190 } 4144 }
4191 pSMB->BufferFormat = 0x04; 4145 pSMB->BufferFormat = 0x04;
4192 name_len++; /* account for buffer type byte */ 4146 name_len++; /* account for buffer type byte */
@@ -4321,10 +4275,8 @@ QPathInfoRetry:
4321 PATH_MAX, nls_codepage, remap); 4275 PATH_MAX, nls_codepage, remap);
4322 name_len++; /* trailing null */ 4276 name_len++; /* trailing null */
4323 name_len *= 2; 4277 name_len *= 2;
4324 } else { /* BB improve the check for buffer overruns BB */ 4278 } else {
4325 name_len = strnlen(search_name, PATH_MAX); 4279 name_len = copy_path_name(pSMB->FileName, search_name);
4326 name_len++; /* trailing null */
4327 strncpy(pSMB->FileName, search_name, name_len);
4328 } 4280 }
4329 4281
4330 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; 4282 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
@@ -4490,10 +4442,8 @@ UnixQPathInfoRetry:
4490 PATH_MAX, nls_codepage, remap); 4442 PATH_MAX, nls_codepage, remap);
4491 name_len++; /* trailing null */ 4443 name_len++; /* trailing null */
4492 name_len *= 2; 4444 name_len *= 2;
4493 } else { /* BB improve the check for buffer overruns BB */ 4445 } else {
4494 name_len = strnlen(searchName, PATH_MAX); 4446 name_len = copy_path_name(pSMB->FileName, searchName);
4495 name_len++; /* trailing null */
4496 strncpy(pSMB->FileName, searchName, name_len);
4497 } 4447 }
4498 4448
4499 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; 4449 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
@@ -4593,17 +4543,16 @@ findFirstRetry:
4593 pSMB->FileName[name_len+1] = 0; 4543 pSMB->FileName[name_len+1] = 0;
4594 name_len += 2; 4544 name_len += 2;
4595 } 4545 }
4596 } else { /* BB add check for overrun of SMB buf BB */ 4546 } else {
4597 name_len = strnlen(searchName, PATH_MAX); 4547 name_len = copy_path_name(pSMB->FileName, searchName);
4598/* BB fix here and in unicode clause above ie
4599 if (name_len > buffersize-header)
4600 free buffer exit; BB */
4601 strncpy(pSMB->FileName, searchName, name_len);
4602 if (msearch) { 4548 if (msearch) {
4603 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb); 4549 if (WARN_ON_ONCE(name_len > PATH_MAX-2))
4604 pSMB->FileName[name_len+1] = '*'; 4550 name_len = PATH_MAX-2;
4605 pSMB->FileName[name_len+2] = 0; 4551 /* overwrite nul byte */
4606 name_len += 3; 4552 pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb);
4553 pSMB->FileName[name_len] = '*';
4554 pSMB->FileName[name_len+1] = 0;
4555 name_len += 2;
4607 } 4556 }
4608 } 4557 }
4609 4558
@@ -4898,10 +4847,8 @@ GetInodeNumberRetry:
4898 remap); 4847 remap);
4899 name_len++; /* trailing null */ 4848 name_len++; /* trailing null */
4900 name_len *= 2; 4849 name_len *= 2;
4901 } else { /* BB improve the check for buffer overruns BB */ 4850 } else {
4902 name_len = strnlen(search_name, PATH_MAX); 4851 name_len = copy_path_name(pSMB->FileName, search_name);
4903 name_len++; /* trailing null */
4904 strncpy(pSMB->FileName, search_name, name_len);
4905 } 4852 }
4906 4853
4907 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; 4854 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
@@ -5008,9 +4955,7 @@ getDFSRetry:
5008 name_len++; /* trailing null */ 4955 name_len++; /* trailing null */
5009 name_len *= 2; 4956 name_len *= 2;
5010 } else { /* BB improve the check for buffer overruns BB */ 4957 } else { /* BB improve the check for buffer overruns BB */
5011 name_len = strnlen(search_name, PATH_MAX); 4958 name_len = copy_path_name(pSMB->RequestFileName, search_name);
5012 name_len++; /* trailing null */
5013 strncpy(pSMB->RequestFileName, search_name, name_len);
5014 } 4959 }
5015 4960
5016 if (ses->server->sign) 4961 if (ses->server->sign)
@@ -5663,10 +5608,8 @@ SetEOFRetry:
5663 PATH_MAX, cifs_sb->local_nls, remap); 5608 PATH_MAX, cifs_sb->local_nls, remap);
5664 name_len++; /* trailing null */ 5609 name_len++; /* trailing null */
5665 name_len *= 2; 5610 name_len *= 2;
5666 } else { /* BB improve the check for buffer overruns BB */ 5611 } else {
5667 name_len = strnlen(file_name, PATH_MAX); 5612 name_len = copy_path_name(pSMB->FileName, file_name);
5668 name_len++; /* trailing null */
5669 strncpy(pSMB->FileName, file_name, name_len);
5670 } 5613 }
5671 params = 6 + name_len; 5614 params = 6 + name_len;
5672 data_count = sizeof(struct file_end_of_file_info); 5615 data_count = sizeof(struct file_end_of_file_info);
@@ -5959,10 +5902,8 @@ SetTimesRetry:
5959 PATH_MAX, nls_codepage, remap); 5902 PATH_MAX, nls_codepage, remap);
5960 name_len++; /* trailing null */ 5903 name_len++; /* trailing null */
5961 name_len *= 2; 5904 name_len *= 2;
5962 } else { /* BB improve the check for buffer overruns BB */ 5905 } else {
5963 name_len = strnlen(fileName, PATH_MAX); 5906 name_len = copy_path_name(pSMB->FileName, fileName);
5964 name_len++; /* trailing null */
5965 strncpy(pSMB->FileName, fileName, name_len);
5966 } 5907 }
5967 5908
5968 params = 6 + name_len; 5909 params = 6 + name_len;
@@ -6040,10 +5981,8 @@ SetAttrLgcyRetry:
6040 PATH_MAX, nls_codepage); 5981 PATH_MAX, nls_codepage);
6041 name_len++; /* trailing null */ 5982 name_len++; /* trailing null */
6042 name_len *= 2; 5983 name_len *= 2;
6043 } else { /* BB improve the check for buffer overruns BB */ 5984 } else {
6044 name_len = strnlen(fileName, PATH_MAX); 5985 name_len = copy_path_name(pSMB->fileName, fileName);
6045 name_len++; /* trailing null */
6046 strncpy(pSMB->fileName, fileName, name_len);
6047 } 5986 }
6048 pSMB->attr = cpu_to_le16(dos_attrs); 5987 pSMB->attr = cpu_to_le16(dos_attrs);
6049 pSMB->BufferFormat = 0x04; 5988 pSMB->BufferFormat = 0x04;
@@ -6203,10 +6142,8 @@ setPermsRetry:
6203 PATH_MAX, nls_codepage, remap); 6142 PATH_MAX, nls_codepage, remap);
6204 name_len++; /* trailing null */ 6143 name_len++; /* trailing null */
6205 name_len *= 2; 6144 name_len *= 2;
6206 } else { /* BB improve the check for buffer overruns BB */ 6145 } else {
6207 name_len = strnlen(file_name, PATH_MAX); 6146 name_len = copy_path_name(pSMB->FileName, file_name);
6208 name_len++; /* trailing null */
6209 strncpy(pSMB->FileName, file_name, name_len);
6210 } 6147 }
6211 6148
6212 params = 6 + name_len; 6149 params = 6 + name_len;
@@ -6298,10 +6235,8 @@ QAllEAsRetry:
6298 PATH_MAX, nls_codepage, remap); 6235 PATH_MAX, nls_codepage, remap);
6299 list_len++; /* trailing null */ 6236 list_len++; /* trailing null */
6300 list_len *= 2; 6237 list_len *= 2;
6301 } else { /* BB improve the check for buffer overruns BB */ 6238 } else {
6302 list_len = strnlen(searchName, PATH_MAX); 6239 list_len = copy_path_name(pSMB->FileName, searchName);
6303 list_len++; /* trailing null */
6304 strncpy(pSMB->FileName, searchName, list_len);
6305 } 6240 }
6306 6241
6307 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */; 6242 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
@@ -6480,10 +6415,8 @@ SetEARetry:
6480 PATH_MAX, nls_codepage, remap); 6415 PATH_MAX, nls_codepage, remap);
6481 name_len++; /* trailing null */ 6416 name_len++; /* trailing null */
6482 name_len *= 2; 6417 name_len *= 2;
6483 } else { /* BB improve the check for buffer overruns BB */ 6418 } else {
6484 name_len = strnlen(fileName, PATH_MAX); 6419 name_len = copy_path_name(pSMB->FileName, fileName);
6485 name_len++; /* trailing null */
6486 strncpy(pSMB->FileName, fileName, name_len);
6487 } 6420 }
6488 6421
6489 params = 6 + name_len; 6422 params = 6 + name_len;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index ddefddeffd06..5299effa6f7d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -4231,16 +4231,19 @@ build_unc_path_to_root(const struct smb_vol *vol,
4231 strlen(vol->prepath) + 1 : 0; 4231 strlen(vol->prepath) + 1 : 0;
4232 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1); 4232 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
4233 4233
4234 if (unc_len > MAX_TREE_SIZE)
4235 return ERR_PTR(-EINVAL);
4236
4234 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL); 4237 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
4235 if (full_path == NULL) 4238 if (full_path == NULL)
4236 return ERR_PTR(-ENOMEM); 4239 return ERR_PTR(-ENOMEM);
4237 4240
4238 strncpy(full_path, vol->UNC, unc_len); 4241 memcpy(full_path, vol->UNC, unc_len);
4239 pos = full_path + unc_len; 4242 pos = full_path + unc_len;
4240 4243
4241 if (pplen) { 4244 if (pplen) {
4242 *pos = CIFS_DIR_SEP(cifs_sb); 4245 *pos = CIFS_DIR_SEP(cifs_sb);
4243 strncpy(pos + 1, vol->prepath, pplen); 4246 memcpy(pos + 1, vol->prepath, pplen);
4244 pos += pplen; 4247 pos += pplen;
4245 } 4248 }
4246 4249
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index f26a48dd2e39..be424e81e3ad 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -69,11 +69,10 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
69 return full_path; 69 return full_path;
70 70
71 if (dfsplen) 71 if (dfsplen)
72 strncpy(full_path, tcon->treeName, dfsplen); 72 memcpy(full_path, tcon->treeName, dfsplen);
73 full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb); 73 full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb);
74 strncpy(full_path + dfsplen + 1, vol->prepath, pplen); 74 memcpy(full_path + dfsplen + 1, vol->prepath, pplen);
75 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); 75 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
76 full_path[dfsplen + pplen] = 0; /* add trailing null */
77 return full_path; 76 return full_path;
78} 77}
79 78
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index f383877a6511..5ad83bdb9bea 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1011,3 +1011,25 @@ void extract_unc_hostname(const char *unc, const char **h, size_t *len)
1011 *h = unc; 1011 *h = unc;
1012 *len = end - unc; 1012 *len = end - unc;
1013} 1013}
1014
1015/**
1016 * copy_path_name - copy src path to dst, possibly truncating
1017 *
1018 * returns number of bytes written (including trailing nul)
1019 */
1020int copy_path_name(char *dst, const char *src)
1021{
1022 int name_len;
1023
1024 /*
1025 * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it
1026 * will truncate and strlen(dst) will be PATH_MAX-1
1027 */
1028 name_len = strscpy(dst, src, PATH_MAX);
1029 if (WARN_ON_ONCE(name_len < 0))
1030 name_len = PATH_MAX-1;
1031
1032 /* we count the trailing nul */
1033 name_len++;
1034 return name_len;
1035}
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index dcd49ad60c83..4c764ff7edd2 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -159,13 +159,16 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
159 const struct nls_table *nls_cp) 159 const struct nls_table *nls_cp)
160{ 160{
161 char *bcc_ptr = *pbcc_area; 161 char *bcc_ptr = *pbcc_area;
162 int len;
162 163
163 /* copy user */ 164 /* copy user */
164 /* BB what about null user mounts - check that we do this BB */ 165 /* BB what about null user mounts - check that we do this BB */
165 /* copy user */ 166 /* copy user */
166 if (ses->user_name != NULL) { 167 if (ses->user_name != NULL) {
167 strncpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN); 168 len = strscpy(bcc_ptr, ses->user_name, CIFS_MAX_USERNAME_LEN);
168 bcc_ptr += strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN); 169 if (WARN_ON_ONCE(len < 0))
170 len = CIFS_MAX_USERNAME_LEN - 1;
171 bcc_ptr += len;
169 } 172 }
170 /* else null user mount */ 173 /* else null user mount */
171 *bcc_ptr = 0; 174 *bcc_ptr = 0;
@@ -173,8 +176,10 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
173 176
174 /* copy domain */ 177 /* copy domain */
175 if (ses->domainName != NULL) { 178 if (ses->domainName != NULL) {
176 strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN); 179 len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
177 bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); 180 if (WARN_ON_ONCE(len < 0))
181 len = CIFS_MAX_DOMAINNAME_LEN - 1;
182 bcc_ptr += len;
178 } /* else we will send a null domain name 183 } /* else we will send a null domain name
179 so the server will default to its own domain */ 184 so the server will default to its own domain */
180 *bcc_ptr = 0; 185 *bcc_ptr = 0;
@@ -242,9 +247,10 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
242 247
243 kfree(ses->serverOS); 248 kfree(ses->serverOS);
244 249
245 ses->serverOS = kzalloc(len + 1, GFP_KERNEL); 250 ses->serverOS = kmalloc(len + 1, GFP_KERNEL);
246 if (ses->serverOS) { 251 if (ses->serverOS) {
247 strncpy(ses->serverOS, bcc_ptr, len); 252 memcpy(ses->serverOS, bcc_ptr, len);
253 ses->serverOS[len] = 0;
248 if (strncmp(ses->serverOS, "OS/2", 4) == 0) 254 if (strncmp(ses->serverOS, "OS/2", 4) == 0)
249 cifs_dbg(FYI, "OS/2 server\n"); 255 cifs_dbg(FYI, "OS/2 server\n");
250 } 256 }
@@ -258,9 +264,11 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
258 264
259 kfree(ses->serverNOS); 265 kfree(ses->serverNOS);
260 266
261 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); 267 ses->serverNOS = kmalloc(len + 1, GFP_KERNEL);
262 if (ses->serverNOS) 268 if (ses->serverNOS) {
263 strncpy(ses->serverNOS, bcc_ptr, len); 269 memcpy(ses->serverNOS, bcc_ptr, len);
270 ses->serverNOS[len] = 0;
271 }
264 272
265 bcc_ptr += len + 1; 273 bcc_ptr += len + 1;
266 bleft -= len + 1; 274 bleft -= len + 1;