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

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (21 commits)
[CIFS] Remove debug statement
Fix possible access to undefined memory region.
[CIFS] Enable DFS support for Windows query path info
[CIFS] Enable DFS support for Unix query path info
[CIFS] add missing seq_printf to cifs_show_options for hard mount option
[CIFS] add more complete mount options to cifs_show_options
[CIFS] Add missing defines for DFS
CIFSGetDFSRefer cleanup + dfs_referral_level_3 fixed to conform REFERRAL_V3 the MS-DFSC spec.
Fixed DFS code to work with new 'build_path_from_dentry', that returns full path if share in the dfs, now.
[CIFS] enable parsing for transport encryption mount parm
[CIFS] Finishup DFS code
[CIFS] BKL-removal: convert CIFS over to unlocked_ioctl
[CIFS] suppress duplicate warning
[CIFS] Fix paths when share is in DFS to include proper prefix
add function to convert access flags to legacy open mode
clarify return value of cifs_convert_flags()
[CIFS] don't explicitly do a FindClose on rewind when directory search has ended
[CIFS] cleanup old checkpatch warnings
[CIFS] CIFSSMBPosixLock should return -EINVAL on error
fix memory leak in CIFSFindNext
...

+625 -558
+1
fs/cifs/AUTHORS
··· 36 36 Kazeon team for various fixes especially for 2.4 version. 37 37 Asser Ferno (Change Notify support) 38 38 Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup 39 + Igor Mammedov (DFS support) 39 40 40 41 Test case and Bug Report contributors 41 42 -------------------------------------
+4 -1
fs/cifs/CHANGES
··· 1 1 Version 1.53 2 2 ------------ 3 + DFS support added (Microsoft Distributed File System client support needed 4 + for referrals which enable a hierarchical name space among servers). 3 5 4 6 Version 1.52 5 7 ------------ ··· 14 12 cifsacl flag). Fix prefixpath path separator so we can handle mounts 15 13 with prefixpaths longer than one directory (one path component) when 16 14 mounted to Windows servers. Fix slow file open when cifsacl 17 - enabled. 15 + enabled. Fix memory leak in FindNext when the SMB call returns -EBADF. 16 + 18 17 19 18 Version 1.51 20 19 ------------
+5
fs/cifs/README
··· 483 483 sign Must use packet signing (helps avoid unwanted data modification 484 484 by intermediate systems in the route). Note that signing 485 485 does not work with lanman or plaintext authentication. 486 + seal Must seal (encrypt) all data on this mounted share before 487 + sending on the network. Requires support for Unix Extensions. 488 + Note that this differs from the sign mount option in that it 489 + causes encryption of data sent over this mounted share but other 490 + shares mounted to the same server are unaffected. 486 491 sec Security mode. Allowed values are: 487 492 none attempt to connection as a null user (no name) 488 493 krb5 Use Kerberos version 5 authentication
+8 -7
fs/cifs/TODO
··· 1 - Version 1.52 January 3, 2008 1 + Version 1.53 May 20, 2008 2 2 3 3 A Partial List of Missing Features 4 4 ================================== ··· 20 20 fs/cifs/connect.c and add back in NTLMSSP code if any servers 21 21 need it 22 22 23 - e) ms-dfs and ms-dfs host name resolution cleanup 24 - 25 - f) fix NTLMv2 signing when two mounts with different users to same 23 + e) fix NTLMv2 signing when two mounts with different users to same 26 24 server. 27 25 28 - g) Directory entry caching relies on a 1 second timer, rather than 26 + f) Directory entry caching relies on a 1 second timer, rather than 29 27 using FindNotify or equivalent. - (started) 30 28 31 - h) quota support (needs minor kernel change since quota calls 29 + g) quota support (needs minor kernel change since quota calls 32 30 to make it to network filesystems or deviceless filesystems) 33 31 34 - i) investigate sync behavior (including syncpage) and check 32 + h) investigate sync behavior (including syncpage) and check 35 33 for proper behavior of intr/nointr 34 + 35 + i) improve support for very old servers (OS/2 and Win9x for example) 36 + Including support for changing the time remotely (utimes command). 36 37 37 38 j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the 38 39 extra copy in/out of the socket buffers in some cases.
+1 -48
fs/cifs/cifs_dfs_ref.c
··· 219 219 220 220 } 221 221 222 - static char *build_full_dfs_path_from_dentry(struct dentry *dentry) 223 - { 224 - char *full_path = NULL; 225 - char *search_path; 226 - char *tmp_path; 227 - size_t l_max_len; 228 - struct cifs_sb_info *cifs_sb; 229 - 230 - if (dentry->d_inode == NULL) 231 - return NULL; 232 - 233 - cifs_sb = CIFS_SB(dentry->d_inode->i_sb); 234 - 235 - if (cifs_sb->tcon == NULL) 236 - return NULL; 237 - 238 - search_path = build_path_from_dentry(dentry); 239 - if (search_path == NULL) 240 - return NULL; 241 - 242 - if (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS) { 243 - int i; 244 - /* we should use full path name for correct working with DFS */ 245 - l_max_len = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE+1) + 246 - strnlen(search_path, MAX_PATHCONF) + 1; 247 - tmp_path = kmalloc(l_max_len, GFP_KERNEL); 248 - if (tmp_path == NULL) { 249 - kfree(search_path); 250 - return NULL; 251 - } 252 - strncpy(tmp_path, cifs_sb->tcon->treeName, l_max_len); 253 - tmp_path[l_max_len-1] = 0; 254 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 255 - for (i = 0; i < l_max_len; i++) { 256 - if (tmp_path[i] == '\\') 257 - tmp_path[i] = '/'; 258 - } 259 - strncat(tmp_path, search_path, l_max_len - strlen(tmp_path)); 260 - 261 - full_path = tmp_path; 262 - kfree(search_path); 263 - } else { 264 - full_path = search_path; 265 - } 266 - return full_path; 267 - } 268 - 269 222 static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, 270 223 struct list_head *mntlist) 271 224 { ··· 286 333 goto out_err; 287 334 } 288 335 289 - full_path = build_full_dfs_path_from_dentry(dentry); 336 + full_path = build_path_from_dentry(dentry); 290 337 if (full_path == NULL) { 291 338 rc = -ENOMEM; 292 339 goto out_err;
+1
fs/cifs/cifs_fs_sb.h
··· 30 30 #define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */ 31 31 #define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */ 32 32 #define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */ 33 + #define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ 33 34 34 35 struct cifs_sb_info { 35 36 struct cifsTconInfo *tcon; /* primary mount */
+38 -6
fs/cifs/cifsfs.c
··· 1 1 /* 2 2 * fs/cifs/cifsfs.c 3 3 * 4 - * Copyright (C) International Business Machines Corp., 2002,2007 4 + * Copyright (C) International Business Machines Corp., 2002,2008 5 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 6 * 7 7 * Common Internet FileSystem (CIFS) client ··· 353 353 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || 354 354 !(cifs_sb->tcon->unix_ext)) 355 355 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); 356 + if (!cifs_sb->tcon->unix_ext) { 357 + seq_printf(s, ",file_mode=0%o,dir_mode=0%o", 358 + cifs_sb->mnt_file_mode, 359 + cifs_sb->mnt_dir_mode); 360 + } 361 + if (cifs_sb->tcon->seal) 362 + seq_printf(s, ",seal"); 363 + if (cifs_sb->tcon->nocase) 364 + seq_printf(s, ",nocase"); 365 + if (cifs_sb->tcon->retry) 366 + seq_printf(s, ",hard"); 356 367 } 357 368 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 358 369 seq_printf(s, ",posixpaths"); 370 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) 371 + seq_printf(s, ",setuids"); 372 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 373 + seq_printf(s, ",serverino"); 374 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 375 + seq_printf(s, ",directio"); 376 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 377 + seq_printf(s, ",nouser_xattr"); 378 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 379 + seq_printf(s, ",mapchars"); 380 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) 381 + seq_printf(s, ",sfu"); 382 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 383 + seq_printf(s, ",nobrl"); 384 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) 385 + seq_printf(s, ",cifsacl"); 386 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) 387 + seq_printf(s, ",dynperm"); 388 + if (m->mnt_sb->s_flags & MS_POSIXACL) 389 + seq_printf(s, ",acl"); 390 + 359 391 seq_printf(s, ",rsize=%d", cifs_sb->rsize); 360 392 seq_printf(s, ",wsize=%d", cifs_sb->wsize); 361 393 } ··· 689 657 .splice_read = generic_file_splice_read, 690 658 .llseek = cifs_llseek, 691 659 #ifdef CONFIG_CIFS_POSIX 692 - .ioctl = cifs_ioctl, 660 + .unlocked_ioctl = cifs_ioctl, 693 661 #endif /* CONFIG_CIFS_POSIX */ 694 662 695 663 #ifdef CONFIG_CIFS_EXPERIMENTAL ··· 709 677 .flush = cifs_flush, 710 678 .splice_read = generic_file_splice_read, 711 679 #ifdef CONFIG_CIFS_POSIX 712 - .ioctl = cifs_ioctl, 680 + .unlocked_ioctl = cifs_ioctl, 713 681 #endif /* CONFIG_CIFS_POSIX */ 714 682 .llseek = cifs_llseek, 715 683 #ifdef CONFIG_CIFS_EXPERIMENTAL ··· 729 697 .splice_read = generic_file_splice_read, 730 698 .llseek = cifs_llseek, 731 699 #ifdef CONFIG_CIFS_POSIX 732 - .ioctl = cifs_ioctl, 700 + .unlocked_ioctl = cifs_ioctl, 733 701 #endif /* CONFIG_CIFS_POSIX */ 734 702 735 703 #ifdef CONFIG_CIFS_EXPERIMENTAL ··· 748 716 .flush = cifs_flush, 749 717 .splice_read = generic_file_splice_read, 750 718 #ifdef CONFIG_CIFS_POSIX 751 - .ioctl = cifs_ioctl, 719 + .unlocked_ioctl = cifs_ioctl, 752 720 #endif /* CONFIG_CIFS_POSIX */ 753 721 .llseek = cifs_llseek, 754 722 #ifdef CONFIG_CIFS_EXPERIMENTAL ··· 763 731 #ifdef CONFIG_CIFS_EXPERIMENTAL 764 732 .dir_notify = cifs_dir_notify, 765 733 #endif /* CONFIG_CIFS_EXPERIMENTAL */ 766 - .ioctl = cifs_ioctl, 734 + .unlocked_ioctl = cifs_ioctl, 767 735 }; 768 736 769 737 static void
+1 -2
fs/cifs/cifsfs.h
··· 95 95 size_t, int); 96 96 extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); 97 97 extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 98 - extern int cifs_ioctl(struct inode *inode, struct file *filep, 99 - unsigned int command, unsigned long arg); 98 + extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); 100 99 101 100 #ifdef CONFIG_CIFS_EXPERIMENTAL 102 101 extern const struct export_operations cifs_export_ops;
+1
fs/cifs/cifsglob.h
··· 281 281 bool ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */ 282 282 bool retry:1; 283 283 bool nocase:1; 284 + bool seal:1; /* transport encryption for this mounted share */ 284 285 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol 285 286 for this mount even if server would support */ 286 287 /* BB add field for back pointer to sb struct(s)? */
+16 -9
fs/cifs/cifspdu.h
··· 1904 1904 char RequestFileName[1]; 1905 1905 } __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ; 1906 1906 1907 + #define DFS_VERSION cpu_to_le16(0x0003) 1908 + 1909 + /* DFS server target type */ 1910 + #define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */ 1911 + #define DFS_TYPE_ROOT 0x0001 1912 + 1913 + /* Referral Entry Flags */ 1914 + #define DFS_NAME_LIST_REF 0x0200 1915 + 1907 1916 typedef struct dfs_referral_level_3 { 1908 1917 __le16 VersionNumber; 1909 - __le16 ReferralSize; 1910 - __le16 ServerType; /* 0x0001 = CIFS server */ 1911 - __le16 ReferralFlags; /* or proximity - not clear which since it is 1912 - always set to zero - SNIA spec says 0x01 1913 - means strip off PathConsumed chars before 1914 - submitting RequestFileName to remote node */ 1915 - __le16 TimeToLive; 1916 - __le16 Proximity; 1918 + __le16 Size; 1919 + __le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */ 1920 + __le16 ReferralEntryFlags; /* 0x0200 bit set only for domain 1921 + or DC referral responce */ 1922 + __le32 TimeToLive; 1917 1923 __le16 DfsPathOffset; 1918 1924 __le16 DfsAlternatePathOffset; 1919 - __le16 NetworkAddressOffset; 1925 + __le16 NetworkAddressOffset; /* offset of the link target */ 1926 + __le16 ServiceSiteGuid; 1920 1927 } __attribute__((packed)) REFERRAL3; 1921 1928 1922 1929 typedef struct smb_com_transaction_get_dfs_refer_rsp {
+5 -8
fs/cifs/cifsproto.h
··· 93 93 94 94 extern int cifs_get_inode_info(struct inode **pinode, 95 95 const unsigned char *search_path, 96 - FILE_ALL_INFO * pfile_info, 96 + FILE_ALL_INFO *pfile_info, 97 97 struct super_block *sb, int xid, const __u16 *pfid); 98 98 extern int cifs_get_inode_info_unix(struct inode **pinode, 99 99 const unsigned char *search_path, ··· 130 130 131 131 extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 132 132 const unsigned char *searchName, 133 - FILE_ALL_INFO * findData, 133 + FILE_ALL_INFO *findData, 134 134 int legacy /* whether to use old info level */, 135 135 const struct nls_table *nls_codepage, int remap); 136 136 extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, ··· 141 141 extern int CIFSSMBUnixQPathInfo(const int xid, 142 142 struct cifsTconInfo *tcon, 143 143 const unsigned char *searchName, 144 - FILE_UNIX_BASIC_INFO * pFindData, 144 + FILE_UNIX_BASIC_INFO *pFindData, 145 145 const struct nls_table *nls_codepage, int remap); 146 146 147 147 extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, 148 148 const unsigned char *searchName, 149 - unsigned char **targetUNCs, 150 - unsigned int *number_of_UNC_in_array, 149 + struct dfs_info3_param **target_nodes, 150 + unsigned int *number_of_nodes_in_array, 151 151 const struct nls_table *nls_codepage, int remap); 152 152 153 - extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 154 - const char *old_path, 155 - const struct nls_table *nls_codepage, int remap); 156 153 extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 157 154 const char *old_path, 158 155 const struct nls_table *nls_codepage,
+195 -126
fs/cifs/cifssmb.c
··· 81 81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */ 82 82 #endif /* CIFS_POSIX */ 83 83 84 + /* Allocates buffer into dst and copies smb string from src to it. 85 + * caller is responsible for freeing dst if function returned 0. 86 + * returns: 87 + * on success - 0 88 + * on failure - errno 89 + */ 90 + static int 91 + cifs_strncpy_to_host(char **dst, const char *src, const int maxlen, 92 + const bool is_unicode, const struct nls_table *nls_codepage) 93 + { 94 + int plen; 95 + 96 + if (is_unicode) { 97 + plen = UniStrnlen((wchar_t *)src, maxlen); 98 + *dst = kmalloc(plen + 2, GFP_KERNEL); 99 + if (!*dst) 100 + goto cifs_strncpy_to_host_ErrExit; 101 + cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage); 102 + } else { 103 + plen = strnlen(src, maxlen); 104 + *dst = kmalloc(plen + 2, GFP_KERNEL); 105 + if (!*dst) 106 + goto cifs_strncpy_to_host_ErrExit; 107 + strncpy(*dst, src, plen); 108 + } 109 + (*dst)[plen] = 0; 110 + (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */ 111 + return 0; 112 + 113 + cifs_strncpy_to_host_ErrExit: 114 + cERROR(1, ("Failed to allocate buffer for string\n")); 115 + return -ENOMEM; 116 + } 117 + 84 118 85 119 /* Mark as invalid, all open files on tree connections since they 86 120 were closed when session to server was lost */ ··· 1200 1166 return ofun; 1201 1167 } 1202 1168 1169 + static int 1170 + access_flags_to_smbopen_mode(const int access_flags) 1171 + { 1172 + int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE); 1173 + 1174 + if (masked_flags == GENERIC_READ) 1175 + return SMBOPEN_READ; 1176 + else if (masked_flags == GENERIC_WRITE) 1177 + return SMBOPEN_WRITE; 1178 + 1179 + /* just go for read/write */ 1180 + return SMBOPEN_READWRITE; 1181 + } 1182 + 1203 1183 int 1204 1184 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, 1205 1185 const char *fileName, const int openDisposition, ··· 1255 1207 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); 1256 1208 1257 1209 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); 1258 - /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ 1259 - /* 0 = read 1260 - 1 = write 1261 - 2 = rw 1262 - 3 = execute 1263 - */ 1264 - pSMB->Mode = cpu_to_le16(2); 1210 + pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags)); 1265 1211 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */ 1266 1212 /* set file as system file if special file such 1267 1213 as fifo and server expecting SFU style and ··· 1289 1247 } else { 1290 1248 /* BB verify if wct == 15 */ 1291 1249 1292 - /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */ 1250 + /* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/ 1293 1251 1294 1252 *netfid = pSMBr->Fid; /* cifs fid stays in le */ 1295 1253 /* Let caller know file was created so we can set the mode. */ ··· 1809 1767 cFYI(1, ("Posix Lock")); 1810 1768 1811 1769 if (pLockData == NULL) 1812 - return EINVAL; 1770 + return -EINVAL; 1813 1771 1814 1772 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); 1815 1773 ··· 1986 1944 /* protocol requires ASCII signature byte on Unicode string */ 1987 1945 pSMB->OldFileName[name_len + 1] = 0x00; 1988 1946 name_len2 = 1989 - cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2], 1947 + cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], 1990 1948 toName, PATH_MAX, nls_codepage, remap); 1991 1949 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 1992 1950 name_len2 *= 2; /* convert to bytes */ ··· 2967 2925 } 2968 2926 params = 6 + name_len; 2969 2927 pSMB->MaxParameterCount = cpu_to_le16(2); 2970 - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ 2928 + /* BB find max SMB size from sess */ 2929 + pSMB->MaxDataCount = cpu_to_le16(1000); 2971 2930 pSMB->MaxSetupCount = 0; 2972 2931 pSMB->Reserved = 0; 2973 2932 pSMB->Flags = 0; ··· 3365 3322 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; 3366 3323 pSMB->TotalDataCount = 0; 3367 3324 pSMB->MaxParameterCount = cpu_to_le16(2); 3368 - pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ 3325 + /* BB find exact max SMB PDU from sess structure BB */ 3326 + pSMB->MaxDataCount = cpu_to_le16(4000); 3369 3327 pSMB->MaxSetupCount = 0; 3370 3328 pSMB->Reserved = 0; 3371 3329 pSMB->Flags = 0; ··· 3432 3388 int 3433 3389 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, 3434 3390 const unsigned char *searchName, 3435 - FILE_UNIX_BASIC_INFO * pFindData, 3391 + FILE_UNIX_BASIC_INFO *pFindData, 3436 3392 const struct nls_table *nls_codepage, int remap) 3437 3393 { 3438 3394 /* SMB_QUERY_FILE_UNIX_BASIC */ ··· 3723 3679 if (rc) { 3724 3680 if (rc == -EBADF) { 3725 3681 psrch_inf->endOfSearch = true; 3682 + cifs_buf_release(pSMB); 3726 3683 rc = 0; /* search probably was closed at end of search*/ 3727 3684 } else 3728 3685 cFYI(1, ("FindNext returned = %d", rc)); ··· 3901 3856 return rc; 3902 3857 } 3903 3858 3859 + /* parses DFS refferal V3 structure 3860 + * caller is responsible for freeing target_nodes 3861 + * returns: 3862 + * on success - 0 3863 + * on failure - errno 3864 + */ 3865 + static int 3866 + parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, 3867 + unsigned int *num_of_nodes, 3868 + struct dfs_info3_param **target_nodes, 3869 + const struct nls_table *nls_codepage) 3870 + { 3871 + int i, rc = 0; 3872 + char *data_end; 3873 + bool is_unicode; 3874 + struct dfs_referral_level_3 *ref; 3875 + 3876 + is_unicode = pSMBr->hdr.Flags2 & SMBFLG2_UNICODE; 3877 + *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); 3878 + 3879 + if (*num_of_nodes < 1) { 3880 + cERROR(1, ("num_referrals: must be at least > 0," 3881 + "but we get num_referrals = %d\n", *num_of_nodes)); 3882 + rc = -EINVAL; 3883 + goto parse_DFS_referrals_exit; 3884 + } 3885 + 3886 + ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); 3887 + if (ref->VersionNumber != 3) { 3888 + cERROR(1, ("Referrals of V%d version are not supported," 3889 + "should be V3", ref->VersionNumber)); 3890 + rc = -EINVAL; 3891 + goto parse_DFS_referrals_exit; 3892 + } 3893 + 3894 + /* get the upper boundary of the resp buffer */ 3895 + data_end = (char *)(&(pSMBr->PathConsumed)) + 3896 + le16_to_cpu(pSMBr->t2.DataCount); 3897 + 3898 + cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", 3899 + *num_of_nodes, 3900 + le16_to_cpu(pSMBr->DFSFlags))); 3901 + 3902 + *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * 3903 + *num_of_nodes, GFP_KERNEL); 3904 + if (*target_nodes == NULL) { 3905 + cERROR(1, ("Failed to allocate buffer for target_nodes\n")); 3906 + rc = -ENOMEM; 3907 + goto parse_DFS_referrals_exit; 3908 + } 3909 + 3910 + /* collect neccessary data from referrals */ 3911 + for (i = 0; i < *num_of_nodes; i++) { 3912 + char *temp; 3913 + int max_len; 3914 + struct dfs_info3_param *node = (*target_nodes)+i; 3915 + 3916 + node->flags = le16_to_cpu(pSMBr->DFSFlags); 3917 + node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); 3918 + node->server_type = le16_to_cpu(ref->ServerType); 3919 + node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); 3920 + 3921 + /* copy DfsPath */ 3922 + temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); 3923 + max_len = data_end - temp; 3924 + rc = cifs_strncpy_to_host(&(node->path_name), temp, 3925 + max_len, is_unicode, nls_codepage); 3926 + if (rc) 3927 + goto parse_DFS_referrals_exit; 3928 + 3929 + /* copy link target UNC */ 3930 + temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); 3931 + max_len = data_end - temp; 3932 + rc = cifs_strncpy_to_host(&(node->node_name), temp, 3933 + max_len, is_unicode, nls_codepage); 3934 + if (rc) 3935 + goto parse_DFS_referrals_exit; 3936 + 3937 + ref += ref->Size; 3938 + } 3939 + 3940 + parse_DFS_referrals_exit: 3941 + if (rc) { 3942 + free_dfs_info_array(*target_nodes, *num_of_nodes); 3943 + *target_nodes = NULL; 3944 + *num_of_nodes = 0; 3945 + } 3946 + return rc; 3947 + } 3948 + 3904 3949 int 3905 3950 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, 3906 3951 const unsigned char *searchName, 3907 - unsigned char **targetUNCs, 3908 - unsigned int *number_of_UNC_in_array, 3952 + struct dfs_info3_param **target_nodes, 3953 + unsigned int *num_of_nodes, 3909 3954 const struct nls_table *nls_codepage, int remap) 3910 3955 { 3911 3956 /* TRANS2_GET_DFS_REFERRAL */ 3912 3957 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; 3913 3958 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL; 3914 - struct dfs_referral_level_3 *referrals = NULL; 3915 3959 int rc = 0; 3916 3960 int bytes_returned; 3917 3961 int name_len; 3918 - unsigned int i; 3919 - char *temp; 3920 3962 __u16 params, byte_count; 3921 - *number_of_UNC_in_array = 0; 3922 - *targetUNCs = NULL; 3963 + *num_of_nodes = 0; 3964 + *target_nodes = NULL; 3923 3965 3924 3966 cFYI(1, ("In GetDFSRefer the path %s", searchName)); 3925 3967 if (ses == NULL) ··· 4053 3921 pSMB->DataCount = 0; 4054 3922 pSMB->DataOffset = 0; 4055 3923 pSMB->MaxParameterCount = 0; 4056 - pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ 3924 + /* BB find exact max SMB PDU from sess structure BB */ 3925 + pSMB->MaxDataCount = cpu_to_le16(4000); 4057 3926 pSMB->MaxSetupCount = 0; 4058 3927 pSMB->Reserved = 0; 4059 3928 pSMB->Flags = 0; ··· 4076 3943 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 4077 3944 if (rc) { 4078 3945 cFYI(1, ("Send error in GetDFSRefer = %d", rc)); 4079 - } else { /* decode response */ 4080 - /* BB Add logic to parse referrals here */ 4081 - rc = validate_t2((struct smb_t2_rsp *)pSMBr); 4082 - 4083 - /* BB Also check if enough total bytes returned? */ 4084 - if (rc || (pSMBr->ByteCount < 17)) 4085 - rc = -EIO; /* bad smb */ 4086 - else { 4087 - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 4088 - __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount); 4089 - 4090 - cFYI(1, 4091 - ("Decoding GetDFSRefer response BCC: %d Offset %d", 4092 - pSMBr->ByteCount, data_offset)); 4093 - referrals = 4094 - (struct dfs_referral_level_3 *) 4095 - (8 /* sizeof start of data block */ + 4096 - data_offset + 4097 - (char *) &pSMBr->hdr.Protocol); 4098 - cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n" 4099 - "for referral one refer size: 0x%x srv " 4100 - "type: 0x%x refer flags: 0x%x ttl: 0x%x", 4101 - le16_to_cpu(pSMBr->NumberOfReferrals), 4102 - le16_to_cpu(pSMBr->DFSFlags), 4103 - le16_to_cpu(referrals->ReferralSize), 4104 - le16_to_cpu(referrals->ServerType), 4105 - le16_to_cpu(referrals->ReferralFlags), 4106 - le16_to_cpu(referrals->TimeToLive))); 4107 - /* BB This field is actually two bytes in from start of 4108 - data block so we could do safety check that DataBlock 4109 - begins at address of pSMBr->NumberOfReferrals */ 4110 - *number_of_UNC_in_array = 4111 - le16_to_cpu(pSMBr->NumberOfReferrals); 4112 - 4113 - /* BB Fix below so can return more than one referral */ 4114 - if (*number_of_UNC_in_array > 1) 4115 - *number_of_UNC_in_array = 1; 4116 - 4117 - /* get the length of the strings describing refs */ 4118 - name_len = 0; 4119 - for (i = 0; i < *number_of_UNC_in_array; i++) { 4120 - /* make sure that DfsPathOffset not past end */ 4121 - __u16 offset = 4122 - le16_to_cpu(referrals->DfsPathOffset); 4123 - if (offset > data_count) { 4124 - /* if invalid referral, stop here and do 4125 - not try to copy any more */ 4126 - *number_of_UNC_in_array = i; 4127 - break; 4128 - } 4129 - temp = ((char *)referrals) + offset; 4130 - 4131 - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 4132 - name_len += UniStrnlen((wchar_t *)temp, 4133 - data_count); 4134 - } else { 4135 - name_len += strnlen(temp, data_count); 4136 - } 4137 - referrals++; 4138 - /* BB add check that referral pointer does 4139 - not fall off end PDU */ 4140 - } 4141 - /* BB add check for name_len bigger than bcc */ 4142 - *targetUNCs = 4143 - kmalloc(name_len+1+(*number_of_UNC_in_array), 4144 - GFP_KERNEL); 4145 - if (*targetUNCs == NULL) { 4146 - rc = -ENOMEM; 4147 - goto GetDFSRefExit; 4148 - } 4149 - /* copy the ref strings */ 4150 - referrals = (struct dfs_referral_level_3 *) 4151 - (8 /* sizeof data hdr */ + data_offset + 4152 - (char *) &pSMBr->hdr.Protocol); 4153 - 4154 - for (i = 0; i < *number_of_UNC_in_array; i++) { 4155 - temp = ((char *)referrals) + 4156 - le16_to_cpu(referrals->DfsPathOffset); 4157 - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { 4158 - cifs_strfromUCS_le(*targetUNCs, 4159 - (__le16 *) temp, 4160 - name_len, 4161 - nls_codepage); 4162 - } else { 4163 - strncpy(*targetUNCs, temp, name_len); 4164 - } 4165 - /* BB update target_uncs pointers */ 4166 - referrals++; 4167 - } 4168 - temp = *targetUNCs; 4169 - temp[name_len] = 0; 4170 - } 4171 - 3946 + goto GetDFSRefExit; 4172 3947 } 3948 + rc = validate_t2((struct smb_t2_rsp *)pSMBr); 3949 + 3950 + /* BB Also check if enough total bytes returned? */ 3951 + if (rc || (pSMBr->ByteCount < 17)) { 3952 + rc = -EIO; /* bad smb */ 3953 + goto GetDFSRefExit; 3954 + } 3955 + 3956 + cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d", 3957 + pSMBr->ByteCount, 3958 + le16_to_cpu(pSMBr->t2.DataOffset))); 3959 + 3960 + /* parse returned result into more usable form */ 3961 + rc = parse_DFS_referrals(pSMBr, num_of_nodes, 3962 + target_nodes, nls_codepage); 3963 + 4173 3964 GetDFSRefExit: 4174 3965 if (pSMB) 4175 3966 cifs_buf_release(pSMB); ··· 4286 4229 params = 2; /* level */ 4287 4230 pSMB->TotalDataCount = 0; 4288 4231 pSMB->MaxParameterCount = cpu_to_le16(2); 4289 - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ 4232 + /* BB find exact max SMB PDU from sess structure BB */ 4233 + pSMB->MaxDataCount = cpu_to_le16(1000); 4290 4234 pSMB->MaxSetupCount = 0; 4291 4235 pSMB->Reserved = 0; 4292 4236 pSMB->Flags = 0; ··· 4356 4298 params = 2; /* level */ 4357 4299 pSMB->TotalDataCount = 0; 4358 4300 pSMB->MaxParameterCount = cpu_to_le16(2); 4359 - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ 4301 + /* BB find exact max SMB PDU from sess structure BB */ 4302 + pSMB->MaxDataCount = cpu_to_le16(1000); 4360 4303 pSMB->MaxSetupCount = 0; 4361 4304 pSMB->Reserved = 0; 4362 4305 pSMB->Flags = 0; ··· 4428 4369 pSMB->DataCount = 0; 4429 4370 pSMB->DataOffset = 0; 4430 4371 pSMB->MaxParameterCount = cpu_to_le16(2); 4431 - pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ 4372 + /* BB find exact max SMB PDU from sess structure BB */ 4373 + pSMB->MaxDataCount = cpu_to_le16(100); 4432 4374 pSMB->MaxSetupCount = 0; 4433 4375 pSMB->Reserved = 0; 4434 4376 pSMB->Flags = 0; ··· 4504 4444 offset = param_offset + params; 4505 4445 4506 4446 pSMB->MaxParameterCount = cpu_to_le16(4); 4507 - pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ 4447 + /* BB find exact max SMB PDU from sess structure BB */ 4448 + pSMB->MaxDataCount = cpu_to_le16(100); 4508 4449 pSMB->SetupCount = 1; 4509 4450 pSMB->Reserved3 = 0; 4510 4451 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION); ··· 4573 4512 pSMB->DataCount = 0; 4574 4513 pSMB->DataOffset = 0; 4575 4514 pSMB->MaxParameterCount = cpu_to_le16(2); 4576 - pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */ 4515 + /* BB find exact max SMB PDU from sess structure BB */ 4516 + pSMB->MaxDataCount = cpu_to_le16(100); 4577 4517 pSMB->MaxSetupCount = 0; 4578 4518 pSMB->Reserved = 0; 4579 4519 pSMB->Flags = 0; ··· 4764 4702 4765 4703 count = sizeof(struct file_end_of_file_info); 4766 4704 pSMB->MaxParameterCount = cpu_to_le16(2); 4767 - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ 4705 + /* BB find exact max SMB PDU from sess structure BB */ 4706 + pSMB->MaxDataCount = cpu_to_le16(1000); 4768 4707 pSMB->SetupCount = 1; 4769 4708 pSMB->Reserved3 = 0; 4770 4709 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); ··· 4852 4789 4853 4790 count = sizeof(FILE_BASIC_INFO); 4854 4791 pSMB->MaxParameterCount = cpu_to_le16(2); 4855 - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ 4792 + /* BB find max SMB PDU from sess */ 4793 + pSMB->MaxDataCount = cpu_to_le16(1000); 4856 4794 pSMB->SetupCount = 1; 4857 4795 pSMB->Reserved3 = 0; 4858 4796 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); ··· 4920 4856 params = 6 + name_len; 4921 4857 count = sizeof(FILE_BASIC_INFO); 4922 4858 pSMB->MaxParameterCount = cpu_to_le16(2); 4923 - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ 4859 + /* BB find max SMB PDU from sess structure BB */ 4860 + pSMB->MaxDataCount = cpu_to_le16(1000); 4924 4861 pSMB->MaxSetupCount = 0; 4925 4862 pSMB->Reserved = 0; 4926 4863 pSMB->Flags = 0; ··· 5051 4986 params = 6 + name_len; 5052 4987 count = sizeof(FILE_UNIX_BASIC_INFO); 5053 4988 pSMB->MaxParameterCount = cpu_to_le16(2); 5054 - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ 4989 + /* BB find max SMB PDU from sess structure BB */ 4990 + pSMB->MaxDataCount = cpu_to_le16(1000); 5055 4991 pSMB->MaxSetupCount = 0; 5056 4992 pSMB->Reserved = 0; 5057 4993 pSMB->Flags = 0; ··· 5235 5169 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; 5236 5170 pSMB->TotalDataCount = 0; 5237 5171 pSMB->MaxParameterCount = cpu_to_le16(2); 5238 - pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ 5172 + /* BB find exact max SMB PDU from sess structure BB */ 5173 + pSMB->MaxDataCount = cpu_to_le16(4000); 5239 5174 pSMB->MaxSetupCount = 0; 5240 5175 pSMB->Reserved = 0; 5241 5176 pSMB->Flags = 0; ··· 5384 5317 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; 5385 5318 pSMB->TotalDataCount = 0; 5386 5319 pSMB->MaxParameterCount = cpu_to_le16(2); 5387 - pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */ 5320 + /* BB find exact max SMB PDU from sess structure BB */ 5321 + pSMB->MaxDataCount = cpu_to_le16(4000); 5388 5322 pSMB->MaxSetupCount = 0; 5389 5323 pSMB->Reserved = 0; 5390 5324 pSMB->Flags = 0; ··· 5543 5475 5544 5476 count = sizeof(*parm_data) + ea_value_len + name_len; 5545 5477 pSMB->MaxParameterCount = cpu_to_le16(2); 5546 - pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ 5478 + /* BB find max SMB PDU from sess */ 5479 + pSMB->MaxDataCount = cpu_to_le16(1000); 5547 5480 pSMB->MaxSetupCount = 0; 5548 5481 pSMB->Reserved = 0; 5549 5482 pSMB->Flags = 0;
+32 -36
fs/cifs/connect.c
··· 60 60 char *domainname; 61 61 char *UNC; 62 62 char *UNCip; 63 - char *in6_addr; /* ipv6 address as human readable form of in6_addr */ 63 + char *in6_addr; /* ipv6 address as human readable form of in6_addr */ 64 64 char *iocharset; /* local code page for mapping to and from Unicode */ 65 65 char source_rfc1001_name[16]; /* netbios name of client */ 66 66 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ ··· 75 75 bool setuids:1; 76 76 bool override_uid:1; 77 77 bool override_gid:1; 78 + bool dynperm:1; 78 79 bool noperm:1; 79 80 bool no_psx_acl:1; /* set if posix acl support should be disabled */ 80 81 bool cifs_acl:1; 81 82 bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ 82 83 bool server_ino:1; /* use inode numbers from server ie UniqueId */ 83 84 bool direct_io:1; 84 - bool remap:1; /* set to remap seven reserved chars in filenames */ 85 - bool posix_paths:1; /* unset to not ask for posix pathnames. */ 85 + bool remap:1; /* set to remap seven reserved chars in filenames */ 86 + bool posix_paths:1; /* unset to not ask for posix pathnames. */ 86 87 bool no_linux_ext:1; 87 88 bool sfu_emul:1; 88 - bool nullauth:1; /* attempt to authenticate with null user */ 89 - unsigned nocase; /* request case insensitive filenames */ 90 - unsigned nobrl; /* disable sending byte range locks to srv */ 89 + bool nullauth:1; /* attempt to authenticate with null user */ 90 + bool nocase:1; /* request case insensitive filenames */ 91 + bool nobrl:1; /* disable sending byte range locks to srv */ 92 + bool seal:1; /* request transport encryption on share */ 91 93 unsigned int rsize; 92 94 unsigned int wsize; 93 95 unsigned int sockopt; ··· 1248 1246 vol->setuids = 1; 1249 1247 } else if (strnicmp(data, "nosetuids", 9) == 0) { 1250 1248 vol->setuids = 0; 1249 + } else if (strnicmp(data, "dynperm", 7) == 0) { 1250 + vol->dynperm = true; 1251 + } else if (strnicmp(data, "nodynperm", 9) == 0) { 1252 + vol->dynperm = false; 1251 1253 } else if (strnicmp(data, "nohard", 6) == 0) { 1252 1254 vol->retry = 0; 1253 1255 } else if (strnicmp(data, "nosoft", 6) == 0) { ··· 1274 1268 vol->no_psx_acl = 1; 1275 1269 } else if (strnicmp(data, "sign", 4) == 0) { 1276 1270 vol->secFlg |= CIFSSEC_MUST_SIGN; 1277 - /* } else if (strnicmp(data, "seal",4) == 0) { 1278 - vol->secFlg |= CIFSSEC_MUST_SEAL; */ 1271 + } else if (strnicmp(data, "seal", 4) == 0) { 1272 + /* we do not do the following in secFlags because seal 1273 + is a per tree connection (mount) not a per socket 1274 + or per-smb connection option in the protocol */ 1275 + /* vol->secFlg |= CIFSSEC_MUST_SEAL; */ 1276 + vol->seal = 1; 1279 1277 } else if (strnicmp(data, "direct", 6) == 0) { 1280 1278 vol->direct_io = 1; 1281 1279 } else if (strnicmp(data, "forcedirectio", 13) == 0) { ··· 1424 1414 } 1425 1415 1426 1416 int 1427 - connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, 1428 - const char *old_path, const struct nls_table *nls_codepage, 1429 - int remap) 1430 - { 1431 - struct dfs_info3_param *referrals = NULL; 1432 - unsigned int num_referrals; 1433 - int rc = 0; 1434 - 1435 - rc = get_dfs_path(xid, pSesInfo, old_path, nls_codepage, 1436 - &num_referrals, &referrals, remap); 1437 - 1438 - /* BB Add in code to: if valid refrl, if not ip address contact 1439 - the helper that resolves tcp names, mount to it, try to 1440 - tcon to it unmount it if fail */ 1441 - 1442 - kfree(referrals); 1443 - 1444 - return rc; 1445 - } 1446 - 1447 - int 1448 1417 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, 1449 1418 const struct nls_table *nls_codepage, unsigned int *pnum_referrals, 1450 1419 struct dfs_info3_param **preferrals, int remap) 1451 1420 { 1452 1421 char *temp_unc; 1453 1422 int rc = 0; 1454 - unsigned char *targetUNCs; 1455 1423 1456 1424 *pnum_referrals = 0; 1457 1425 *preferrals = NULL; ··· 1452 1464 kfree(temp_unc); 1453 1465 } 1454 1466 if (rc == 0) 1455 - rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, &targetUNCs, 1467 + rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, 1456 1468 pnum_referrals, nls_codepage, remap); 1457 1469 /* BB map targetUNCs to dfs_info3 structures, here or 1458 1470 in CIFSGetDFSRefer BB */ ··· 1803 1815 if (path == NULL) 1804 1816 return; 1805 1817 1806 - if (delim == '/') 1818 + if (delim == '/') 1807 1819 old_delim = '\\'; 1808 1820 else 1809 1821 old_delim = '/'; ··· 2113 2125 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; 2114 2126 if (volume_info.override_gid) 2115 2127 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; 2128 + if (volume_info.dynperm) 2129 + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; 2116 2130 if (volume_info.direct_io) { 2117 2131 cFYI(1, ("mounting share using direct i/o")); 2118 2132 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; ··· 2131 2141 for the retry flag is used */ 2132 2142 tcon->retry = volume_info.retry; 2133 2143 tcon->nocase = volume_info.nocase; 2144 + if (tcon->seal != volume_info.seal) 2145 + cERROR(1, ("transport encryption setting " 2146 + "conflicts with existing tid")); 2134 2147 } else { 2135 2148 tcon = tconInfoAlloc(); 2136 2149 if (tcon == NULL) ··· 2147 2154 if ((strchr(volume_info.UNC + 3, '\\') == NULL) 2148 2155 && (strchr(volume_info.UNC + 3, '/') == 2149 2156 NULL)) { 2150 - rc = connect_to_dfs_path(xid, pSesInfo, 2157 + /* rc = connect_to_dfs_path(xid, pSesInfo, 2151 2158 "", cifs_sb->local_nls, 2152 2159 cifs_sb->mnt_cifs_flags & 2153 - CIFS_MOUNT_MAP_SPECIAL_CHR); 2160 + CIFS_MOUNT_MAP_SPECIAL_CHR);*/ 2161 + cFYI(1, ("DFS root not supported")); 2154 2162 rc = -ENODEV; 2155 2163 goto out; 2156 2164 } else { ··· 2167 2173 atomic_inc(&pSesInfo->inUse); 2168 2174 tcon->retry = volume_info.retry; 2169 2175 tcon->nocase = volume_info.nocase; 2176 + tcon->seal = volume_info.seal; 2170 2177 } 2171 2178 } 2172 2179 } ··· 2309 2314 user = ses->userName; 2310 2315 domain = ses->domainName; 2311 2316 smb_buffer = cifs_buf_get(); 2312 - if (smb_buffer == NULL) { 2317 + 2318 + if (smb_buffer == NULL) 2313 2319 return -ENOMEM; 2314 - } 2320 + 2315 2321 smb_buffer_response = smb_buffer; 2316 2322 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; 2317 2323
+24 -6
fs/cifs/dir.c
··· 49 49 struct dentry *temp; 50 50 int namelen; 51 51 int pplen; 52 + int dfsplen; 52 53 char *full_path; 53 54 char dirsep; 55 + struct cifs_sb_info *cifs_sb; 54 56 55 57 if (direntry == NULL) 56 58 return NULL; /* not much we can do if dentry is freed and 57 59 we need to reopen the file after it was closed implicitly 58 60 when the server crashed */ 59 61 60 - dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); 61 - pplen = CIFS_SB(direntry->d_sb)->prepathlen; 62 + cifs_sb = CIFS_SB(direntry->d_sb); 63 + dirsep = CIFS_DIR_SEP(cifs_sb); 64 + pplen = cifs_sb->prepathlen; 65 + if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS)) 66 + dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1); 67 + else 68 + dfsplen = 0; 62 69 cifs_bp_rename_retry: 63 - namelen = pplen; 70 + namelen = pplen + dfsplen; 64 71 for (temp = direntry; !IS_ROOT(temp);) { 65 72 namelen += (1 + temp->d_name.len); 66 73 temp = temp->d_parent; ··· 98 91 return NULL; 99 92 } 100 93 } 101 - if (namelen != pplen) { 94 + if (namelen != pplen + dfsplen) { 102 95 cERROR(1, 103 96 ("did not end path lookup where expected namelen is %d", 104 97 namelen)); ··· 114 107 since the '\' is a valid posix character so we can not switch 115 108 those safely to '/' if any are found in the middle of the prepath */ 116 109 /* BB test paths to Windows with '/' in the midst of prepath */ 117 - strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen); 110 + 111 + if (dfsplen) { 112 + strncpy(full_path, cifs_sb->tcon->treeName, dfsplen); 113 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { 114 + int i; 115 + for (i = 0; i < dfsplen; i++) { 116 + if (full_path[i] == '\\') 117 + full_path[i] = '/'; 118 + } 119 + } 120 + } 121 + strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen); 118 122 return full_path; 119 123 } 120 124 ··· 608 590 * case take precedence. If a is not a negative dentry, this 609 591 * should have no side effects 610 592 */ 611 - memcpy(a->name, b->name, a->len); 593 + memcpy((void *)a->name, b->name, a->len); 612 594 return 0; 613 595 } 614 596 return 1;
+5 -4
fs/cifs/dns_resolve.c
··· 134 134 rkey = request_key(&key_type_dns_resolver, name, ""); 135 135 if (!IS_ERR(rkey)) { 136 136 data = rkey->payload.data; 137 - cFYI(1, ("%s: resolved: %s to %s", __func__, 138 - rkey->description, 139 - *ip_addr 140 - )); 141 137 } else { 142 138 cERROR(1, ("%s: unable to resolve: %s", __func__, name)); 143 139 goto out; ··· 146 150 if (*ip_addr) { 147 151 memcpy(*ip_addr, data, len); 148 152 (*ip_addr)[len] = '\0'; 153 + if (!IS_ERR(rkey)) 154 + cFYI(1, ("%s: resolved: %s to %s", __func__, 155 + name, 156 + *ip_addr 157 + )); 149 158 rc = 0; 150 159 } else { 151 160 rc = -ENOMEM;
+5 -1
fs/cifs/file.c
··· 75 75 return (GENERIC_READ | GENERIC_WRITE); 76 76 } 77 77 78 - return 0x20197; 78 + return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | 79 + FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | 80 + FILE_READ_DATA); 81 + 82 + 79 83 } 80 84 81 85 static inline int cifs_get_disposition(unsigned int flags)
+268 -255
fs/cifs/inode.c
··· 161 161 spin_unlock(&inode->i_lock); 162 162 } 163 163 164 - static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb, 165 - const char *search_path) 164 + 165 + /* 166 + * Needed to setup inode data for the directory which is the 167 + * junction to the new submount (ie to setup the fake directory 168 + * which represents a DFS referral) 169 + */ 170 + static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, 171 + struct super_block *sb) 166 172 { 167 - int tree_len; 168 - int path_len; 169 - int i; 170 - char *tmp_path; 171 - struct cifsTconInfo *pTcon = cifs_sb->tcon; 173 + struct inode *pinode = NULL; 172 174 173 - if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) 174 - return search_path; 175 + memset(pfnd_dat, sizeof(FILE_UNIX_BASIC_INFO), 0); 175 176 176 - /* use full path name for working with DFS */ 177 - tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); 178 - path_len = strnlen(search_path, MAX_PATHCONF); 177 + /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); 178 + __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); 179 + __u64 UniqueId = 0; */ 180 + pfnd_dat->LastStatusChange = 181 + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 182 + pfnd_dat->LastAccessTime = 183 + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 184 + pfnd_dat->LastModificationTime = 185 + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 186 + pfnd_dat->Type = cpu_to_le32(UNIX_DIR); 187 + pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU); 188 + pfnd_dat->Nlinks = cpu_to_le64(2); 189 + if (sb->s_root) 190 + pinode = sb->s_root->d_inode; 191 + if (pinode == NULL) 192 + return; 179 193 180 - tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); 181 - if (tmp_path == NULL) 182 - return search_path; 183 - 184 - strncpy(tmp_path, pTcon->treeName, tree_len); 185 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 186 - for (i = 0; i < tree_len; i++) { 187 - if (tmp_path[i] == '\\') 188 - tmp_path[i] = '/'; 189 - } 190 - strncpy(tmp_path+tree_len, search_path, path_len); 191 - tmp_path[tree_len+path_len] = 0; 192 - return tmp_path; 194 + /* fill in default values for the remaining based on root 195 + inode since we can not query the server for this inode info */ 196 + pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev)); 197 + pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev)); 198 + pfnd_dat->Uid = cpu_to_le64(pinode->i_uid); 199 + pfnd_dat->Gid = cpu_to_le64(pinode->i_gid); 193 200 } 194 201 195 202 int cifs_get_inode_info_unix(struct inode **pinode, 196 - const unsigned char *search_path, struct super_block *sb, int xid) 203 + const unsigned char *full_path, struct super_block *sb, int xid) 197 204 { 198 205 int rc = 0; 199 - FILE_UNIX_BASIC_INFO findData; 206 + FILE_UNIX_BASIC_INFO find_data; 200 207 struct cifsTconInfo *pTcon; 201 208 struct inode *inode; 202 209 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 203 - const unsigned char *full_path; 204 210 bool is_dfs_referral = false; 211 + struct cifsInodeInfo *cifsInfo; 212 + __u64 num_of_bytes; 213 + __u64 end_of_file; 205 214 206 215 pTcon = cifs_sb->tcon; 207 - cFYI(1, ("Getting info on %s", search_path)); 216 + cFYI(1, ("Getting info on %s", full_path)); 208 217 209 - full_path = cifs_get_search_path(cifs_sb, search_path); 210 - 211 - try_again_CIFSSMBUnixQPathInfo: 212 218 /* could have done a find first instead but this returns more info */ 213 - rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, 219 + rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data, 214 220 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 215 221 CIFS_MOUNT_MAP_SPECIAL_CHR); 216 - /* dump_mem("\nUnixQPathInfo return data", &findData, 217 - sizeof(findData)); */ 218 222 if (rc) { 219 223 if (rc == -EREMOTE && !is_dfs_referral) { 220 224 is_dfs_referral = true; 221 - if (full_path != search_path) { 222 - kfree(full_path); 223 - full_path = search_path; 224 - } 225 - goto try_again_CIFSSMBUnixQPathInfo; 225 + cFYI(DBG2, ("DFS ref")); 226 + /* for DFS, server does not give us real inode data */ 227 + fill_fake_finddataunix(&find_data, sb); 228 + rc = 0; 226 229 } 227 - goto cgiiu_exit; 228 - } else { 229 - struct cifsInodeInfo *cifsInfo; 230 - __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); 231 - __u64 end_of_file = le64_to_cpu(findData.EndOfFile); 232 - 233 - /* get new inode */ 234 - if (*pinode == NULL) { 235 - *pinode = new_inode(sb); 236 - if (*pinode == NULL) { 237 - rc = -ENOMEM; 238 - goto cgiiu_exit; 239 - } 240 - /* Is an i_ino of zero legal? */ 241 - /* Are there sanity checks we can use to ensure that 242 - the server is really filling in that field? */ 243 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 244 - (*pinode)->i_ino = 245 - (unsigned long)findData.UniqueId; 246 - } /* note ino incremented to unique num in new_inode */ 247 - if (sb->s_flags & MS_NOATIME) 248 - (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; 249 - 250 - insert_inode_hash(*pinode); 251 - } 252 - 253 - inode = *pinode; 254 - cifsInfo = CIFS_I(inode); 255 - 256 - cFYI(1, ("Old time %ld", cifsInfo->time)); 257 - cifsInfo->time = jiffies; 258 - cFYI(1, ("New time %ld", cifsInfo->time)); 259 - /* this is ok to set on every inode revalidate */ 260 - atomic_set(&cifsInfo->inUse, 1); 261 - 262 - cifs_unix_info_to_inode(inode, &findData, 0); 263 - 264 - 265 - if (num_of_bytes < end_of_file) 266 - cFYI(1, ("allocation size less than end of file")); 267 - cFYI(1, ("Size %ld and blocks %llu", 268 - (unsigned long) inode->i_size, 269 - (unsigned long long)inode->i_blocks)); 270 - 271 - cifs_set_ops(inode, is_dfs_referral); 272 230 } 231 + num_of_bytes = le64_to_cpu(find_data.NumOfBytes); 232 + end_of_file = le64_to_cpu(find_data.EndOfFile); 233 + 234 + /* get new inode */ 235 + if (*pinode == NULL) { 236 + *pinode = new_inode(sb); 237 + if (*pinode == NULL) { 238 + rc = -ENOMEM; 239 + goto cgiiu_exit; 240 + } 241 + /* Is an i_ino of zero legal? */ 242 + /* note ino incremented to unique num in new_inode */ 243 + /* Are there sanity checks we can use to ensure that 244 + the server is really filling in that field? */ 245 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 246 + (*pinode)->i_ino = (unsigned long)find_data.UniqueId; 247 + 248 + if (sb->s_flags & MS_NOATIME) 249 + (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; 250 + 251 + insert_inode_hash(*pinode); 252 + } 253 + 254 + inode = *pinode; 255 + cifsInfo = CIFS_I(inode); 256 + 257 + cFYI(1, ("Old time %ld", cifsInfo->time)); 258 + cifsInfo->time = jiffies; 259 + cFYI(1, ("New time %ld", cifsInfo->time)); 260 + /* this is ok to set on every inode revalidate */ 261 + atomic_set(&cifsInfo->inUse, 1); 262 + 263 + cifs_unix_info_to_inode(inode, &find_data, 0); 264 + 265 + if (num_of_bytes < end_of_file) 266 + cFYI(1, ("allocation size less than end of file")); 267 + cFYI(1, ("Size %ld and blocks %llu", 268 + (unsigned long) inode->i_size, 269 + (unsigned long long)inode->i_blocks)); 270 + 271 + cifs_set_ops(inode, is_dfs_referral); 273 272 cgiiu_exit: 274 - if (full_path != search_path) 275 - kfree(full_path); 276 273 return rc; 277 274 } 278 275 ··· 376 379 #endif 377 380 } 378 381 382 + /* 383 + * Needed to setup inode data for the directory which is the 384 + * junction to the new submount (ie to setup the fake directory 385 + * which represents a DFS referral) 386 + */ 387 + static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, 388 + struct super_block *sb) 389 + { 390 + memset(pfnd_dat, sizeof(FILE_ALL_INFO), 0); 391 + 392 + /* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); 393 + __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); 394 + __u8 pfnd_dat->DeletePending = 0; 395 + __u8 pfnd_data->Directory = 0; 396 + __le32 pfnd_dat->EASize = 0; 397 + __u64 pfnd_dat->IndexNumber = 0; 398 + __u64 pfnd_dat->IndexNumber1 = 0; */ 399 + pfnd_dat->CreationTime = 400 + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 401 + pfnd_dat->LastAccessTime = 402 + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 403 + pfnd_dat->LastWriteTime = 404 + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 405 + pfnd_dat->ChangeTime = 406 + cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 407 + pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); 408 + pfnd_dat->NumberOfLinks = cpu_to_le32(2); 409 + } 410 + 379 411 int cifs_get_inode_info(struct inode **pinode, 380 - const unsigned char *search_path, FILE_ALL_INFO *pfindData, 412 + const unsigned char *full_path, FILE_ALL_INFO *pfindData, 381 413 struct super_block *sb, int xid, const __u16 *pfid) 382 414 { 383 415 int rc = 0; 416 + __u32 attr; 417 + struct cifsInodeInfo *cifsInfo; 384 418 struct cifsTconInfo *pTcon; 385 419 struct inode *inode; 386 420 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 387 - const unsigned char *full_path = NULL; 388 421 char *buf = NULL; 389 422 bool adjustTZ = false; 390 423 bool is_dfs_referral = false; 391 424 392 425 pTcon = cifs_sb->tcon; 393 - cFYI(1, ("Getting info on %s", search_path)); 426 + cFYI(1, ("Getting info on %s", full_path)); 394 427 395 428 if ((pfindData == NULL) && (*pinode != NULL)) { 396 429 if (CIFS_I(*pinode)->clientCanCacheRead) { ··· 436 409 return -ENOMEM; 437 410 pfindData = (FILE_ALL_INFO *)buf; 438 411 439 - full_path = cifs_get_search_path(cifs_sb, search_path); 440 - 441 - try_again_CIFSSMBQPathInfo: 442 412 /* could do find first instead but this returns more info */ 443 413 rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, 444 414 0 /* not legacy */, ··· 453 429 } 454 430 } 455 431 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 456 - if (rc) { 457 - if (rc == -EREMOTE && !is_dfs_referral) { 458 - is_dfs_referral = true; 459 - if (full_path != search_path) { 460 - kfree(full_path); 461 - full_path = search_path; 462 - } 463 - goto try_again_CIFSSMBQPathInfo; 464 - } 432 + if (rc == -EREMOTE) { 433 + is_dfs_referral = true; 434 + fill_fake_finddata(pfindData, sb); 435 + rc = 0; 436 + } else if (rc) 465 437 goto cgii_exit; 466 - } else { 467 - struct cifsInodeInfo *cifsInfo; 468 - __u32 attr = le32_to_cpu(pfindData->Attributes); 469 438 470 - /* get new inode */ 439 + attr = le32_to_cpu(pfindData->Attributes); 440 + 441 + /* get new inode */ 442 + if (*pinode == NULL) { 443 + *pinode = new_inode(sb); 471 444 if (*pinode == NULL) { 472 - *pinode = new_inode(sb); 473 - if (*pinode == NULL) { 474 - rc = -ENOMEM; 475 - goto cgii_exit; 476 - } 477 - /* Is an i_ino of zero legal? Can we use that to check 478 - if the server supports returning inode numbers? Are 479 - there other sanity checks we can use to ensure that 480 - the server is really filling in that field? */ 445 + rc = -ENOMEM; 446 + goto cgii_exit; 447 + } 448 + /* Is an i_ino of zero legal? Can we use that to check 449 + if the server supports returning inode numbers? Are 450 + there other sanity checks we can use to ensure that 451 + the server is really filling in that field? */ 481 452 482 - /* We can not use the IndexNumber field by default from 483 - Windows or Samba (in ALL_INFO buf) but we can request 484 - it explicitly. It may not be unique presumably if 485 - the server has multiple devices mounted under one 486 - share */ 453 + /* We can not use the IndexNumber field by default from 454 + Windows or Samba (in ALL_INFO buf) but we can request 455 + it explicitly. It may not be unique presumably if 456 + the server has multiple devices mounted under one share */ 487 457 488 - /* There may be higher info levels that work but are 489 - there Windows server or network appliances for which 490 - IndexNumber field is not guaranteed unique? */ 458 + /* There may be higher info levels that work but are 459 + there Windows server or network appliances for which 460 + IndexNumber field is not guaranteed unique? */ 491 461 492 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 493 - int rc1 = 0; 494 - __u64 inode_num; 462 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 463 + int rc1 = 0; 464 + __u64 inode_num; 495 465 496 - rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 497 - search_path, &inode_num, 466 + rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 467 + full_path, &inode_num, 498 468 cifs_sb->local_nls, 499 469 cifs_sb->mnt_cifs_flags & 500 470 CIFS_MOUNT_MAP_SPECIAL_CHR); 501 - if (rc1) { 502 - cFYI(1, ("GetSrvInodeNum rc %d", rc1)); 503 - /* BB EOPNOSUPP disable SERVER_INUM? */ 504 - } else /* do we need cast or hash to ino? */ 505 - (*pinode)->i_ino = inode_num; 506 - } /* else ino incremented to unique num in new_inode*/ 507 - if (sb->s_flags & MS_NOATIME) 508 - (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; 509 - insert_inode_hash(*pinode); 510 - } 511 - inode = *pinode; 512 - cifsInfo = CIFS_I(inode); 513 - cifsInfo->cifsAttrs = attr; 514 - cFYI(1, ("Old time %ld", cifsInfo->time)); 515 - cifsInfo->time = jiffies; 516 - cFYI(1, ("New time %ld", cifsInfo->time)); 517 - 518 - /* blksize needs to be multiple of two. So safer to default to 519 - blksize and blkbits set in superblock so 2**blkbits and blksize 520 - will match rather than setting to: 521 - (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ 522 - 523 - /* Linux can not store file creation time so ignore it */ 524 - if (pfindData->LastAccessTime) 525 - inode->i_atime = cifs_NTtimeToUnix 526 - (le64_to_cpu(pfindData->LastAccessTime)); 527 - else /* do not need to use current_fs_time - time not stored */ 528 - inode->i_atime = CURRENT_TIME; 529 - inode->i_mtime = 530 - cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 531 - inode->i_ctime = 532 - cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 533 - cFYI(0, ("Attributes came in as 0x%x", attr)); 534 - if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { 535 - inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; 536 - inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; 537 - } 538 - 539 - /* set default mode. will override for dirs below */ 540 - if (atomic_read(&cifsInfo->inUse) == 0) 541 - /* new inode, can safely set these fields */ 542 - inode->i_mode = cifs_sb->mnt_file_mode; 543 - else /* since we set the inode type below we need to mask off 544 - to avoid strange results if type changes and both 545 - get orred in */ 546 - inode->i_mode &= ~S_IFMT; 547 - /* if (attr & ATTR_REPARSE) */ 548 - /* We no longer handle these as symlinks because we could not 549 - follow them due to the absolute path with drive letter */ 550 - if (attr & ATTR_DIRECTORY) { 551 - /* override default perms since we do not do byte range locking 552 - on dirs */ 553 - inode->i_mode = cifs_sb->mnt_dir_mode; 554 - inode->i_mode |= S_IFDIR; 555 - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 556 - (cifsInfo->cifsAttrs & ATTR_SYSTEM) && 557 - /* No need to le64 convert size of zero */ 558 - (pfindData->EndOfFile == 0)) { 559 - inode->i_mode = cifs_sb->mnt_file_mode; 560 - inode->i_mode |= S_IFIFO; 561 - /* BB Finish for SFU style symlinks and devices */ 562 - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 563 - (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { 564 - if (decode_sfu_inode(inode, 565 - le64_to_cpu(pfindData->EndOfFile), 566 - search_path, 567 - cifs_sb, xid)) 568 - cFYI(1, ("Unrecognized sfu inode type")); 569 - 570 - cFYI(1, ("sfu mode 0%o", inode->i_mode)); 571 - } else { 572 - inode->i_mode |= S_IFREG; 573 - /* treat the dos attribute of read-only as read-only 574 - mode e.g. 555 */ 575 - if (cifsInfo->cifsAttrs & ATTR_READONLY) 576 - inode->i_mode &= ~(S_IWUGO); 577 - else if ((inode->i_mode & S_IWUGO) == 0) 578 - /* the ATTR_READONLY flag may have been */ 579 - /* changed on server -- set any w bits */ 580 - /* allowed by mnt_file_mode */ 581 - inode->i_mode |= (S_IWUGO & 582 - cifs_sb->mnt_file_mode); 583 - /* BB add code here - 584 - validate if device or weird share or device type? */ 585 - } 586 - 587 - spin_lock(&inode->i_lock); 588 - if (is_size_safe_to_change(cifsInfo, 589 - le64_to_cpu(pfindData->EndOfFile))) { 590 - /* can not safely shrink the file size here if the 591 - client is writing to it due to potential races */ 592 - i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); 593 - 594 - /* 512 bytes (2**9) is the fake blocksize that must be 595 - used for this calculation */ 596 - inode->i_blocks = (512 - 1 + le64_to_cpu( 597 - pfindData->AllocationSize)) >> 9; 598 - } 599 - spin_unlock(&inode->i_lock); 600 - 601 - inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); 602 - 603 - /* BB fill in uid and gid here? with help from winbind? 604 - or retrieve from NTFS stream extended attribute */ 605 - #ifdef CONFIG_CIFS_EXPERIMENTAL 606 - /* fill in 0777 bits from ACL */ 607 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 608 - cFYI(1, ("Getting mode bits from ACL")); 609 - acl_to_uid_mode(inode, search_path, pfid); 610 - } 611 - #endif 612 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { 613 - /* fill in remaining high mode bits e.g. SUID, VTX */ 614 - get_sfu_mode(inode, search_path, cifs_sb, xid); 615 - } else if (atomic_read(&cifsInfo->inUse) == 0) { 616 - inode->i_uid = cifs_sb->mnt_uid; 617 - inode->i_gid = cifs_sb->mnt_gid; 618 - /* set so we do not keep refreshing these fields with 619 - bad data after user has changed them in memory */ 620 - atomic_set(&cifsInfo->inUse, 1); 621 - } 622 - 623 - cifs_set_ops(inode, is_dfs_referral); 471 + if (rc1) { 472 + cFYI(1, ("GetSrvInodeNum rc %d", rc1)); 473 + /* BB EOPNOSUPP disable SERVER_INUM? */ 474 + } else /* do we need cast or hash to ino? */ 475 + (*pinode)->i_ino = inode_num; 476 + } /* else ino incremented to unique num in new_inode*/ 477 + if (sb->s_flags & MS_NOATIME) 478 + (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; 479 + insert_inode_hash(*pinode); 624 480 } 481 + inode = *pinode; 482 + cifsInfo = CIFS_I(inode); 483 + cifsInfo->cifsAttrs = attr; 484 + cFYI(1, ("Old time %ld", cifsInfo->time)); 485 + cifsInfo->time = jiffies; 486 + cFYI(1, ("New time %ld", cifsInfo->time)); 487 + 488 + /* blksize needs to be multiple of two. So safer to default to 489 + blksize and blkbits set in superblock so 2**blkbits and blksize 490 + will match rather than setting to: 491 + (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ 492 + 493 + /* Linux can not store file creation time so ignore it */ 494 + if (pfindData->LastAccessTime) 495 + inode->i_atime = cifs_NTtimeToUnix 496 + (le64_to_cpu(pfindData->LastAccessTime)); 497 + else /* do not need to use current_fs_time - time not stored */ 498 + inode->i_atime = CURRENT_TIME; 499 + inode->i_mtime = 500 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 501 + inode->i_ctime = 502 + cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 503 + cFYI(DBG2, ("Attributes came in as 0x%x", attr)); 504 + if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { 505 + inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; 506 + inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; 507 + } 508 + 509 + /* set default mode. will override for dirs below */ 510 + if (atomic_read(&cifsInfo->inUse) == 0) 511 + /* new inode, can safely set these fields */ 512 + inode->i_mode = cifs_sb->mnt_file_mode; 513 + else /* since we set the inode type below we need to mask off 514 + to avoid strange results if type changes and both 515 + get orred in */ 516 + inode->i_mode &= ~S_IFMT; 517 + /* if (attr & ATTR_REPARSE) */ 518 + /* We no longer handle these as symlinks because we could not 519 + follow them due to the absolute path with drive letter */ 520 + if (attr & ATTR_DIRECTORY) { 521 + /* override default perms since we do not do byte range locking 522 + on dirs */ 523 + inode->i_mode = cifs_sb->mnt_dir_mode; 524 + inode->i_mode |= S_IFDIR; 525 + } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 526 + (cifsInfo->cifsAttrs & ATTR_SYSTEM) && 527 + /* No need to le64 convert size of zero */ 528 + (pfindData->EndOfFile == 0)) { 529 + inode->i_mode = cifs_sb->mnt_file_mode; 530 + inode->i_mode |= S_IFIFO; 531 + /* BB Finish for SFU style symlinks and devices */ 532 + } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 533 + (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { 534 + if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile), 535 + full_path, cifs_sb, xid)) 536 + cFYI(1, ("Unrecognized sfu inode type")); 537 + 538 + cFYI(1, ("sfu mode 0%o", inode->i_mode)); 539 + } else { 540 + inode->i_mode |= S_IFREG; 541 + /* treat dos attribute of read-only as read-only mode eg 555 */ 542 + if (cifsInfo->cifsAttrs & ATTR_READONLY) 543 + inode->i_mode &= ~(S_IWUGO); 544 + else if ((inode->i_mode & S_IWUGO) == 0) 545 + /* the ATTR_READONLY flag may have been */ 546 + /* changed on server -- set any w bits */ 547 + /* allowed by mnt_file_mode */ 548 + inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); 549 + /* BB add code to validate if device or weird share or device type? */ 550 + } 551 + 552 + spin_lock(&inode->i_lock); 553 + if (is_size_safe_to_change(cifsInfo, 554 + le64_to_cpu(pfindData->EndOfFile))) { 555 + /* can not safely shrink the file size here if the 556 + client is writing to it due to potential races */ 557 + i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); 558 + 559 + /* 512 bytes (2**9) is the fake blocksize that must be 560 + used for this calculation */ 561 + inode->i_blocks = (512 - 1 + le64_to_cpu( 562 + pfindData->AllocationSize)) >> 9; 563 + } 564 + spin_unlock(&inode->i_lock); 565 + 566 + inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); 567 + 568 + /* BB fill in uid and gid here? with help from winbind? 569 + or retrieve from NTFS stream extended attribute */ 570 + #ifdef CONFIG_CIFS_EXPERIMENTAL 571 + /* fill in 0777 bits from ACL */ 572 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 573 + cFYI(1, ("Getting mode bits from ACL")); 574 + acl_to_uid_mode(inode, full_path, pfid); 575 + } 576 + #endif 577 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { 578 + /* fill in remaining high mode bits e.g. SUID, VTX */ 579 + get_sfu_mode(inode, full_path, cifs_sb, xid); 580 + } else if (atomic_read(&cifsInfo->inUse) == 0) { 581 + inode->i_uid = cifs_sb->mnt_uid; 582 + inode->i_gid = cifs_sb->mnt_gid; 583 + /* set so we do not keep refreshing these fields with 584 + bad data after user has changed them in memory */ 585 + atomic_set(&cifsInfo->inUse, 1); 586 + } 587 + 588 + cifs_set_ops(inode, is_dfs_referral); 589 + 590 + 591 + 592 + 625 593 cgii_exit: 626 - if (full_path != search_path) 627 - kfree(full_path); 628 594 kfree(buf); 629 595 return rc; 630 596 } ··· 1516 1502 int oplock = 0; 1517 1503 1518 1504 rc = SMBLegacyOpen(xid, pTcon, full_path, 1519 - FILE_OPEN, 1520 - SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, 1505 + FILE_OPEN, GENERIC_WRITE, 1521 1506 CREATE_NOT_DIR, &netfid, &oplock, 1522 1507 NULL, cifs_sb->local_nls, 1523 1508 cifs_sb->mnt_cifs_flags &
+2 -2
fs/cifs/ioctl.c
··· 30 30 31 31 #define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) 32 32 33 - int cifs_ioctl(struct inode *inode, struct file *filep, 34 - unsigned int command, unsigned long arg) 33 + long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) 35 34 { 35 + struct inode *inode = filep->f_dentry->d_inode; 36 36 int rc = -ENOTTY; /* strange error - but the precedent */ 37 37 int xid; 38 38 struct cifs_sb_info *cifs_sb;
+3 -40
fs/cifs/link.c
··· 234 234 struct cifs_sb_info *cifs_sb; 235 235 struct cifsTconInfo *pTcon; 236 236 char *full_path = NULL; 237 - char *tmp_path = NULL; 238 237 char *tmpbuffer; 239 238 int len; 240 239 __u16 fid; ··· 294 295 cFYI(1, ("Error closing junction point " 295 296 "(open for ioctl)")); 296 297 } 297 - /* BB unwind this long, nested function, or remove BB */ 298 - if (rc == -EIO) { 299 - /* Query if DFS Junction */ 300 - unsigned int num_referrals = 0; 301 - struct dfs_info3_param *refs = NULL; 302 - tmp_path = 303 - kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1, 304 - GFP_KERNEL); 305 - if (tmp_path) { 306 - strncpy(tmp_path, pTcon->treeName, 307 - MAX_TREE_SIZE); 308 - strncat(tmp_path, full_path, 309 - MAX_PATHCONF); 310 - rc = get_dfs_path(xid, pTcon->ses, 311 - tmp_path, 312 - cifs_sb->local_nls, 313 - &num_referrals, &refs, 314 - cifs_sb->mnt_cifs_flags & 315 - CIFS_MOUNT_MAP_SPECIAL_CHR); 316 - cFYI(1, ("Get DFS for %s rc = %d ", 317 - tmp_path, rc)); 318 - if ((num_referrals == 0) && (rc == 0)) 319 - rc = -EACCES; 320 - else { 321 - cFYI(1, ("num referral: %d", 322 - num_referrals)); 323 - if (refs && refs->path_name) { 324 - strncpy(tmpbuffer, 325 - refs->path_name, 326 - len-1); 327 - } 328 - } 329 - kfree(refs); 330 - kfree(tmp_path); 331 - } 332 - /* BB add code like else decode referrals 333 - then memcpy to tmpbuffer and free referrals 334 - string array BB */ 335 - } 298 + /* If it is a DFS junction earlier we would have gotten 299 + PATH_NOT_COVERED returned from server so we do 300 + not need to request the DFS info here */ 336 301 } 337 302 } 338 303 /* BB Anything else to do to handle recursive links? */
+3 -3
fs/cifs/netmisc.c
··· 141 141 int ret = 0; 142 142 143 143 /* calculate length by finding first slash or NULL */ 144 - if (address_family == AF_INET) { 144 + if (address_family == AF_INET) 145 145 ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); 146 - } else if (address_family == AF_INET6) { 146 + else if (address_family == AF_INET6) 147 147 ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); 148 - } 148 + 149 149 cFYI(DBG2, ("address conversion returned %d for %s", ret, cp)); 150 150 if (ret > 0) 151 151 ret = 1;
+2 -2
fs/cifs/ntlmssp.h
··· 64 64 } __attribute__((packed)) SECURITY_BUFFER; 65 65 66 66 typedef struct _NEGOTIATE_MESSAGE { 67 - __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; 67 + __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 68 68 __le32 MessageType; /* 1 */ 69 69 __le32 NegotiateFlags; 70 70 SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ ··· 74 74 } __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; 75 75 76 76 typedef struct _CHALLENGE_MESSAGE { 77 - __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; 77 + __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 78 78 __le32 MessageType; /* 2 */ 79 79 SECURITY_BUFFER TargetName; 80 80 __le32 NegotiateFlags;
+5 -2
fs/cifs/readdir.c
··· 670 670 (index_to_find < first_entry_in_buffer)) { 671 671 /* close and restart search */ 672 672 cFYI(1, ("search backing up - close and restart search")); 673 - cifsFile->invalidHandle = true; 674 - CIFSFindClose(xid, pTcon, cifsFile->netfid); 673 + if (!cifsFile->srch_inf.endOfSearch && 674 + !cifsFile->invalidHandle) { 675 + cifsFile->invalidHandle = true; 676 + CIFSFindClose(xid, pTcon, cifsFile->netfid); 677 + } 675 678 kfree(cifsFile->search_resume_name); 676 679 cifsFile->search_resume_name = NULL; 677 680 if (cifsFile->srch_inf.ntwrk_buf_start) {