Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1dd5c6b1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "This ncludes various cifs/smb3 bug fixes, mostly for stable as well.

  In the next week I expect that Germano will have some reconnection
  fixes, and also I expect to have the remaining pieces of the snapshot
  enablement and SMB3 ACLs, but wanted to get this set of bug fixes in"

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
  cifs_get_root shouldn't use path with tree name
  Fix default behaviour for empty domains and add domainauto option
  cifs: use %16phN for formatting md5 sum
  cifs: Fix smbencrypt() to stop pointing a scatterlist at the stack
  CIFS: Fix a possible double locking of mutex during reconnect
  CIFS: Fix a possible memory corruption during reconnect
  CIFS: Fix a possible memory corruption in push locks
  CIFS: Fix missing nls unload in smb2_reconnect()
  CIFS: Decrease verbosity of ioctl call
  SMB3: parsing for new snapshot timestamp mount parm
parents 3a77fa85 374402a2
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -699,12 +699,16 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)

	if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
		if (!ses->domainName) {
			if (ses->domainAuto) {
				rc = find_domain_name(ses, nls_cp);
				if (rc) {
					cifs_dbg(VFS, "error %d finding domain name\n",
						 rc);
					goto setup_ntlmv2_rsp_ret;
				}
			} else {
				ses->domainName = kstrdup("", GFP_KERNEL);
			}
		}
	} else {
		rc = build_avpair_blob(ses, nls_cp);
+1 −1
Original line number Diff line number Diff line
@@ -615,7 +615,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
		return dget(sb->s_root);

	full_path = cifs_build_path_to_root(vol, cifs_sb,
					    cifs_sb_master_tcon(cifs_sb));
				cifs_sb_master_tcon(cifs_sb), 0);
	if (full_path == NULL)
		return ERR_PTR(-ENOMEM);

+8 −0
Original line number Diff line number Diff line
@@ -514,6 +514,7 @@ struct smb_vol {
	bool persistent:1;
	bool nopersistent:1;
	bool resilient:1; /* noresilient not required since not fored for CA */
	bool domainauto:1;
	unsigned int rsize;
	unsigned int wsize;
	bool sockopt_tcp_nodelay:1;
@@ -525,6 +526,7 @@ struct smb_vol {
	struct sockaddr_storage srcaddr; /* allow binding to a local IP */
	struct nls_table *local_nls;
	unsigned int echo_interval; /* echo interval in secs */
	__u64 snapshot_time; /* needed for timewarp tokens */
	unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
};

@@ -646,6 +648,8 @@ struct TCP_Server_Info {
	unsigned int	max_read;
	unsigned int	max_write;
	__u8		preauth_hash[512];
	struct delayed_work reconnect; /* reconnect workqueue job */
	struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
#endif /* CONFIG_CIFS_SMB2 */
	unsigned long echo_interval;
};
@@ -827,6 +831,7 @@ struct cifs_ses {
	enum securityEnum sectype; /* what security flavor was specified? */
	bool sign;		/* is signing required? */
	bool need_reconnect:1; /* connection reset, uid now invalid */
	bool domainAuto:1;
#ifdef CONFIG_CIFS_SMB2
	__u16 session_flags;
	__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
@@ -849,6 +854,7 @@ cap_unix(struct cifs_ses *ses)
struct cifs_tcon {
	struct list_head tcon_list;
	int tc_count;
	struct list_head rlist; /* reconnect list */
	struct list_head openFileList;
	spinlock_t open_file_lock; /* protects list above */
	struct cifs_ses *ses;	/* pointer to session associated with */
@@ -922,6 +928,7 @@ struct cifs_tcon {
	bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
	bool broken_sparse_sup; /* if server or share does not support sparse */
	bool need_reconnect:1; /* connection reset, tid now invalid */
	bool need_reopen_files:1; /* need to reopen tcon file handles */
	bool use_resilient:1; /* use resilient instead of durable handles */
	bool use_persistent:1; /* use persistent instead of durable handles */
#ifdef CONFIG_CIFS_SMB2
@@ -932,6 +939,7 @@ struct cifs_tcon {
	__u32 maximal_access;
	__u32 vol_serial_number;
	__le64 vol_create_time;
	__u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */
	__u32 ss_flags;		/* sector size flags */
	__u32 perf_sector_size; /* best sector size for perf */
	__u32 max_chunks;
+5 −1
Original line number Diff line number Diff line
@@ -63,7 +63,8 @@ extern void exit_cifs_spnego(void);
extern char *build_path_from_dentry(struct dentry *);
extern char *cifs_build_path_to_root(struct smb_vol *vol,
				     struct cifs_sb_info *cifs_sb,
				     struct cifs_tcon *tcon);
				     struct cifs_tcon *tcon,
				     int add_treename);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
extern char *cifs_compose_mount_options(const char *sb_mountdata,
		const char *fullpath, const struct dfs_info3_param *ref,
@@ -206,6 +207,9 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
					 struct tcon_link *tlink,
					 struct cifs_pending_open *open);
extern void cifs_del_pending_open(struct cifs_pending_open *open);
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
				 int from_reconnect);
extern void cifs_put_tcon(struct cifs_tcon *tcon);

#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
extern void cifs_dfs_release_automount_timer(void);
+71 −11
Original line number Diff line number Diff line
@@ -53,6 +53,9 @@
#include "nterr.h"
#include "rfc1002pdu.h"
#include "fscache.h"
#ifdef CONFIG_CIFS_SMB2
#include "smb2proto.h"
#endif

#define CIFS_PORT 445
#define RFC1001_PORT 139
@@ -89,6 +92,7 @@ enum {
	Opt_multiuser, Opt_sloppy, Opt_nosharesock,
	Opt_persistent, Opt_nopersistent,
	Opt_resilient, Opt_noresilient,
	Opt_domainauto,

	/* Mount options which take numeric value */
	Opt_backupuid, Opt_backupgid, Opt_uid,
@@ -96,6 +100,7 @@ enum {
	Opt_dirmode, Opt_port,
	Opt_rsize, Opt_wsize, Opt_actimeo,
	Opt_echo_interval, Opt_max_credits,
	Opt_snapshot,

	/* Mount options which take string value */
	Opt_user, Opt_pass, Opt_ip,
@@ -177,6 +182,7 @@ static const match_table_t cifs_mount_option_tokens = {
	{ Opt_nopersistent, "nopersistenthandles"},
	{ Opt_resilient, "resilienthandles"},
	{ Opt_noresilient, "noresilienthandles"},
	{ Opt_domainauto, "domainauto"},

	{ Opt_backupuid, "backupuid=%s" },
	{ Opt_backupgid, "backupgid=%s" },
@@ -192,6 +198,7 @@ static const match_table_t cifs_mount_option_tokens = {
	{ Opt_actimeo, "actimeo=%s" },
	{ Opt_echo_interval, "echo_interval=%s" },
	{ Opt_max_credits, "max_credits=%s" },
	{ Opt_snapshot, "snapshot=%s" },

	{ Opt_blank_user, "user=" },
	{ Opt_blank_user, "username=" },
@@ -1500,6 +1507,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
		case Opt_noresilient:
			vol->resilient = false; /* already the default */
			break;
		case Opt_domainauto:
			vol->domainauto = true;
			break;

		/* Numeric Values */
		case Opt_backupuid:
@@ -1602,6 +1612,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
			}
			vol->echo_interval = option;
			break;
		case Opt_snapshot:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid snapshot time\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
			vol->snapshot_time = option;
			break;
		case Opt_max_credits:
			if (get_option_ul(args, &option) || (option < 20) ||
			    (option > 60000)) {
@@ -2101,8 +2119,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
	return NULL;
}

static void
cifs_put_tcp_session(struct TCP_Server_Info *server)
void
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
{
	struct task_struct *task;

@@ -2119,6 +2137,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)

	cancel_delayed_work_sync(&server->echo);

#ifdef CONFIG_CIFS_SMB2
	if (from_reconnect)
		/*
		 * Avoid deadlock here: reconnect work calls
		 * cifs_put_tcp_session() at its end. Need to be sure
		 * that reconnect work does nothing with server pointer after
		 * that step.
		 */
		cancel_delayed_work(&server->reconnect);
	else
		cancel_delayed_work_sync(&server->reconnect);
#endif

	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
@@ -2183,6 +2214,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
#ifdef CONFIG_CIFS_SMB2
	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
	mutex_init(&tcp_ses->reconnect_mutex);
#endif
	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
	       sizeof(tcp_ses->srcaddr));
	memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
@@ -2341,7 +2376,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
	spin_unlock(&cifs_tcp_ses_lock);

	sesInfoFree(ses);
	cifs_put_tcp_session(server);
	cifs_put_tcp_session(server, 0);
}

#ifdef CONFIG_KEYS
@@ -2515,7 +2550,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
		mutex_unlock(&ses->session_mutex);

		/* existing SMB ses has a server reference already */
		cifs_put_tcp_session(server);
		cifs_put_tcp_session(server, 0);
		free_xid(xid);
		return ses;
	}
@@ -2549,6 +2584,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
		if (!ses->domainName)
			goto get_ses_fail;
	}
	if (volume_info->domainauto)
		ses->domainAuto = volume_info->domainauto;
	ses->cred_uid = volume_info->cred_uid;
	ses->linux_uid = volume_info->linux_uid;

@@ -2587,7 +2624,7 @@ static int match_tcon(struct cifs_tcon *tcon, const char *unc)
}

static struct cifs_tcon *
cifs_find_tcon(struct cifs_ses *ses, const char *unc)
cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
{
	struct list_head *tmp;
	struct cifs_tcon *tcon;
@@ -2595,8 +2632,14 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
	spin_lock(&cifs_tcp_ses_lock);
	list_for_each(tmp, &ses->tcon_list) {
		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
		if (!match_tcon(tcon, unc))
		if (!match_tcon(tcon, volume_info->UNC))
			continue;

#ifdef CONFIG_CIFS_SMB2
		if (tcon->snapshot_time != volume_info->snapshot_time)
			continue;
#endif /* CONFIG_CIFS_SMB2 */

		++tcon->tc_count;
		spin_unlock(&cifs_tcp_ses_lock);
		return tcon;
@@ -2605,7 +2648,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
	return NULL;
}

static void
void
cifs_put_tcon(struct cifs_tcon *tcon)
{
	unsigned int xid;
@@ -2637,7 +2680,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
	int rc, xid;
	struct cifs_tcon *tcon;

	tcon = cifs_find_tcon(ses, volume_info->UNC);
	tcon = cifs_find_tcon(ses, volume_info);
	if (tcon) {
		cifs_dbg(FYI, "Found match on UNC path\n");
		/* existing tcon already has a reference */
@@ -2658,6 +2701,22 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
		goto out_fail;
	}

	if (volume_info->snapshot_time) {
#ifdef CONFIG_CIFS_SMB2
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "Use SMB2 or later for snapshot mount option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
			tcon->snapshot_time = volume_info->snapshot_time;
#else
		cifs_dbg(VFS, "Snapshot mount option requires SMB2 support\n");
		rc = -EOPNOTSUPP;
		goto out_fail;
#endif /* CONFIG_CIFS_SMB2 */
	}

	tcon->ses = ses;
	if (volume_info->password) {
		tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
@@ -3707,7 +3766,8 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
		/*
		 * cifs_build_path_to_root works only when we have a valid tcon
		 */
		full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
		full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
					tcon->Flags & SMB_SHARE_IS_IN_DFS);
		if (full_path == NULL) {
			rc = -ENOMEM;
			goto mount_fail_check;
@@ -3793,7 +3853,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
		else if (ses)
			cifs_put_smb_ses(ses);
		else
			cifs_put_tcp_session(server);
			cifs_put_tcp_session(server, 0);
		bdi_destroy(&cifs_sb->bdi);
	}

@@ -4104,7 +4164,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
	if (IS_ERR(ses)) {
		tcon = (struct cifs_tcon *)ses;
		cifs_put_tcp_session(master_tcon->ses->server);
		cifs_put_tcp_session(master_tcon->ses->server, 0);
		goto out;
	}

Loading