Skip to content

Commit

Permalink
Merge tag '6.5-rc-smb3-client-fixes-part1' of git://git.samba.org/sfr…
Browse files Browse the repository at this point in the history
…ench/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
  • Loading branch information
Linus Torvalds committed Jul 1, 2023
2 parents 8976e9d + 61986a5 commit a507db1
Show file tree
Hide file tree
Showing 20 changed files with 403 additions and 345 deletions.
17 changes: 10 additions & 7 deletions fs/smb/client/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
seq_puts(m, " nosparse");
if (tcon->need_reconnect)
seq_puts(m, "\tDISCONNECTED ");
spin_lock(&tcon->tc_lock);
if (tcon->origin_fullpath) {
seq_printf(m, "\n\tDFS origin fullpath: %s",
tcon->origin_fullpath);
}
spin_unlock(&tcon->tc_lock);
seq_putc(m, '\n');
}

Expand Down Expand Up @@ -330,6 +336,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
spin_lock(&server->srv_lock);
if (server->hostname)
seq_printf(m, "Hostname: %s ", server->hostname);
seq_printf(m, "\nClientGUID: %pUL", server->client_guid);
spin_unlock(&server->srv_lock);
#ifdef CONFIG_CIFS_SMB_DIRECT
if (!server->rdma)
Expand Down Expand Up @@ -427,13 +434,9 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
seq_printf(m, "\nIn Send: %d In MaxReq Wait: %d",
atomic_read(&server->in_send),
atomic_read(&server->num_waiters));
if (IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)) {
if (server->origin_fullpath)
seq_printf(m, "\nDFS origin full path: %s",
server->origin_fullpath);
if (server->leaf_fullpath)
seq_printf(m, "\nDFS leaf full path: %s",
server->leaf_fullpath);
if (server->leaf_fullpath) {
seq_printf(m, "\nDFS leaf full path: %s",
server->leaf_fullpath);
}

seq_printf(m, "\n\n\tSessions: ");
Expand Down
20 changes: 14 additions & 6 deletions fs/smb/client/cifs_dfs_ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ cifs_build_devname(char *nodename, const char *prepath)
return dev;
}

static int set_dest_addr(struct smb3_fs_context *ctx, const char *full_path)
static int set_dest_addr(struct smb3_fs_context *ctx)
{
struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
int rc;

rc = dns_resolve_server_name_to_ip(full_path, addr, NULL);
rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL);
if (!rc)
cifs_set_port(addr, ctx->port);
return rc;
Expand Down Expand Up @@ -171,10 +171,9 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
mnt = ERR_CAST(full_path);
goto out;
}
cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);

tmp = *cur_ctx;
tmp.source = full_path;
tmp.source = NULL;
tmp.leaf_fullpath = NULL;
tmp.UNC = tmp.prepath = NULL;
tmp.dfs_root_ses = NULL;
Expand All @@ -185,13 +184,22 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
goto out;
}

rc = set_dest_addr(ctx, full_path);
rc = smb3_parse_devname(full_path, ctx);
if (rc) {
mnt = ERR_PTR(rc);
goto out;
}

rc = smb3_parse_devname(full_path, ctx);
ctx->source = smb3_fs_context_fullpath(ctx, '/');
if (IS_ERR(ctx->source)) {
mnt = ERR_CAST(ctx->source);
ctx->source = NULL;
goto out;
}
cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s dstaddr=%pISpc\n",
__func__, ctx->source, ctx->UNC, ctx->prepath, &ctx->dstaddr);

rc = set_dest_addr(ctx);
if (!rc)
mnt = fc_mount(fc);
else
Expand Down
30 changes: 12 additions & 18 deletions fs/smb/client/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts(s, ",noautotune");
if (tcon->ses->server->noblocksnd)
seq_puts(s, ",noblocksend");
if (tcon->ses->server->nosharesock)
seq_puts(s, ",nosharesock");

if (tcon->snapshot_time)
seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
Expand Down Expand Up @@ -884,11 +886,11 @@ struct dentry *
cifs_smb3_do_mount(struct file_system_type *fs_type,
int flags, struct smb3_fs_context *old_ctx)
{
int rc;
struct super_block *sb = NULL;
struct cifs_sb_info *cifs_sb = NULL;
struct cifs_mnt_data mnt_data;
struct cifs_sb_info *cifs_sb;
struct super_block *sb;
struct dentry *root;
int rc;

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

cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
if (cifs_sb == NULL) {
root = ERR_PTR(-ENOMEM);
goto out;
}
cifs_sb = kzalloc(sizeof(*cifs_sb), GFP_KERNEL);
if (!cifs_sb)
return ERR_PTR(-ENOMEM);

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

sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data);
if (IS_ERR(sb)) {
root = ERR_CAST(sb);
cifs_umount(cifs_sb);
cifs_sb = NULL;
goto out;
return ERR_CAST(sb);
}

if (sb->s_root) {
Expand Down Expand Up @@ -972,13 +970,9 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
deactivate_locked_super(sb);
return root;
out:
if (cifs_sb) {
if (!sb || IS_ERR(sb)) { /* otherwise kill_sb will handle */
kfree(cifs_sb->prepath);
smb3_cleanup_fs_context(cifs_sb->ctx);
kfree(cifs_sb);
}
}
kfree(cifs_sb->prepath);
smb3_cleanup_fs_context(cifs_sb->ctx);
kfree(cifs_sb);
return root;
}

Expand Down
10 changes: 4 additions & 6 deletions fs/smb/client/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,23 +736,20 @@ struct TCP_Server_Info {
#endif
struct mutex refpath_lock; /* protects leaf_fullpath */
/*
* origin_fullpath: Canonical copy of smb3_fs_context::source.
* It is used for matching existing DFS tcons.
*
* leaf_fullpath: Canonical DFS referral path related to this
* connection.
* It is used in DFS cache refresher, reconnect and may
* change due to nested DFS links.
*
* Both protected by @refpath_lock and @srv_lock. The @refpath_lock is
* mosly used for not requiring a copy of @leaf_fullpath when getting
* Protected by @refpath_lock and @srv_lock. The @refpath_lock is
* mostly used for not requiring a copy of @leaf_fullpath when getting
* cached or new DFS referrals (which might also sleep during I/O).
* While @srv_lock is held for making string and NULL comparions against
* both fields as in mount(2) and cache refresh.
*
* format: \\HOST\SHARE[\OPTIONAL PATH]
*/
char *origin_fullpath, *leaf_fullpath;
char *leaf_fullpath;
};

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

/*
Expand Down
4 changes: 3 additions & 1 deletion fs/smb/client/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ extern void release_mid(struct mid_q_entry *mid);
extern void cifs_wake_up_task(struct mid_q_entry *mid);
extern int cifs_handle_standard(struct TCP_Server_Info *server,
struct mid_q_entry *mid);
extern char *smb3_fs_context_fullpath(const struct smb3_fs_context *ctx,
char dirsep);
extern int smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx);
extern int smb3_parse_opt(const char *options, const char *key, char **val);
extern int cifs_ipaddr_cmp(struct sockaddr *srcaddr, struct sockaddr *rhs);
Expand Down Expand Up @@ -650,7 +652,7 @@ int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov,
int resp_buftype,
struct cifs_search_info *srch_inf);

struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server);
struct super_block *cifs_get_dfs_tcon_super(struct cifs_tcon *tcon);
void cifs_put_tcp_super(struct super_block *sb);
int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
char *extract_hostname(const char *unc);
Expand Down
Loading

0 comments on commit a507db1

Please sign in to comment.