Skip to content

Commit 63342b1

Browse files
committed
Merge tag '6.4-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "smb3 client fixes, mostly DFS or reconnect related: - Two DFS connection sharing fixes - DFS refresh fix - Reconnect fix - Two potential use after free fixes - Also print prefix patch in mount debug msg - Two small cleanup fixes" * tag '6.4-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6: cifs: Remove unneeded semicolon cifs: fix sharing of DFS connections cifs: avoid potential races when handling multiple dfs tcons cifs: protect access of TCP_Server_Info::{origin,leaf}_fullpath cifs: fix potential race when tree connecting ipc cifs: fix potential use-after-free bugs in TCP_Server_Info::hostname cifs: print smb3_fs_context::source when mounting cifs: protect session status check in smb2_reconnect() SMB3.1.1: correct definition for app_instance_id create contexts
2 parents d6b8a8c + 9ee0487 commit 63342b1

File tree

15 files changed

+376
-223
lines changed

15 files changed

+376
-223
lines changed

fs/cifs/cifs_debug.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,10 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
280280
seq_printf(m, "\n%d) ConnectionId: 0x%llx ",
281281
c, server->conn_id);
282282

283+
spin_lock(&server->srv_lock);
283284
if (server->hostname)
284285
seq_printf(m, "Hostname: %s ", server->hostname);
286+
spin_unlock(&server->srv_lock);
285287
#ifdef CONFIG_CIFS_SMB_DIRECT
286288
if (!server->rdma)
287289
goto skip_rdma;
@@ -623,10 +625,13 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
623625
server->fastest_cmd[j],
624626
server->slowest_cmd[j]);
625627
for (j = 0; j < NUMBER_OF_SMB2_COMMANDS; j++)
626-
if (atomic_read(&server->smb2slowcmd[j]))
628+
if (atomic_read(&server->smb2slowcmd[j])) {
629+
spin_lock(&server->srv_lock);
627630
seq_printf(m, " %d slow responses from %s for command %d\n",
628631
atomic_read(&server->smb2slowcmd[j]),
629632
server->hostname, j);
633+
spin_unlock(&server->srv_lock);
634+
}
630635
#endif /* STATS2 */
631636
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
632637
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {

fs/cifs/cifs_debug.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,19 @@ do { \
8181

8282
#define cifs_server_dbg_func(ratefunc, type, fmt, ...) \
8383
do { \
84-
const char *sn = ""; \
85-
if (server && server->hostname) \
86-
sn = server->hostname; \
84+
spin_lock(&server->srv_lock); \
8785
if ((type) & FYI && cifsFYI & CIFS_INFO) { \
8886
pr_debug_ ## ratefunc("%s: \\\\%s " fmt, \
89-
__FILE__, sn, ##__VA_ARGS__); \
87+
__FILE__, server->hostname, \
88+
##__VA_ARGS__); \
9089
} else if ((type) & VFS) { \
9190
pr_err_ ## ratefunc("VFS: \\\\%s " fmt, \
92-
sn, ##__VA_ARGS__); \
91+
server->hostname, ##__VA_ARGS__); \
9392
} else if ((type) & NOISY && (NOISY != 0)) { \
9493
pr_debug_ ## ratefunc("\\\\%s " fmt, \
95-
sn, ##__VA_ARGS__); \
94+
server->hostname, ##__VA_ARGS__); \
9695
} \
96+
spin_unlock(&server->srv_lock); \
9797
} while (0)
9898

9999
#define cifs_server_dbg(type, fmt, ...) \

fs/cifs/cifsfs.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -874,14 +874,12 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
874874
struct cifs_mnt_data mnt_data;
875875
struct dentry *root;
876876

877-
/*
878-
* Prints in Kernel / CIFS log the attempted mount operation
879-
* If CIFS_DEBUG && cifs_FYI
880-
*/
881-
if (cifsFYI)
882-
cifs_dbg(FYI, "Devname: %s flags: %d\n", old_ctx->UNC, flags);
883-
else
884-
cifs_info("Attempting to mount %s\n", old_ctx->UNC);
877+
if (cifsFYI) {
878+
cifs_dbg(FYI, "%s: devname=%s flags=0x%x\n", __func__,
879+
old_ctx->source, flags);
880+
} else {
881+
cifs_info("Attempting to mount %s\n", old_ctx->source);
882+
}
885883

886884
cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
887885
if (cifs_sb == NULL) {

fs/cifs/cifsglob.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -736,17 +736,23 @@ struct TCP_Server_Info {
736736
#endif
737737
struct mutex refpath_lock; /* protects leaf_fullpath */
738738
/*
739-
* Canonical DFS full paths that were used to chase referrals in mount and reconnect.
739+
* origin_fullpath: Canonical copy of smb3_fs_context::source.
740+
* It is used for matching existing DFS tcons.
740741
*
741-
* origin_fullpath: first or original referral path
742-
* leaf_fullpath: last referral path (might be changed due to nested links in reconnect)
742+
* leaf_fullpath: Canonical DFS referral path related to this
743+
* connection.
744+
* It is used in DFS cache refresher, reconnect and may
745+
* change due to nested DFS links.
743746
*
744-
* current_fullpath: pointer to either origin_fullpath or leaf_fullpath
745-
* NOTE: cannot be accessed outside cifs_reconnect() and smb2_reconnect()
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
749+
* cached or new DFS referrals (which might also sleep during I/O).
750+
* While @srv_lock is held for making string and NULL comparions against
751+
* both fields as in mount(2) and cache refresh.
746752
*
747-
* format: \\HOST\SHARE\[OPTIONAL PATH]
753+
* format: \\HOST\SHARE[\OPTIONAL PATH]
748754
*/
749-
char *origin_fullpath, *leaf_fullpath, *current_fullpath;
755+
char *origin_fullpath, *leaf_fullpath;
750756
};
751757

752758
static inline bool is_smb1(struct TCP_Server_Info *server)
@@ -1232,8 +1238,8 @@ struct cifs_tcon {
12321238
struct cached_fids *cfids;
12331239
/* BB add field for back pointer to sb struct(s)? */
12341240
#ifdef CONFIG_CIFS_DFS_UPCALL
1235-
struct list_head ulist; /* cache update list */
12361241
struct list_head dfs_ses_list;
1242+
struct delayed_work dfs_cache_work;
12371243
#endif
12381244
struct delayed_work query_interfaces; /* query interfaces workqueue job */
12391245
};
@@ -1750,7 +1756,6 @@ struct cifs_mount_ctx {
17501756
struct TCP_Server_Info *server;
17511757
struct cifs_ses *ses;
17521758
struct cifs_tcon *tcon;
1753-
char *origin_fullpath, *leaf_fullpath;
17541759
struct list_head dfs_ses_list;
17551760
};
17561761

fs/cifs/cifsproto.h

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef _CIFSPROTO_H
99
#define _CIFSPROTO_H
1010
#include <linux/nls.h>
11+
#include <linux/ctype.h>
1112
#include "trace.h"
1213
#ifdef CONFIG_CIFS_DFS_UPCALL
1314
#include "dfs_cache.h"
@@ -572,7 +573,7 @@ extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
572573
extern struct TCP_Server_Info *
573574
cifs_find_tcp_session(struct smb3_fs_context *ctx);
574575

575-
extern void cifs_put_smb_ses(struct cifs_ses *ses);
576+
void __cifs_put_smb_ses(struct cifs_ses *ses);
576577

577578
extern struct cifs_ses *
578579
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx);
@@ -696,4 +697,45 @@ struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
696697
void cifs_put_tcon_super(struct super_block *sb);
697698
int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
698699

700+
/* Put references of @ses and @ses->dfs_root_ses */
701+
static inline void cifs_put_smb_ses(struct cifs_ses *ses)
702+
{
703+
struct cifs_ses *rses = ses->dfs_root_ses;
704+
705+
__cifs_put_smb_ses(ses);
706+
if (rses)
707+
__cifs_put_smb_ses(rses);
708+
}
709+
710+
/* Get an active reference of @ses and @ses->dfs_root_ses.
711+
*
712+
* NOTE: make sure to call this function when incrementing reference count of
713+
* @ses to ensure that any DFS root session attached to it (@ses->dfs_root_ses)
714+
* will also get its reference count incremented.
715+
*
716+
* cifs_put_smb_ses() will put both references, so call it when you're done.
717+
*/
718+
static inline void cifs_smb_ses_inc_refcount(struct cifs_ses *ses)
719+
{
720+
lockdep_assert_held(&cifs_tcp_ses_lock);
721+
722+
ses->ses_count++;
723+
if (ses->dfs_root_ses)
724+
ses->dfs_root_ses->ses_count++;
725+
}
726+
727+
static inline bool dfs_src_pathname_equal(const char *s1, const char *s2)
728+
{
729+
if (strlen(s1) != strlen(s2))
730+
return false;
731+
for (; *s1; s1++, s2++) {
732+
if (*s1 == '/' || *s1 == '\\') {
733+
if (*s2 != '/' && *s2 != '\\')
734+
return false;
735+
} else if (tolower(*s1) != tolower(*s2))
736+
return false;
737+
}
738+
return true;
739+
}
740+
699741
#endif /* _CIFSPROTO_H */

0 commit comments

Comments
 (0)