Skip to content

Commit a507db1

Browse files
committed
Merge tag '6.5-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client updates from Steve French: - Deferred close fix - Debugging improvements: display missing mount option, dump rc on invalidate inode failures, print client_guid in DebugData, log session id when matching session not found in reconnect, new dynamic tracepoint for session not found - Mount fixes including: potential null dereference, and possible memory leak and path name parsing when double slashes - Fix potential use after free in compounding - Two crediting (flow control) fixes: fix for crediting leak (stress scenario with excess lease credits) and better locking around updating credits - Three cleanups from issues pointed out by the kernel test robot - Session state check improvements (including for potential use after free) - DFS fixes: Fix for getattr on link when DFS disabled, fix for DFS mounts to same share with different prefix paths, DFS mount error checking improvement * tag '6.5-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: cifs: new dynamic tracepoint to track ses not found errors cifs: log session id when a matching ses is not found smb: client: improve DFS mount check smb: client: fix shared DFS root mounts with different prefixes smb: client: fix parsing of source mount option smb: client: fix broken file attrs with nodfs mounts cifs: print client_guid in DebugData cifs: fix session state check in smb2_find_smb_ses cifs: fix session state check in reconnect to avoid use-after-free issue cifs: do all necessary checks for credits within or before locking cifs: prevent use-after-free by freeing the cfile later smb: client: fix warning in generic_ip_connect() smb: client: fix warning in CIFSFindNext() smb: client: fix warning in CIFSFindFirst() smb3: do not reserve too many oplock credits cifs: print more detail when invalidate_inode_mapping fails smb: client: fix warning in cifs_smb3_do_mount() smb: client: fix warning in cifs_match_super() cifs: print nosharesock value while dumping mount options SMB3: Do not send lease break acknowledgment if all file handles have been closed
2 parents 8976e9d + 61986a5 commit a507db1

20 files changed

+403
-345
lines changed

fs/smb/client/cifs_debug.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
122122
seq_puts(m, " nosparse");
123123
if (tcon->need_reconnect)
124124
seq_puts(m, "\tDISCONNECTED ");
125+
spin_lock(&tcon->tc_lock);
126+
if (tcon->origin_fullpath) {
127+
seq_printf(m, "\n\tDFS origin fullpath: %s",
128+
tcon->origin_fullpath);
129+
}
130+
spin_unlock(&tcon->tc_lock);
125131
seq_putc(m, '\n');
126132
}
127133

@@ -330,6 +336,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
330336
spin_lock(&server->srv_lock);
331337
if (server->hostname)
332338
seq_printf(m, "Hostname: %s ", server->hostname);
339+
seq_printf(m, "\nClientGUID: %pUL", server->client_guid);
333340
spin_unlock(&server->srv_lock);
334341
#ifdef CONFIG_CIFS_SMB_DIRECT
335342
if (!server->rdma)
@@ -427,13 +434,9 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
427434
seq_printf(m, "\nIn Send: %d In MaxReq Wait: %d",
428435
atomic_read(&server->in_send),
429436
atomic_read(&server->num_waiters));
430-
if (IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)) {
431-
if (server->origin_fullpath)
432-
seq_printf(m, "\nDFS origin full path: %s",
433-
server->origin_fullpath);
434-
if (server->leaf_fullpath)
435-
seq_printf(m, "\nDFS leaf full path: %s",
436-
server->leaf_fullpath);
437+
if (server->leaf_fullpath) {
438+
seq_printf(m, "\nDFS leaf full path: %s",
439+
server->leaf_fullpath);
437440
}
438441

439442
seq_printf(m, "\n\n\tSessions: ");

fs/smb/client/cifs_dfs_ref.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,12 @@ cifs_build_devname(char *nodename, const char *prepath)
118118
return dev;
119119
}
120120

121-
static int set_dest_addr(struct smb3_fs_context *ctx, const char *full_path)
121+
static int set_dest_addr(struct smb3_fs_context *ctx)
122122
{
123123
struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
124124
int rc;
125125

126-
rc = dns_resolve_server_name_to_ip(full_path, addr, NULL);
126+
rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL);
127127
if (!rc)
128128
cifs_set_port(addr, ctx->port);
129129
return rc;
@@ -171,10 +171,9 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
171171
mnt = ERR_CAST(full_path);
172172
goto out;
173173
}
174-
cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
175174

176175
tmp = *cur_ctx;
177-
tmp.source = full_path;
176+
tmp.source = NULL;
178177
tmp.leaf_fullpath = NULL;
179178
tmp.UNC = tmp.prepath = NULL;
180179
tmp.dfs_root_ses = NULL;
@@ -185,13 +184,22 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
185184
goto out;
186185
}
187186

188-
rc = set_dest_addr(ctx, full_path);
187+
rc = smb3_parse_devname(full_path, ctx);
189188
if (rc) {
190189
mnt = ERR_PTR(rc);
191190
goto out;
192191
}
193192

194-
rc = smb3_parse_devname(full_path, ctx);
193+
ctx->source = smb3_fs_context_fullpath(ctx, '/');
194+
if (IS_ERR(ctx->source)) {
195+
mnt = ERR_CAST(ctx->source);
196+
ctx->source = NULL;
197+
goto out;
198+
}
199+
cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s dstaddr=%pISpc\n",
200+
__func__, ctx->source, ctx->UNC, ctx->prepath, &ctx->dstaddr);
201+
202+
rc = set_dest_addr(ctx);
195203
if (!rc)
196204
mnt = fc_mount(fc);
197205
else

fs/smb/client/cifsfs.c

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
688688
seq_puts(s, ",noautotune");
689689
if (tcon->ses->server->noblocksnd)
690690
seq_puts(s, ",noblocksend");
691+
if (tcon->ses->server->nosharesock)
692+
seq_puts(s, ",nosharesock");
691693

692694
if (tcon->snapshot_time)
693695
seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
@@ -884,11 +886,11 @@ struct dentry *
884886
cifs_smb3_do_mount(struct file_system_type *fs_type,
885887
int flags, struct smb3_fs_context *old_ctx)
886888
{
887-
int rc;
888-
struct super_block *sb = NULL;
889-
struct cifs_sb_info *cifs_sb = NULL;
890889
struct cifs_mnt_data mnt_data;
890+
struct cifs_sb_info *cifs_sb;
891+
struct super_block *sb;
891892
struct dentry *root;
893+
int rc;
892894

893895
if (cifsFYI) {
894896
cifs_dbg(FYI, "%s: devname=%s flags=0x%x\n", __func__,
@@ -897,11 +899,9 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
897899
cifs_info("Attempting to mount %s\n", old_ctx->source);
898900
}
899901

900-
cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
901-
if (cifs_sb == NULL) {
902-
root = ERR_PTR(-ENOMEM);
903-
goto out;
904-
}
902+
cifs_sb = kzalloc(sizeof(*cifs_sb), GFP_KERNEL);
903+
if (!cifs_sb)
904+
return ERR_PTR(-ENOMEM);
905905

906906
cifs_sb->ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL);
907907
if (!cifs_sb->ctx) {
@@ -938,10 +938,8 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
938938

939939
sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data);
940940
if (IS_ERR(sb)) {
941-
root = ERR_CAST(sb);
942941
cifs_umount(cifs_sb);
943-
cifs_sb = NULL;
944-
goto out;
942+
return ERR_CAST(sb);
945943
}
946944

947945
if (sb->s_root) {
@@ -972,13 +970,9 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
972970
deactivate_locked_super(sb);
973971
return root;
974972
out:
975-
if (cifs_sb) {
976-
if (!sb || IS_ERR(sb)) { /* otherwise kill_sb will handle */
977-
kfree(cifs_sb->prepath);
978-
smb3_cleanup_fs_context(cifs_sb->ctx);
979-
kfree(cifs_sb);
980-
}
981-
}
973+
kfree(cifs_sb->prepath);
974+
smb3_cleanup_fs_context(cifs_sb->ctx);
975+
kfree(cifs_sb);
982976
return root;
983977
}
984978

fs/smb/client/cifsglob.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -736,23 +736,20 @@ struct TCP_Server_Info {
736736
#endif
737737
struct mutex refpath_lock; /* protects leaf_fullpath */
738738
/*
739-
* origin_fullpath: Canonical copy of smb3_fs_context::source.
740-
* It is used for matching existing DFS tcons.
741-
*
742739
* leaf_fullpath: Canonical DFS referral path related to this
743740
* connection.
744741
* It is used in DFS cache refresher, reconnect and may
745742
* change due to nested DFS links.
746743
*
747-
* Both protected by @refpath_lock and @srv_lock. The @refpath_lock is
748-
* mosly used for not requiring a copy of @leaf_fullpath when getting
744+
* Protected by @refpath_lock and @srv_lock. The @refpath_lock is
745+
* mostly used for not requiring a copy of @leaf_fullpath when getting
749746
* cached or new DFS referrals (which might also sleep during I/O).
750747
* While @srv_lock is held for making string and NULL comparions against
751748
* both fields as in mount(2) and cache refresh.
752749
*
753750
* format: \\HOST\SHARE[\OPTIONAL PATH]
754751
*/
755-
char *origin_fullpath, *leaf_fullpath;
752+
char *leaf_fullpath;
756753
};
757754

758755
static inline bool is_smb1(struct TCP_Server_Info *server)
@@ -1205,6 +1202,7 @@ struct cifs_tcon {
12051202
struct delayed_work dfs_cache_work;
12061203
#endif
12071204
struct delayed_work query_interfaces; /* query interfaces workqueue job */
1205+
char *origin_fullpath; /* canonical copy of smb3_fs_context::source */
12081206
};
12091207

12101208
/*

fs/smb/client/cifsproto.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ extern void release_mid(struct mid_q_entry *mid);
8585
extern void cifs_wake_up_task(struct mid_q_entry *mid);
8686
extern int cifs_handle_standard(struct TCP_Server_Info *server,
8787
struct mid_q_entry *mid);
88+
extern char *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx,
89+
char dirsep);
8890
extern int smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx);
8991
extern int smb3_parse_opt(const char *options, const char *key, char **val);
9092
extern int cifs_ipaddr_cmp(struct sockaddr *srcaddr, struct sockaddr *rhs);
@@ -650,7 +652,7 @@ int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov,
650652
int resp_buftype,
651653
struct cifs_search_info *srch_inf);
652654

653-
struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server);
655+
struct super_block *cifs_get_dfs_tcon_super(struct cifs_tcon *tcon);
654656
void cifs_put_tcp_super(struct super_block *sb);
655657
int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
656658
char *extract_hostname(const char *unc);

0 commit comments

Comments
 (0)