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 tag 'v6.16-rc4-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

- Two reconnect fixes including one for a reboot/reconnect race

- Fix for incorrect file type that can be returned by SMB3.1.1 POSIX
extensions

- tcon initialization fix

- Fix for resolving Windows symlinks with absolute paths

* tag 'v6.16-rc4-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
smb: client: fix native SMB symlink traversal
smb: client: fix race condition in negotiate timeout by using more precise timing
cifs: all initializations for tcon should happen in tcon_info_alloc
smb: client: fix warning when reconnecting channel
smb: client: fix readdir returning wrong type with POSIX extensions

+39 -36
+2
fs/smb/client/cifsglob.h
··· 777 777 __le32 session_key_id; /* retrieved from negotiate response and send in session setup request */ 778 778 struct session_key session_key; 779 779 unsigned long lstrp; /* when we got last response from this server */ 780 + unsigned long neg_start; /* when negotiate started (jiffies) */ 780 781 struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ 781 782 #define CIFS_NEGFLAVOR_UNENCAP 1 /* wct == 17, but no ext_sec */ 782 783 #define CIFS_NEGFLAVOR_EXTENDED 2 /* wct == 17, ext_sec bit set */ ··· 1304 1303 bool use_persistent:1; /* use persistent instead of durable handles */ 1305 1304 bool no_lease:1; /* Do not request leases on files or directories */ 1306 1305 bool use_witness:1; /* use witness protocol */ 1306 + bool dummy:1; /* dummy tcon used for reconnecting channels */ 1307 1307 __le32 capabilities; 1308 1308 __u32 share_flags; 1309 1309 __u32 maximal_access;
+1
fs/smb/client/cifsproto.h
··· 136 136 struct smb_hdr *out_buf, 137 137 int *bytes_returned); 138 138 139 + void smb2_query_server_interfaces(struct work_struct *work); 139 140 void 140 141 cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server, 141 142 bool all_channels);
+5 -10
fs/smb/client/connect.c
··· 97 97 return rc; 98 98 } 99 99 100 - static void smb2_query_server_interfaces(struct work_struct *work) 100 + void smb2_query_server_interfaces(struct work_struct *work) 101 101 { 102 102 int rc; 103 103 int xid; ··· 679 679 /* 680 680 * If we're in the process of mounting a share or reconnecting a session 681 681 * and the server abruptly shut down (e.g. socket wasn't closed, packet 682 - * had been ACK'ed but no SMB response), don't wait longer than 20s to 683 - * negotiate protocol. 682 + * had been ACK'ed but no SMB response), don't wait longer than 20s from 683 + * when negotiate actually started. 684 684 */ 685 685 spin_lock(&server->srv_lock); 686 686 if (server->tcpStatus == CifsInNegotiate && 687 - time_after(jiffies, server->lstrp + 20 * HZ)) { 687 + time_after(jiffies, server->neg_start + 20 * HZ)) { 688 688 spin_unlock(&server->srv_lock); 689 689 cifs_reconnect(server, false); 690 690 return true; ··· 2880 2880 tcon->max_cached_dirs = ctx->max_cached_dirs; 2881 2881 tcon->nodelete = ctx->nodelete; 2882 2882 tcon->local_lease = ctx->local_lease; 2883 - INIT_LIST_HEAD(&tcon->pending_opens); 2884 2883 tcon->status = TID_GOOD; 2885 2884 2886 - INIT_DELAYED_WORK(&tcon->query_interfaces, 2887 - smb2_query_server_interfaces); 2888 2885 if (ses->server->dialect >= SMB30_PROT_ID && 2889 2886 (ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { 2890 2887 /* schedule query interfaces poll */ 2891 2888 queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, 2892 2889 (SMB_INTERFACE_POLL_INTERVAL * HZ)); 2893 2890 } 2894 - #ifdef CONFIG_CIFS_DFS_UPCALL 2895 - INIT_DELAYED_WORK(&tcon->dfs_cache_work, dfs_cache_refresh); 2896 - #endif 2897 2891 spin_lock(&cifs_tcp_ses_lock); 2898 2892 list_add(&tcon->tcon_list, &ses->tcon_list); 2899 2893 spin_unlock(&cifs_tcp_ses_lock); ··· 4209 4215 4210 4216 server->lstrp = jiffies; 4211 4217 server->tcpStatus = CifsInNegotiate; 4218 + server->neg_start = jiffies; 4212 4219 spin_unlock(&server->srv_lock); 4213 4220 4214 4221 rc = server->ops->negotiate(xid, ses, server);
+7 -10
fs/smb/client/fs_context.c
··· 1824 1824 cifs_errorf(fc, "symlinkroot mount options must be absolute path\n"); 1825 1825 goto cifs_parse_mount_err; 1826 1826 } 1827 - kfree(ctx->symlinkroot); 1828 - ctx->symlinkroot = kstrdup(param->string, GFP_KERNEL); 1829 - if (!ctx->symlinkroot) 1827 + if (strnlen(param->string, PATH_MAX) == PATH_MAX) { 1828 + cifs_errorf(fc, "symlinkroot path too long (max path length: %u)\n", 1829 + PATH_MAX - 1); 1830 1830 goto cifs_parse_mount_err; 1831 + } 1832 + kfree(ctx->symlinkroot); 1833 + ctx->symlinkroot = param->string; 1834 + param->string = NULL; 1831 1835 break; 1832 1836 } 1833 1837 /* case Opt_ignore: - is ignored as expected ... */ ··· 1840 1836 cifs_errorf(fc, "multiuser mount option not supported with upcalltarget set as 'mount'\n"); 1841 1837 goto cifs_parse_mount_err; 1842 1838 } 1843 - 1844 - /* 1845 - * By default resolve all native absolute symlinks relative to "/mnt/". 1846 - * Same default has drvfs driver running in WSL for resolving SMB shares. 1847 - */ 1848 - if (!ctx->symlinkroot) 1849 - ctx->symlinkroot = kstrdup("/mnt/", GFP_KERNEL); 1850 1839 1851 1840 return 0; 1852 1841
+6
fs/smb/client/misc.c
··· 151 151 #ifdef CONFIG_CIFS_DFS_UPCALL 152 152 INIT_LIST_HEAD(&ret_buf->dfs_ses_list); 153 153 #endif 154 + INIT_LIST_HEAD(&ret_buf->pending_opens); 155 + INIT_DELAYED_WORK(&ret_buf->query_interfaces, 156 + smb2_query_server_interfaces); 157 + #ifdef CONFIG_CIFS_DFS_UPCALL 158 + INIT_DELAYED_WORK(&ret_buf->dfs_cache_work, dfs_cache_refresh); 159 + #endif 154 160 155 161 return ret_buf; 156 162 }
+1 -1
fs/smb/client/readdir.c
··· 264 264 /* The Mode field in the response can now include the file type as well */ 265 265 fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode), 266 266 fattr->cf_cifsattrs & ATTR_DIRECTORY); 267 - fattr->cf_dtype = S_DT(le32_to_cpu(info->Mode)); 267 + fattr->cf_dtype = S_DT(fattr->cf_mode); 268 268 269 269 switch (fattr->cf_mode & S_IFMT) { 270 270 case S_IFLNK:
+13 -9
fs/smb/client/reparse.c
··· 57 57 struct reparse_symlink_data_buffer *buf = NULL; 58 58 struct cifs_open_info_data data = {}; 59 59 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 60 + const char *symroot = cifs_sb->ctx->symlinkroot; 60 61 struct inode *new; 61 62 struct kvec iov; 62 63 __le16 *path = NULL; ··· 83 82 .symlink_target = symlink_target, 84 83 }; 85 84 86 - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') { 85 + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && 86 + symroot && symname[0] == '/') { 87 87 /* 88 88 * This is a request to create an absolute symlink on the server 89 89 * which does not support POSIX paths, and expects symlink in ··· 94 92 * ensure compatibility of this symlink stored in absolute form 95 93 * on the SMB server. 96 94 */ 97 - if (!strstarts(symname, cifs_sb->ctx->symlinkroot)) { 95 + if (!strstarts(symname, symroot)) { 98 96 /* 99 97 * If the absolute Linux symlink target path is not 100 98 * inside "symlinkroot" location then there is no way ··· 103 101 cifs_dbg(VFS, 104 102 "absolute symlink '%s' cannot be converted to NT format " 105 103 "because it is outside of symlinkroot='%s'\n", 106 - symname, cifs_sb->ctx->symlinkroot); 104 + symname, symroot); 107 105 rc = -EINVAL; 108 106 goto out; 109 107 } 110 - len = strlen(cifs_sb->ctx->symlinkroot); 111 - if (cifs_sb->ctx->symlinkroot[len-1] != '/') 108 + len = strlen(symroot); 109 + if (symroot[len - 1] != '/') 112 110 len++; 113 111 if (symname[len] >= 'a' && symname[len] <= 'z' && 114 112 (symname[len+1] == '/' || symname[len+1] == '\0')) { ··· 784 782 const char *full_path, 785 783 struct cifs_sb_info *cifs_sb) 786 784 { 785 + const char *symroot = cifs_sb->ctx->symlinkroot; 787 786 char sep = CIFS_DIR_SEP(cifs_sb); 788 787 char *linux_target = NULL; 789 788 char *smb_target = NULL; ··· 818 815 goto out; 819 816 } 820 817 821 - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && !relative) { 818 + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && 819 + symroot && !relative) { 822 820 /* 823 821 * This is an absolute symlink from the server which does not 824 822 * support POSIX paths, so the symlink is in NT-style path. ··· 911 907 } 912 908 913 909 abs_path_len = strlen(abs_path)+1; 914 - symlinkroot_len = strlen(cifs_sb->ctx->symlinkroot); 915 - if (cifs_sb->ctx->symlinkroot[symlinkroot_len-1] == '/') 910 + symlinkroot_len = strlen(symroot); 911 + if (symroot[symlinkroot_len - 1] == '/') 916 912 symlinkroot_len--; 917 913 linux_target = kmalloc(symlinkroot_len + 1 + abs_path_len, GFP_KERNEL); 918 914 if (!linux_target) { 919 915 rc = -ENOMEM; 920 916 goto out; 921 917 } 922 - memcpy(linux_target, cifs_sb->ctx->symlinkroot, symlinkroot_len); 918 + memcpy(linux_target, symroot, symlinkroot_len); 923 919 linux_target[symlinkroot_len] = '/'; 924 920 memcpy(linux_target + symlinkroot_len + 1, abs_path, abs_path_len); 925 921 } else if (smb_target[0] == sep && relative) {
+4 -6
fs/smb/client/smb2pdu.c
··· 424 424 free_xid(xid); 425 425 ses->flags &= ~CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES; 426 426 427 - /* regardless of rc value, setup polling */ 428 - queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, 429 - (SMB_INTERFACE_POLL_INTERVAL * HZ)); 427 + if (!tcon->ipc && !tcon->dummy) 428 + queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, 429 + (SMB_INTERFACE_POLL_INTERVAL * HZ)); 430 430 431 431 mutex_unlock(&ses->session_mutex); 432 432 ··· 4229 4229 } 4230 4230 goto done; 4231 4231 } 4232 - 4233 4232 tcon->status = TID_GOOD; 4234 - tcon->retry = false; 4235 - tcon->need_reconnect = false; 4233 + tcon->dummy = true; 4236 4234 4237 4235 /* now reconnect sessions for necessary channels */ 4238 4236 list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) {