Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
"Back from SambaXP - now have 8 small CIFS bug fixes to merge"

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
CIFS: Fix race condition on RFC1002_NEGATIVE_SESSION_RESPONSE
Fix to convert SURROGATE PAIR
cifs: potential missing check for posix_lock_file_wait
Fix to check Unique id and FileType when client refer file directly.
CIFS: remove an unneeded NULL check
[cifs] fix null pointer check
Fix that several functions handle incorrect value of mapchars
cifs: Don't replace dentries for dfs mounts

+194 -74
+2 -1
fs/cifs/cifs_dfs_ref.c
··· 24 24 #include "cifsfs.h" 25 25 #include "dns_resolve.h" 26 26 #include "cifs_debug.h" 27 + #include "cifs_unicode.h" 27 28 28 29 static LIST_HEAD(cifs_dfs_automount_list); 29 30 ··· 313 312 xid = get_xid(); 314 313 rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls, 315 314 &num_referrals, &referrals, 316 - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 315 + cifs_remap(cifs_sb)); 317 316 free_xid(xid); 318 317 319 318 cifs_put_tlink(tlink);
+136 -46
fs/cifs/cifs_unicode.c
··· 27 27 #include "cifsglob.h" 28 28 #include "cifs_debug.h" 29 29 30 - /* 31 - * cifs_utf16_bytes - how long will a string be after conversion? 32 - * @utf16 - pointer to input string 33 - * @maxbytes - don't go past this many bytes of input string 34 - * @codepage - destination codepage 35 - * 36 - * Walk a utf16le string and return the number of bytes that the string will 37 - * be after being converted to the given charset, not including any null 38 - * termination required. Don't walk past maxbytes in the source buffer. 39 - */ 40 - int 41 - cifs_utf16_bytes(const __le16 *from, int maxbytes, 42 - const struct nls_table *codepage) 43 - { 44 - int i; 45 - int charlen, outlen = 0; 46 - int maxwords = maxbytes / 2; 47 - char tmp[NLS_MAX_CHARSET_SIZE]; 48 - __u16 ftmp; 49 - 50 - for (i = 0; i < maxwords; i++) { 51 - ftmp = get_unaligned_le16(&from[i]); 52 - if (ftmp == 0) 53 - break; 54 - 55 - charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE); 56 - if (charlen > 0) 57 - outlen += charlen; 58 - else 59 - outlen++; 60 - } 61 - 62 - return outlen; 63 - } 64 - 65 30 int cifs_remap(struct cifs_sb_info *cifs_sb) 66 31 { 67 32 int map_type; ··· 120 155 * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). 121 156 */ 122 157 static int 123 - cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, 158 + cifs_mapchar(char *target, const __u16 *from, const struct nls_table *cp, 124 159 int maptype) 125 160 { 126 161 int len = 1; 162 + __u16 src_char; 163 + 164 + src_char = *from; 127 165 128 166 if ((maptype == SFM_MAP_UNI_RSVD) && convert_sfm_char(src_char, target)) 129 167 return len; ··· 136 168 137 169 /* if character not one of seven in special remap set */ 138 170 len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); 139 - if (len <= 0) { 140 - *target = '?'; 141 - len = 1; 142 - } 171 + if (len <= 0) 172 + goto surrogate_pair; 173 + 174 + return len; 175 + 176 + surrogate_pair: 177 + /* convert SURROGATE_PAIR and IVS */ 178 + if (strcmp(cp->charset, "utf8")) 179 + goto unknown; 180 + len = utf16s_to_utf8s(from, 3, UTF16_LITTLE_ENDIAN, target, 6); 181 + if (len <= 0) 182 + goto unknown; 183 + return len; 184 + 185 + unknown: 186 + *target = '?'; 187 + len = 1; 143 188 return len; 144 189 } 145 190 ··· 187 206 int nullsize = nls_nullsize(codepage); 188 207 int fromwords = fromlen / 2; 189 208 char tmp[NLS_MAX_CHARSET_SIZE]; 190 - __u16 ftmp; 209 + __u16 ftmp[3]; /* ftmp[3] = 3array x 2bytes = 6bytes UTF-16 */ 191 210 192 211 /* 193 212 * because the chars can be of varying widths, we need to take care ··· 198 217 safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); 199 218 200 219 for (i = 0; i < fromwords; i++) { 201 - ftmp = get_unaligned_le16(&from[i]); 202 - if (ftmp == 0) 220 + ftmp[0] = get_unaligned_le16(&from[i]); 221 + if (ftmp[0] == 0) 203 222 break; 223 + if (i + 1 < fromwords) 224 + ftmp[1] = get_unaligned_le16(&from[i + 1]); 225 + else 226 + ftmp[1] = 0; 227 + if (i + 2 < fromwords) 228 + ftmp[2] = get_unaligned_le16(&from[i + 2]); 229 + else 230 + ftmp[2] = 0; 204 231 205 232 /* 206 233 * check to see if converting this character might make the ··· 223 234 /* put converted char into 'to' buffer */ 224 235 charlen = cifs_mapchar(&to[outlen], ftmp, codepage, map_type); 225 236 outlen += charlen; 237 + 238 + /* charlen (=bytes of UTF-8 for 1 character) 239 + * 4bytes UTF-8(surrogate pair) is charlen=4 240 + * (4bytes UTF-16 code) 241 + * 7-8bytes UTF-8(IVS) is charlen=3+4 or 4+4 242 + * (2 UTF-8 pairs divided to 2 UTF-16 pairs) */ 243 + if (charlen == 4) 244 + i++; 245 + else if (charlen >= 5) 246 + /* 5-6bytes UTF-8 */ 247 + i += 2; 226 248 } 227 249 228 250 /* properly null-terminate string */ ··· 293 293 success: 294 294 put_unaligned_le16(0, &to[i]); 295 295 return i; 296 + } 297 + 298 + /* 299 + * cifs_utf16_bytes - how long will a string be after conversion? 300 + * @utf16 - pointer to input string 301 + * @maxbytes - don't go past this many bytes of input string 302 + * @codepage - destination codepage 303 + * 304 + * Walk a utf16le string and return the number of bytes that the string will 305 + * be after being converted to the given charset, not including any null 306 + * termination required. Don't walk past maxbytes in the source buffer. 307 + */ 308 + int 309 + cifs_utf16_bytes(const __le16 *from, int maxbytes, 310 + const struct nls_table *codepage) 311 + { 312 + int i; 313 + int charlen, outlen = 0; 314 + int maxwords = maxbytes / 2; 315 + char tmp[NLS_MAX_CHARSET_SIZE]; 316 + __u16 ftmp[3]; 317 + 318 + for (i = 0; i < maxwords; i++) { 319 + ftmp[0] = get_unaligned_le16(&from[i]); 320 + if (ftmp[0] == 0) 321 + break; 322 + if (i + 1 < maxwords) 323 + ftmp[1] = get_unaligned_le16(&from[i + 1]); 324 + else 325 + ftmp[1] = 0; 326 + if (i + 2 < maxwords) 327 + ftmp[2] = get_unaligned_le16(&from[i + 2]); 328 + else 329 + ftmp[2] = 0; 330 + 331 + charlen = cifs_mapchar(tmp, ftmp, codepage, NO_MAP_UNI_RSVD); 332 + outlen += charlen; 333 + } 334 + 335 + return outlen; 296 336 } 297 337 298 338 /* ··· 449 409 char src_char; 450 410 __le16 dst_char; 451 411 wchar_t tmp; 412 + wchar_t *wchar_to; /* UTF-16 */ 413 + int ret; 414 + unicode_t u; 452 415 453 416 if (map_chars == NO_MAP_UNI_RSVD) 454 417 return cifs_strtoUTF16(target, source, PATH_MAX, cp); 418 + 419 + wchar_to = kzalloc(6, GFP_KERNEL); 455 420 456 421 for (i = 0; i < srclen; j++) { 457 422 src_char = source[i]; ··· 486 441 * if no match, use question mark, which at least in 487 442 * some cases serves as wild card 488 443 */ 489 - if (charlen < 1) { 490 - dst_char = cpu_to_le16(0x003f); 491 - charlen = 1; 444 + if (charlen > 0) 445 + goto ctoUTF16; 446 + 447 + /* convert SURROGATE_PAIR */ 448 + if (strcmp(cp->charset, "utf8") || !wchar_to) 449 + goto unknown; 450 + if (*(source + i) & 0x80) { 451 + charlen = utf8_to_utf32(source + i, 6, &u); 452 + if (charlen < 0) 453 + goto unknown; 454 + } else 455 + goto unknown; 456 + ret = utf8s_to_utf16s(source + i, charlen, 457 + UTF16_LITTLE_ENDIAN, 458 + wchar_to, 6); 459 + if (ret < 0) 460 + goto unknown; 461 + 462 + i += charlen; 463 + dst_char = cpu_to_le16(*wchar_to); 464 + if (charlen <= 3) 465 + /* 1-3bytes UTF-8 to 2bytes UTF-16 */ 466 + put_unaligned(dst_char, &target[j]); 467 + else if (charlen == 4) { 468 + /* 4bytes UTF-8(surrogate pair) to 4bytes UTF-16 469 + * 7-8bytes UTF-8(IVS) divided to 2 UTF-16 470 + * (charlen=3+4 or 4+4) */ 471 + put_unaligned(dst_char, &target[j]); 472 + dst_char = cpu_to_le16(*(wchar_to + 1)); 473 + j++; 474 + put_unaligned(dst_char, &target[j]); 475 + } else if (charlen >= 5) { 476 + /* 5-6bytes UTF-8 to 6bytes UTF-16 */ 477 + put_unaligned(dst_char, &target[j]); 478 + dst_char = cpu_to_le16(*(wchar_to + 1)); 479 + j++; 480 + put_unaligned(dst_char, &target[j]); 481 + dst_char = cpu_to_le16(*(wchar_to + 2)); 482 + j++; 483 + put_unaligned(dst_char, &target[j]); 492 484 } 485 + continue; 486 + 487 + unknown: 488 + dst_char = cpu_to_le16(0x003f); 489 + charlen = 1; 493 490 } 491 + 492 + ctoUTF16: 494 493 /* 495 494 * character may take more than one byte in the source string, 496 495 * but will take exactly two bytes in the target string ··· 545 456 546 457 ctoUTF16_out: 547 458 put_unaligned(0, &target[j]); /* Null terminate target unicode string */ 459 + kfree(wchar_to); 548 460 return j; 549 461 } 550 462
+2
fs/cifs/cifsfs.c
··· 469 469 seq_puts(s, ",nouser_xattr"); 470 470 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 471 471 seq_puts(s, ",mapchars"); 472 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR) 473 + seq_puts(s, ",mapposix"); 472 474 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) 473 475 seq_puts(s, ",sfu"); 474 476 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+2 -2
fs/cifs/cifsproto.h
··· 361 361 extern int CIFSUnixCreateSymLink(const unsigned int xid, 362 362 struct cifs_tcon *tcon, 363 363 const char *fromName, const char *toName, 364 - const struct nls_table *nls_codepage); 364 + const struct nls_table *nls_codepage, int remap); 365 365 extern int CIFSSMBUnixQuerySymLink(const unsigned int xid, 366 366 struct cifs_tcon *tcon, 367 367 const unsigned char *searchName, char **syminfo, 368 - const struct nls_table *nls_codepage); 368 + const struct nls_table *nls_codepage, int remap); 369 369 extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, 370 370 __u16 fid, char **symlinkinfo, 371 371 const struct nls_table *nls_codepage);
+12 -11
fs/cifs/cifssmb.c
··· 2784 2784 int 2785 2785 CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, 2786 2786 const char *fromName, const char *toName, 2787 - const struct nls_table *nls_codepage) 2787 + const struct nls_table *nls_codepage, int remap) 2788 2788 { 2789 2789 TRANSACTION2_SPI_REQ *pSMB = NULL; 2790 2790 TRANSACTION2_SPI_RSP *pSMBr = NULL; ··· 2804 2804 2805 2805 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2806 2806 name_len = 2807 - cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName, 2808 - /* find define for this maxpathcomponent */ 2809 - PATH_MAX, nls_codepage); 2807 + cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName, 2808 + /* find define for this maxpathcomponent */ 2809 + PATH_MAX, nls_codepage, remap); 2810 2810 name_len++; /* trailing null */ 2811 2811 name_len *= 2; 2812 2812 ··· 2828 2828 data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 2829 2829 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2830 2830 name_len_target = 2831 - cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX 2832 - /* find define for this maxpathcomponent */ 2833 - , nls_codepage); 2831 + cifsConvertToUTF16((__le16 *) data_offset, toName, 2832 + /* find define for this maxpathcomponent */ 2833 + PATH_MAX, nls_codepage, remap); 2834 2834 name_len_target++; /* trailing null */ 2835 2835 name_len_target *= 2; 2836 2836 } else { /* BB improve the check for buffer overruns BB */ ··· 3034 3034 int 3035 3035 CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, 3036 3036 const unsigned char *searchName, char **symlinkinfo, 3037 - const struct nls_table *nls_codepage) 3037 + const struct nls_table *nls_codepage, int remap) 3038 3038 { 3039 3039 /* SMB_QUERY_FILE_UNIX_LINK */ 3040 3040 TRANSACTION2_QPI_REQ *pSMB = NULL; ··· 3055 3055 3056 3056 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3057 3057 name_len = 3058 - cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName, 3059 - PATH_MAX, nls_codepage); 3058 + cifsConvertToUTF16((__le16 *) pSMB->FileName, 3059 + searchName, PATH_MAX, nls_codepage, 3060 + remap); 3060 3061 name_len++; /* trailing null */ 3061 3062 name_len *= 2; 3062 3063 } else { /* BB improve the check for buffer overruns BB */ ··· 4918 4917 strncpy(pSMB->RequestFileName, search_name, name_len); 4919 4918 } 4920 4919 4921 - if (ses->server && ses->server->sign) 4920 + if (ses->server->sign) 4922 4921 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 4923 4922 4924 4923 pSMB->hdr.Uid = ses->Suid;
+2 -1
fs/cifs/connect.c
··· 386 386 rc = generic_ip_connect(server); 387 387 if (rc) { 388 388 cifs_dbg(FYI, "reconnect error %d\n", rc); 389 + mutex_unlock(&server->srv_mutex); 389 390 msleep(3000); 390 391 } else { 391 392 atomic_inc(&tcpSesReconnectCount); ··· 394 393 if (server->tcpStatus != CifsExiting) 395 394 server->tcpStatus = CifsNeedNegotiate; 396 395 spin_unlock(&GlobalMid_Lock); 396 + mutex_unlock(&server->srv_mutex); 397 397 } 398 - mutex_unlock(&server->srv_mutex); 399 398 } while (server->tcpStatus == CifsNeedReconnect); 400 399 401 400 return rc;
+1 -2
fs/cifs/dir.c
··· 620 620 } 621 621 rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, 622 622 cifs_sb->local_nls, 623 - cifs_sb->mnt_cifs_flags & 624 - CIFS_MOUNT_MAP_SPECIAL_CHR); 623 + cifs_remap(cifs_sb)); 625 624 if (rc) 626 625 goto mknod_out; 627 626
+3 -4
fs/cifs/file.c
··· 140 140 posix_flags = cifs_posix_convert_flags(f_flags); 141 141 rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, 142 142 poplock, full_path, cifs_sb->local_nls, 143 - cifs_sb->mnt_cifs_flags & 144 - CIFS_MOUNT_MAP_SPECIAL_CHR); 143 + cifs_remap(cifs_sb)); 145 144 cifs_put_tlink(tlink); 146 145 147 146 if (rc) ··· 1552 1553 rc = server->ops->mand_unlock_range(cfile, flock, xid); 1553 1554 1554 1555 out: 1555 - if (flock->fl_flags & FL_POSIX) 1556 - posix_lock_file_wait(file, flock); 1556 + if (flock->fl_flags & FL_POSIX && !rc) 1557 + rc = posix_lock_file_wait(file, flock); 1557 1558 return rc; 1558 1559 } 1559 1560
+27 -4
fs/cifs/inode.c
··· 373 373 374 374 /* could have done a find first instead but this returns more info */ 375 375 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, 376 - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 377 - CIFS_MOUNT_MAP_SPECIAL_CHR); 376 + cifs_sb->local_nls, cifs_remap(cifs_sb)); 378 377 cifs_put_tlink(tlink); 379 378 380 379 if (!rc) { ··· 401 402 rc = -ENOMEM; 402 403 } else { 403 404 /* we already have inode, update it */ 405 + 406 + /* if uniqueid is different, return error */ 407 + if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM && 408 + CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) { 409 + rc = -ESTALE; 410 + goto cgiiu_exit; 411 + } 412 + 413 + /* if filetype is different, return error */ 414 + if (unlikely(((*pinode)->i_mode & S_IFMT) != 415 + (fattr.cf_mode & S_IFMT))) { 416 + rc = -ESTALE; 417 + goto cgiiu_exit; 418 + } 419 + 404 420 cifs_fattr_to_inode(*pinode, &fattr); 405 421 } 406 422 423 + cgiiu_exit: 407 424 return rc; 408 425 } 409 426 ··· 854 839 if (!*inode) 855 840 rc = -ENOMEM; 856 841 } else { 842 + /* we already have inode, update it */ 843 + 844 + /* if filetype is different, return error */ 845 + if (unlikely(((*inode)->i_mode & S_IFMT) != 846 + (fattr.cf_mode & S_IFMT))) { 847 + rc = -ESTALE; 848 + goto cgii_exit; 849 + } 850 + 857 851 cifs_fattr_to_inode(*inode, &fattr); 858 852 } 859 853 ··· 2239 2215 pTcon = tlink_tcon(tlink); 2240 2216 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, 2241 2217 cifs_sb->local_nls, 2242 - cifs_sb->mnt_cifs_flags & 2243 - CIFS_MOUNT_MAP_SPECIAL_CHR); 2218 + cifs_remap(cifs_sb)); 2244 2219 cifs_put_tlink(tlink); 2245 2220 } 2246 2221
+2 -1
fs/cifs/link.c
··· 717 717 rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); 718 718 else if (pTcon->unix_ext) 719 719 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, 720 - cifs_sb->local_nls); 720 + cifs_sb->local_nls, 721 + cifs_remap(cifs_sb)); 721 722 /* else 722 723 rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName, 723 724 cifs_sb_target->local_nls); */
+2
fs/cifs/readdir.c
··· 90 90 if (dentry) { 91 91 inode = d_inode(dentry); 92 92 if (inode) { 93 + if (d_mountpoint(dentry)) 94 + goto out; 93 95 /* 94 96 * If we're generating inode numbers, then we don't 95 97 * want to clobber the existing one with the one that
+2 -1
fs/cifs/smb1ops.c
··· 960 960 /* Check for unix extensions */ 961 961 if (cap_unix(tcon->ses)) { 962 962 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, 963 - cifs_sb->local_nls); 963 + cifs_sb->local_nls, 964 + cifs_remap(cifs_sb)); 964 965 if (rc == -EREMOTE) 965 966 rc = cifs_unix_dfs_readlink(xid, tcon, full_path, 966 967 target_path,
+1 -1
fs/cifs/smb2pdu.c
··· 110 110 111 111 /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */ 112 112 /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ 113 - if ((tcon->ses) && 113 + if ((tcon->ses) && (tcon->ses->server) && 114 114 (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) 115 115 hdr->CreditCharge = cpu_to_le16(1); 116 116 /* else CreditCharge MBZ */