Commit 05df9192 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents fd860cd7 3363da82
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -777,6 +777,7 @@ struct TCP_Server_Info {
	__le32 session_key_id; /* retrieved from negotiate response and send in session setup request */
	struct session_key session_key;
	unsigned long lstrp; /* when we got last response from this server */
	unsigned long neg_start; /* when negotiate started (jiffies) */
	struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */
#define	CIFS_NEGFLAVOR_UNENCAP	1	/* wct == 17, but no ext_sec */
#define	CIFS_NEGFLAVOR_EXTENDED	2	/* wct == 17, ext_sec bit set */
@@ -1303,6 +1304,7 @@ struct cifs_tcon {
	bool use_persistent:1; /* use persistent instead of durable handles */
	bool no_lease:1;    /* Do not request leases on files or directories */
	bool use_witness:1; /* use witness protocol */
	bool dummy:1; /* dummy tcon used for reconnecting channels */
	__le32 capabilities;
	__u32 share_flags;
	__u32 maximal_access;
+1 −0
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
			struct smb_hdr *out_buf,
			int *bytes_returned);

void smb2_query_server_interfaces(struct work_struct *work);
void
cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
				      bool all_channels);
+5 −10
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
	return rc;
}

static void smb2_query_server_interfaces(struct work_struct *work)
void smb2_query_server_interfaces(struct work_struct *work)
{
	int rc;
	int xid;
@@ -679,12 +679,12 @@ server_unresponsive(struct TCP_Server_Info *server)
	/*
	 * If we're in the process of mounting a share or reconnecting a session
	 * and the server abruptly shut down (e.g. socket wasn't closed, packet
	 * had been ACK'ed but no SMB response), don't wait longer than 20s to
	 * negotiate protocol.
	 * had been ACK'ed but no SMB response), don't wait longer than 20s from
	 * when negotiate actually started.
	 */
	spin_lock(&server->srv_lock);
	if (server->tcpStatus == CifsInNegotiate &&
	    time_after(jiffies, server->lstrp + 20 * HZ)) {
	    time_after(jiffies, server->neg_start + 20 * HZ)) {
		spin_unlock(&server->srv_lock);
		cifs_reconnect(server, false);
		return true;
@@ -2880,20 +2880,14 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
	tcon->max_cached_dirs = ctx->max_cached_dirs;
	tcon->nodelete = ctx->nodelete;
	tcon->local_lease = ctx->local_lease;
	INIT_LIST_HEAD(&tcon->pending_opens);
	tcon->status = TID_GOOD;

	INIT_DELAYED_WORK(&tcon->query_interfaces,
			  smb2_query_server_interfaces);
	if (ses->server->dialect >= SMB30_PROT_ID &&
	    (ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
		/* schedule query interfaces poll */
		queue_delayed_work(cifsiod_wq, &tcon->query_interfaces,
				   (SMB_INTERFACE_POLL_INTERVAL * HZ));
	}
#ifdef CONFIG_CIFS_DFS_UPCALL
	INIT_DELAYED_WORK(&tcon->dfs_cache_work, dfs_cache_refresh);
#endif
	spin_lock(&cifs_tcp_ses_lock);
	list_add(&tcon->tcon_list, &ses->tcon_list);
	spin_unlock(&cifs_tcp_ses_lock);
@@ -4215,6 +4209,7 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,

	server->lstrp = jiffies;
	server->tcpStatus = CifsInNegotiate;
	server->neg_start = jiffies;
	spin_unlock(&server->srv_lock);

	rc = server->ops->negotiate(xid, ses, server);
+7 −10
Original line number Diff line number Diff line
@@ -1824,10 +1824,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
			cifs_errorf(fc, "symlinkroot mount options must be absolute path\n");
			goto cifs_parse_mount_err;
		}
		kfree(ctx->symlinkroot);
		ctx->symlinkroot = kstrdup(param->string, GFP_KERNEL);
		if (!ctx->symlinkroot)
		if (strnlen(param->string, PATH_MAX) == PATH_MAX) {
			cifs_errorf(fc, "symlinkroot path too long (max path length: %u)\n",
				    PATH_MAX - 1);
			goto cifs_parse_mount_err;
		}
		kfree(ctx->symlinkroot);
		ctx->symlinkroot = param->string;
		param->string = NULL;
		break;
	}
	/* case Opt_ignore: - is ignored as expected ... */
@@ -1837,13 +1841,6 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
		goto cifs_parse_mount_err;
	}

	/*
	 * By default resolve all native absolute symlinks relative to "/mnt/".
	 * Same default has drvfs driver running in WSL for resolving SMB shares.
	 */
	if (!ctx->symlinkroot)
		ctx->symlinkroot = kstrdup("/mnt/", GFP_KERNEL);

	return 0;

 cifs_parse_mount_err:
+6 −0
Original line number Diff line number Diff line
@@ -151,6 +151,12 @@ tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace)
#ifdef CONFIG_CIFS_DFS_UPCALL
	INIT_LIST_HEAD(&ret_buf->dfs_ses_list);
#endif
	INIT_LIST_HEAD(&ret_buf->pending_opens);
	INIT_DELAYED_WORK(&ret_buf->query_interfaces,
			  smb2_query_server_interfaces);
#ifdef CONFIG_CIFS_DFS_UPCALL
	INIT_DELAYED_WORK(&ret_buf->dfs_cache_work, dfs_cache_refresh);
#endif

	return ret_buf;
}
Loading