connect.c 140.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *   fs/cifs/connect.c
 *
4
 *   Copyright (C) International Business Machines  Corp., 2002,2011
L
Linus Torvalds 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *   Author(s): Steve French (sfrench@us.ibm.com)
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *   the GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this library; if not, write to the Free Software
S
Steve French 已提交
19
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
L
Linus Torvalds 已提交
20 21 22 23
 */
#include <linux/fs.h>
#include <linux/net.h>
#include <linux/string.h>
24
#include <linux/sched/mm.h>
25
#include <linux/sched/signal.h>
L
Linus Torvalds 已提交
26 27
#include <linux/list.h>
#include <linux/wait.h>
28
#include <linux/slab.h>
L
Linus Torvalds 已提交
29 30 31 32
#include <linux/pagemap.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
#include <linux/mempool.h>
33
#include <linux/delay.h>
34
#include <linux/completion.h>
35
#include <linux/kthread.h>
36
#include <linux/pagevec.h>
37
#include <linux/freezer.h>
38
#include <linux/namei.h>
39
#include <linux/uuid.h>
40
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
41
#include <asm/processor.h>
42
#include <linux/inet.h>
43
#include <linux/module.h>
44
#include <keys/user-type.h>
45
#include <net/ipv6.h>
46
#include <linux/parser.h>
47
#include <linux/bvec.h>
L
Linus Torvalds 已提交
48 49 50 51 52 53 54 55 56
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
#include "ntlmssp.h"
#include "nterr.h"
#include "rfc1002pdu.h"
57
#include "fscache.h"
58
#include "smb2proto.h"
59
#include "smbdirect.h"
60 61 62 63
#include "dns_resolve.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
64
#include "fs_context.h"
L
Linus Torvalds 已提交
65 66

extern mempool_t *cifs_req_poolp;
67
extern bool disable_legacy_dialects;
L
Linus Torvalds 已提交
68

69
/* FIXME: should these be tunable? */
70
#define TLINK_ERROR_EXPIRE	(1 * HZ)
71
#define TLINK_IDLE_EXPIRE	(600 * HZ)
72

73 74 75
/* Drop the connection to not overload the server */
#define NUM_STATUS_IO_TIMEOUT   5

76 77 78 79 80 81
static const match_table_t cifs_mount_option_tokens = {

	{ Opt_user_xattr, "user_xattr" },
	{ Opt_nouser_xattr, "nouser_xattr" },
	{ Opt_forceuid, "forceuid" },
	{ Opt_noforceuid, "noforceuid" },
J
Jeff Layton 已提交
82 83
	{ Opt_forcegid, "forcegid" },
	{ Opt_noforcegid, "noforcegid" },
84 85
	{ Opt_noblocksend, "noblocksend" },
	{ Opt_noautotune, "noautotune" },
86
	{ Opt_nolease, "nolease" },
87 88 89 90
	{ Opt_hard, "hard" },
	{ Opt_soft, "soft" },
	{ Opt_perm, "perm" },
	{ Opt_noperm, "noperm" },
S
Steve French 已提交
91
	{ Opt_nodelete, "nodelete" },
92
	{ Opt_mapchars, "mapchars" }, /* SFU style */
93
	{ Opt_nomapchars, "nomapchars" },
94 95
	{ Opt_mapposix, "mapposix" }, /* SFM style */
	{ Opt_nomapposix, "nomapposix" },
96 97 98 99 100 101 102
	{ Opt_sfu, "sfu" },
	{ Opt_nosfu, "nosfu" },
	{ Opt_nodfs, "nodfs" },
	{ Opt_posixpaths, "posixpaths" },
	{ Opt_noposixpaths, "noposixpaths" },
	{ Opt_nounix, "nounix" },
	{ Opt_nounix, "nolinux" },
103 104 105 106
	{ Opt_nounix, "noposix" },
	{ Opt_unix, "unix" },
	{ Opt_unix, "linux" },
	{ Opt_unix, "posix" },
107 108 109 110
	{ Opt_nocase, "nocase" },
	{ Opt_nocase, "ignorecase" },
	{ Opt_brl, "brl" },
	{ Opt_nobrl, "nobrl" },
S
Steve French 已提交
111 112
	{ Opt_handlecache, "handlecache" },
	{ Opt_nohandlecache, "nohandlecache" },
113 114
	{ Opt_nobrl, "nolock" },
	{ Opt_forcemandatorylock, "forcemandatorylock" },
115
	{ Opt_forcemandatorylock, "forcemand" },
116 117
	{ Opt_setuids, "setuids" },
	{ Opt_nosetuids, "nosetuids" },
118
	{ Opt_setuidfromacl, "idsfromsid" },
119 120 121 122 123 124 125 126 127 128 129
	{ Opt_dynperm, "dynperm" },
	{ Opt_nodynperm, "nodynperm" },
	{ Opt_nohard, "nohard" },
	{ Opt_nosoft, "nosoft" },
	{ Opt_nointr, "nointr" },
	{ Opt_intr, "intr" },
	{ Opt_nostrictsync, "nostrictsync" },
	{ Opt_strictsync, "strictsync" },
	{ Opt_serverino, "serverino" },
	{ Opt_noserverino, "noserverino" },
	{ Opt_rwpidforward, "rwpidforward" },
130
	{ Opt_modesid, "modefromsid" },
131 132 133 134 135 136
	{ Opt_cifsacl, "cifsacl" },
	{ Opt_nocifsacl, "nocifsacl" },
	{ Opt_acl, "acl" },
	{ Opt_noacl, "noacl" },
	{ Opt_locallease, "locallease" },
	{ Opt_sign, "sign" },
137
	{ Opt_ignore_signature, "signloosely" },
138 139 140 141 142
	{ Opt_seal, "seal" },
	{ Opt_noac, "noac" },
	{ Opt_fsc, "fsc" },
	{ Opt_mfsymlinks, "mfsymlinks" },
	{ Opt_multiuser, "multiuser" },
143
	{ Opt_sloppy, "sloppy" },
144
	{ Opt_nosharesock, "nosharesock" },
145 146
	{ Opt_persistent, "persistenthandles"},
	{ Opt_nopersistent, "nopersistenthandles"},
S
Steve French 已提交
147 148
	{ Opt_resilient, "resilienthandles"},
	{ Opt_noresilient, "noresilienthandles"},
149
	{ Opt_domainauto, "domainauto"},
L
Long Li 已提交
150
	{ Opt_rdma, "rdma"},
151 152
	{ Opt_multichannel, "multichannel" },
	{ Opt_nomultichannel, "nomultichannel" },
153 154 155 156 157 158 159 160 161 162

	{ Opt_backupuid, "backupuid=%s" },
	{ Opt_backupgid, "backupgid=%s" },
	{ Opt_uid, "uid=%s" },
	{ Opt_cruid, "cruid=%s" },
	{ Opt_gid, "gid=%s" },
	{ Opt_file_mode, "file_mode=%s" },
	{ Opt_dirmode, "dirmode=%s" },
	{ Opt_dirmode, "dir_mode=%s" },
	{ Opt_port, "port=%s" },
163
	{ Opt_min_enc_offload, "esize=%s" },
164
	{ Opt_blocksize, "bsize=%s" },
165 166 167
	{ Opt_rsize, "rsize=%s" },
	{ Opt_wsize, "wsize=%s" },
	{ Opt_actimeo, "actimeo=%s" },
168
	{ Opt_handletimeout, "handletimeout=%s" },
S
Steve French 已提交
169
	{ Opt_echo_interval, "echo_interval=%s" },
170
	{ Opt_max_credits, "max_credits=%s" },
171
	{ Opt_snapshot, "snapshot=%s" },
172
	{ Opt_max_channels, "max_channels=%s" },
173
	{ Opt_compress, "compress=%s" },
174

175 176
	{ Opt_blank_user, "user=" },
	{ Opt_blank_user, "username=" },
177 178 179
	{ Opt_user, "user=%s" },
	{ Opt_user, "username=%s" },
	{ Opt_blank_pass, "pass=" },
180
	{ Opt_blank_pass, "password=" },
181 182
	{ Opt_pass, "pass=%s" },
	{ Opt_pass, "password=%s" },
183 184
	{ Opt_blank_ip, "ip=" },
	{ Opt_blank_ip, "addr=" },
185 186
	{ Opt_ip, "ip=%s" },
	{ Opt_ip, "addr=%s" },
187 188 189
	{ Opt_ignore, "unc=%s" },
	{ Opt_ignore, "target=%s" },
	{ Opt_ignore, "path=%s" },
190 191 192 193
	{ Opt_domain, "dom=%s" },
	{ Opt_domain, "domain=%s" },
	{ Opt_domain, "workgroup=%s" },
	{ Opt_srcaddr, "srcaddr=%s" },
194
	{ Opt_ignore, "prefixpath=%s" },
195 196 197 198
	{ Opt_iocharset, "iocharset=%s" },
	{ Opt_netbiosname, "netbiosname=%s" },
	{ Opt_servern, "servern=%s" },
	{ Opt_ver, "ver=%s" },
199
	{ Opt_vers, "vers=%s" },
200
	{ Opt_sec, "sec=%s" },
201
	{ Opt_cache, "cache=%s" },
202 203 204

	{ Opt_ignore, "cred" },
	{ Opt_ignore, "credentials" },
205 206
	{ Opt_ignore, "cred=%s" },
	{ Opt_ignore, "credentials=%s" },
207 208 209 210 211 212 213 214 215 216 217 218
	{ Opt_ignore, "guest" },
	{ Opt_ignore, "rw" },
	{ Opt_ignore, "ro" },
	{ Opt_ignore, "suid" },
	{ Opt_ignore, "nosuid" },
	{ Opt_ignore, "exec" },
	{ Opt_ignore, "noexec" },
	{ Opt_ignore, "nodev" },
	{ Opt_ignore, "noauto" },
	{ Opt_ignore, "dev" },
	{ Opt_ignore, "mand" },
	{ Opt_ignore, "nomand" },
219
	{ Opt_ignore, "relatime" },
220
	{ Opt_ignore, "_netdev" },
221
	{ Opt_rootfs, "rootfs" },
222 223 224 225

	{ Opt_err, NULL }
};

226 227
static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
J
Jeff Layton 已提交
228
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
229
static void cifs_prune_tlinks(struct work_struct *work);
230 231
static char *extract_hostname(const char *unc);

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/*
 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
 * get their ip addresses changed at some point.
 *
 * This should be called with server->srv_mutex held.
 */
#ifdef CONFIG_CIFS_DFS_UPCALL
static int reconn_set_ipaddr(struct TCP_Server_Info *server)
{
	int rc;
	int len;
	char *unc, *ipaddr = NULL;

	if (!server->hostname)
		return -EINVAL;

	len = strlen(server->hostname) + 3;

	unc = kmalloc(len, GFP_KERNEL);
	if (!unc) {
		cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
		return -ENOMEM;
	}
255
	scnprintf(unc, len, "\\\\%s", server->hostname);
256 257 258 259 260 261 262 263 264 265

	rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
	kfree(unc);

	if (rc < 0) {
		cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
			 __func__, server->hostname, rc);
		return rc;
	}

266
	spin_lock(&cifs_tcp_ses_lock);
267 268
	rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
				  strlen(ipaddr));
269
	spin_unlock(&cifs_tcp_ses_lock);
270 271 272 273 274 275 276 277 278 279 280
	kfree(ipaddr);

	return !rc ? -1 : 0;
}
#else
static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
{
	return 0;
}
#endif

281 282
#ifdef CONFIG_CIFS_DFS_UPCALL
/* These functions must be called with server->srv_mutex held */
283 284 285 286
static void reconn_set_next_dfs_target(struct TCP_Server_Info *server,
				       struct cifs_sb_info *cifs_sb,
				       struct dfs_cache_tgt_list *tgt_list,
				       struct dfs_cache_tgt_iterator **tgt_it)
287 288 289
{
	const char *name;

290
	if (!cifs_sb || !cifs_sb->origin_fullpath)
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
		return;

	if (!*tgt_it) {
		*tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
	} else {
		*tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
		if (!*tgt_it)
			*tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
	}

	cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);

	name = dfs_cache_get_tgt_name(*tgt_it);

	kfree(server->hostname);

	server->hostname = extract_hostname(name);
D
Dan Carpenter 已提交
308 309 310 311
	if (IS_ERR(server->hostname)) {
		cifs_dbg(FYI,
			 "%s: failed to extract hostname from target: %ld\n",
			 __func__, PTR_ERR(server->hostname));
312 313 314 315
	}
}

static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
316
					   struct dfs_cache_tgt_list *tl)
317 318 319 320 321 322
{
	if (!cifs_sb->origin_fullpath)
		return -EOPNOTSUPP;
	return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
}
#endif
L
Linus Torvalds 已提交
323

324 325 326 327 328 329 330 331
/*
 * cifs tcp session reconnection
 *
 * mark tcp session as reconnecting so temporarily locked
 * mark all smb sessions as reconnecting for tcp session
 * reconnect tcp session
 * wake up waiters on reconnection? - (not needed currently)
 */
P
Pavel Shilovsky 已提交
332
int
L
Linus Torvalds 已提交
333 334 335
cifs_reconnect(struct TCP_Server_Info *server)
{
	int rc = 0;
336
	struct list_head *tmp, *tmp2;
337 338
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
S
Steve French 已提交
339
	struct mid_q_entry *mid_entry;
340
	struct list_head retry_list;
341
#ifdef CONFIG_CIFS_DFS_UPCALL
342
	struct super_block *sb = NULL;
343 344
	struct cifs_sb_info *cifs_sb = NULL;
	struct dfs_cache_tgt_list tgt_list = {0};
345 346
	struct dfs_cache_tgt_iterator *tgt_it = NULL;
#endif
347

L
Linus Torvalds 已提交
348
	spin_lock(&GlobalMid_Lock);
349 350
	server->nr_targets = 1;
#ifdef CONFIG_CIFS_DFS_UPCALL
351
	spin_unlock(&GlobalMid_Lock);
352
	sb = cifs_get_tcp_super(server);
353 354
	if (IS_ERR(sb)) {
		rc = PTR_ERR(sb);
355 356
		cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
			 __func__, rc);
357
		sb = NULL;
358
	} else {
359
		cifs_sb = CIFS_SB(sb);
360
		rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list);
361 362 363 364 365 366
		if (rc) {
			cifs_sb = NULL;
			if (rc != -EOPNOTSUPP) {
				cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
						__func__);
			}
367 368 369 370 371 372
		} else {
			server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
		}
	}
	cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
		 server->nr_targets);
373
	spin_lock(&GlobalMid_Lock);
374
#endif
375
	if (server->tcpStatus == CifsExiting) {
S
Steve French 已提交
376
		/* the demux thread will exit normally
L
Linus Torvalds 已提交
377 378
		next time through the loop */
		spin_unlock(&GlobalMid_Lock);
379 380
#ifdef CONFIG_CIFS_DFS_UPCALL
		dfs_cache_free_tgts(&tgt_list);
381
		cifs_put_tcp_super(sb);
382
#endif
383
		wake_up(&server->response_q);
L
Linus Torvalds 已提交
384 385 386 387 388
		return rc;
	} else
		server->tcpStatus = CifsNeedReconnect;
	spin_unlock(&GlobalMid_Lock);
	server->maxBuf = 0;
389
	server->max_read = 0;
L
Linus Torvalds 已提交
390

391
	cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
S
Steve French 已提交
392
	trace_smb3_reconnect(server->CurrentMid, server->hostname);
L
Linus Torvalds 已提交
393 394 395

	/* before reconnecting the tcp session, mark the smb session (uid)
		and the tid bad so they are not used until reconnected */
396 397
	cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
		 __func__);
398
	spin_lock(&cifs_tcp_ses_lock);
399
	list_for_each(tmp, &server->smb_ses_list) {
400
		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
401
		ses->need_reconnect = true;
402
		list_for_each(tmp2, &ses->tcon_list) {
403
			tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
S
Steve French 已提交
404
			tcon->need_reconnect = true;
L
Linus Torvalds 已提交
405
		}
A
Aurelien Aptel 已提交
406 407
		if (ses->tcon_ipc)
			ses->tcon_ipc->need_reconnect = true;
L
Linus Torvalds 已提交
408
	}
409
	spin_unlock(&cifs_tcp_ses_lock);
410

L
Linus Torvalds 已提交
411
	/* do not want to be sending data on a socket we are freeing */
412
	cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
J
Jeff Layton 已提交
413
	mutex_lock(&server->srv_mutex);
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
	if (server->ssocket) {
		cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
			 server->ssocket->state, server->ssocket->flags);
		kernel_sock_shutdown(server->ssocket, SHUT_WR);
		cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
			 server->ssocket->state, server->ssocket->flags);
		sock_release(server->ssocket);
		server->ssocket = NULL;
	}
	server->sequence_number = 0;
	server->session_estab = false;
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
	server->lstrp = jiffies;
L
Linus Torvalds 已提交
429

430
	/* mark submitted MIDs for retry and issue callback */
431
	INIT_LIST_HEAD(&retry_list);
432
	cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
L
Linus Torvalds 已提交
433
	spin_lock(&GlobalMid_Lock);
434 435
	list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
436
		kref_get(&mid_entry->refcount);
437 438
		if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
			mid_entry->mid_state = MID_RETRY_NEEDED;
439
		list_move(&mid_entry->qhead, &retry_list);
440
		mid_entry->mid_flags |= MID_DELETED;
441 442
	}
	spin_unlock(&GlobalMid_Lock);
443
	mutex_unlock(&server->srv_mutex);
444

445
	cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
446 447
	list_for_each_safe(tmp, tmp2, &retry_list) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
448 449
		list_del_init(&mid_entry->qhead);
		mid_entry->callback(mid_entry);
450
		cifs_mid_q_entry_release(mid_entry);
L
Linus Torvalds 已提交
451 452
	}

453 454
	if (cifs_rdma_enabled(server)) {
		mutex_lock(&server->srv_mutex);
455
		smbd_destroy(server);
456 457
		mutex_unlock(&server->srv_mutex);
	}
458

459
	do {
460
		try_to_freeze();
461

462
		mutex_lock(&server->srv_mutex);
463
#ifdef CONFIG_CIFS_DFS_UPCALL
464 465 466 467 468
		/*
		 * Set up next DFS target server (if any) for reconnect. If DFS
		 * feature is disabled, then we will retry last server we
		 * connected to before.
		 */
469
		reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it);
470 471 472 473 474 475 476
#endif
		rc = reconn_set_ipaddr(server);
		if (rc) {
			cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
				 __func__, rc);
		}

477 478 479 480
		if (cifs_rdma_enabled(server))
			rc = smbd_reconnect(server);
		else
			rc = generic_ip_connect(server);
S
Steve French 已提交
481
		if (rc) {
482
			cifs_dbg(FYI, "reconnect error %d\n", rc);
483
			mutex_unlock(&server->srv_mutex);
484
			msleep(3000);
L
Linus Torvalds 已提交
485 486
		} else {
			atomic_inc(&tcpSesReconnectCount);
487
			set_credits(server, 1);
L
Linus Torvalds 已提交
488
			spin_lock(&GlobalMid_Lock);
489
			if (server->tcpStatus != CifsExiting)
490
				server->tcpStatus = CifsNeedNegotiate;
S
Steve French 已提交
491
			spin_unlock(&GlobalMid_Lock);
492
			mutex_unlock(&server->srv_mutex);
L
Linus Torvalds 已提交
493
		}
494
	} while (server->tcpStatus == CifsNeedReconnect);
495

496 497 498 499 500
#ifdef CONFIG_CIFS_DFS_UPCALL
	if (tgt_it) {
		rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
						    tgt_it);
		if (rc) {
501
			cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
502 503 504 505
				 __func__, rc);
		}
		rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
		if (rc) {
506
			cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
507 508
				 __func__, rc);
		}
509
		dfs_cache_free_tgts(&tgt_list);
510

511
	}
512

513
	cifs_put_tcp_super(sb);
514
#endif
515 516 517
	if (server->tcpStatus == CifsNeedNegotiate)
		mod_delayed_work(cifsiod_wq, &server->echo, 0);

518
	wake_up(&server->response_q);
L
Linus Torvalds 已提交
519 520 521
	return rc;
}

522 523 524 525 526 527
static void
cifs_echo_request(struct work_struct *work)
{
	int rc;
	struct TCP_Server_Info *server = container_of(work,
					struct TCP_Server_Info, echo.work);
528 529 530 531 532 533 534 535 536 537
	unsigned long echo_interval;

	/*
	 * If we need to renegotiate, set echo interval to zero to
	 * immediately call echo service where we can renegotiate.
	 */
	if (server->tcpStatus == CifsNeedNegotiate)
		echo_interval = 0;
	else
		echo_interval = server->echo_interval;
538

539
	/*
540 541
	 * We cannot send an echo if it is disabled.
	 * Also, no need to ping if we got a response recently.
542
	 */
543 544

	if (server->tcpStatus == CifsNeedReconnect ||
545 546
	    server->tcpStatus == CifsExiting ||
	    server->tcpStatus == CifsNew ||
547
	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
S
Steve French 已提交
548
	    time_before(jiffies, server->lstrp + echo_interval - HZ))
549 550
		goto requeue_echo;

551
	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
552
	if (rc)
553 554
		cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
			 server->hostname);
555 556

requeue_echo:
557
	queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
558 559
}

560
static bool
561
allocate_buffers(struct TCP_Server_Info *server)
562
{
563 564 565
	if (!server->bigbuf) {
		server->bigbuf = (char *)cifs_buf_get();
		if (!server->bigbuf) {
566
			cifs_server_dbg(VFS, "No memory for large SMB response\n");
567 568 569 570
			msleep(3000);
			/* retry will check if exiting */
			return false;
		}
571
	} else if (server->large_buf) {
572
		/* we are reusing a dirty large buf, clear its start */
573
		memset(server->bigbuf, 0, HEADER_SIZE(server));
574 575
	}

576 577 578
	if (!server->smallbuf) {
		server->smallbuf = (char *)cifs_small_buf_get();
		if (!server->smallbuf) {
579
			cifs_server_dbg(VFS, "No memory for SMB response\n");
580 581 582 583 584 585 586
			msleep(1000);
			/* retry will check if exiting */
			return false;
		}
		/* beginning of smb buffer is cleared in our buf_get */
	} else {
		/* if existing small buf clear beginning */
587
		memset(server->smallbuf, 0, HEADER_SIZE(server));
588 589 590 591 592
	}

	return true;
}

593 594 595
static bool
server_unresponsive(struct TCP_Server_Info *server)
{
596
	/*
597
	 * We need to wait 3 echo intervals to make sure we handle such
598 599
	 * situations right:
	 * 1s  client sends a normal SMB request
600
	 * 2s  client gets a response
601 602 603 604 605 606
	 * 30s echo workqueue job pops, and decides we got a response recently
	 *     and don't need to send another
	 * ...
	 * 65s kernel_recvmsg times out, and we see that we haven't gotten
	 *     a response in >60s.
	 */
607 608
	if ((server->tcpStatus == CifsGood ||
	    server->tcpStatus == CifsNeedNegotiate) &&
609
	    time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
610 611
		cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
			 (3 * server->echo_interval) / HZ);
612 613 614 615 616 617 618
		cifs_reconnect(server);
		return true;
	}

	return false;
}

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
static inline bool
zero_credits(struct TCP_Server_Info *server)
{
	int val;

	spin_lock(&server->req_lock);
	val = server->credits + server->echo_credits + server->oplock_credits;
	if (server->in_flight == 0 && val == 0) {
		spin_unlock(&server->req_lock);
		return true;
	}
	spin_unlock(&server->req_lock);
	return false;
}

634 635
static int
cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
636
{
J
Jeff Layton 已提交
637 638
	int length = 0;
	int total_read;
639

640 641
	smb_msg->msg_control = NULL;
	smb_msg->msg_controllen = 0;
642

643
	for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
644 645
		try_to_freeze();

646 647 648 649 650 651
		/* reconnect if no credits and no requests in flight */
		if (zero_credits(server)) {
			cifs_reconnect(server);
			return -ECONNABORTED;
		}

652 653
		if (server_unresponsive(server))
			return -ECONNABORTED;
654 655 656 657
		if (cifs_rdma_enabled(server) && server->smbd_conn)
			length = smbd_recv(server->smbd_conn, smb_msg);
		else
			length = sock_recvmsg(server->ssocket, smb_msg, 0);
658

659 660
		if (server->tcpStatus == CifsExiting)
			return -ESHUTDOWN;
661

662
		if (server->tcpStatus == CifsNeedReconnect) {
663
			cifs_reconnect(server);
664 665 666 667 668 669
			return -ECONNABORTED;
		}

		if (length == -ERESTARTSYS ||
		    length == -EAGAIN ||
		    length == -EINTR) {
670 671 672 673 674 675 676
			/*
			 * Minimum sleep to prevent looping, allowing socket
			 * to clear and app threads to set tcpStatus
			 * CifsNeedReconnect if server hung.
			 */
			usleep_range(1000, 2000);
			length = 0;
J
Jeff Layton 已提交
677
			continue;
678 679 680
		}

		if (length <= 0) {
681
			cifs_dbg(FYI, "Received no data or error: %d\n", length);
682
			cifs_reconnect(server);
683
			return -ECONNABORTED;
684 685
		}
	}
J
Jeff Layton 已提交
686
	return total_read;
687 688
}

J
Jeff Layton 已提交
689 690 691
int
cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
		      unsigned int to_read)
692
{
693 694
	struct msghdr smb_msg;
	struct kvec iov = {.iov_base = buf, .iov_len = to_read};
695
	iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
696

697 698
	return cifs_readv_from_socket(server, &smb_msg);
}
699

700 701
int
cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
L
Long Li 已提交
702
	unsigned int page_offset, unsigned int to_read)
703 704
{
	struct msghdr smb_msg;
L
Long Li 已提交
705 706
	struct bio_vec bv = {
		.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
707
	iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
708
	return cifs_readv_from_socket(server, &smb_msg);
709 710
}

711
static bool
J
Jeff Layton 已提交
712
is_smb_response(struct TCP_Server_Info *server, unsigned char type)
713 714 715 716 717 718
{
	/*
	 * The first byte big endian of the length field,
	 * is actually not part of the length but the type
	 * with the most common, zero, as regular data.
	 */
J
Jeff Layton 已提交
719 720 721 722 723
	switch (type) {
	case RFC1002_SESSION_MESSAGE:
		/* Regular SMB response */
		return true;
	case RFC1002_SESSION_KEEP_ALIVE:
724
		cifs_dbg(FYI, "RFC 1002 session keep alive\n");
J
Jeff Layton 已提交
725 726
		break;
	case RFC1002_POSITIVE_SESSION_RESPONSE:
727
		cifs_dbg(FYI, "RFC 1002 positive session response\n");
J
Jeff Layton 已提交
728 729
		break;
	case RFC1002_NEGATIVE_SESSION_RESPONSE:
730 731 732 733
		/*
		 * We get this from Windows 98 instead of an error on
		 * SMB negprot response.
		 */
734
		cifs_dbg(FYI, "RFC 1002 negative session response\n");
735 736 737 738 739 740 741 742
		/* give server a second to clean up */
		msleep(1000);
		/*
		 * Always try 445 first on reconnect since we get NACK
		 * on some if we ever connected to port 139 (the NACK
		 * is since we do not begin with RFC1001 session
		 * initialize frame).
		 */
J
Jeff Layton 已提交
743
		cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
744
		cifs_reconnect(server);
J
Jeff Layton 已提交
745 746
		break;
	default:
747
		cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
748 749 750
		cifs_reconnect(server);
	}

J
Jeff Layton 已提交
751
	return false;
752 753
}

J
Jeff Layton 已提交
754 755
void
dequeue_mid(struct mid_q_entry *mid, bool malformed)
756
{
757
#ifdef CONFIG_CIFS_STATS2
758
	mid->when_received = jiffies;
759
#endif
760 761
	spin_lock(&GlobalMid_Lock);
	if (!malformed)
762
		mid->mid_state = MID_RESPONSE_RECEIVED;
763
	else
764
		mid->mid_state = MID_RESPONSE_MALFORMED;
765 766 767 768 769
	/*
	 * Trying to handle/dequeue a mid after the send_recv()
	 * function has finished processing it is a bug.
	 */
	if (mid->mid_flags & MID_DELETED)
J
Joe Perches 已提交
770
		pr_warn_once("trying to dequeue a deleted mid\n");
771
	else {
772
		list_del_init(&mid->qhead);
773 774
		mid->mid_flags |= MID_DELETED;
	}
775
	spin_unlock(&GlobalMid_Lock);
776
}
777

778 779 780 781 782 783 784 785 786 787 788 789 790 791
static unsigned int
smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;

	/*
	 * SMB1 does not use credits.
	 */
	if (server->vals->header_preamble_size)
		return 0;

	return le16_to_cpu(shdr->CreditRequest);
}

792 793
static void
handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
794
	   char *buf, int malformed)
795
{
796 797
	if (server->ops->check_trans2 &&
	    server->ops->check_trans2(mid, server, buf, malformed))
798
		return;
799
	mid->credits_received = smb2_get_credits_from_hdr(buf, server);
800
	mid->resp_buf = buf;
801
	mid->large_buf = server->large_buf;
802 803 804 805 806 807 808 809
	/* Was previous buf put in mpx struct for multi-rsp? */
	if (!mid->multiRsp) {
		/* smb buffer will be freed by user thread */
		if (server->large_buf)
			server->bigbuf = NULL;
		else
			server->smallbuf = NULL;
	}
810
	dequeue_mid(mid, malformed);
811 812
}

813 814 815 816 817 818 819 820 821
static void clean_demultiplex_info(struct TCP_Server_Info *server)
{
	int length;

	/* take it off the list, if it's not already */
	spin_lock(&cifs_tcp_ses_lock);
	list_del_init(&server->tcp_ses_list);
	spin_unlock(&cifs_tcp_ses_lock);

822 823
	cancel_delayed_work_sync(&server->echo);

824 825 826 827 828
	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
	wake_up_all(&server->response_q);

829
	/* check if we have blocked requests that need to free */
P
Pavel Shilovsky 已提交
830
	spin_lock(&server->req_lock);
831 832
	if (server->credits <= 0)
		server->credits = 1;
P
Pavel Shilovsky 已提交
833
	spin_unlock(&server->req_lock);
834 835 836 837 838 839 840 841 842 843
	/*
	 * Although there should not be any requests blocked on this queue it
	 * can not hurt to be paranoid and try to wake up requests that may
	 * haven been blocked when more than 50 at time were on the wire to the
	 * same server - they now will see the session is in exit state and get
	 * out of SendReceive.
	 */
	wake_up_all(&server->request_q);
	/* give those requests time to exit */
	msleep(125);
844 845
	if (cifs_rdma_enabled(server))
		smbd_destroy(server);
846 847 848 849 850 851 852 853 854 855 856 857 858 859
	if (server->ssocket) {
		sock_release(server->ssocket);
		server->ssocket = NULL;
	}

	if (!list_empty(&server->pending_mid_q)) {
		struct list_head dispose_list;
		struct mid_q_entry *mid_entry;
		struct list_head *tmp, *tmp2;

		INIT_LIST_HEAD(&dispose_list);
		spin_lock(&GlobalMid_Lock);
		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
860
			cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
861
			kref_get(&mid_entry->refcount);
862
			mid_entry->mid_state = MID_SHUTDOWN;
863
			list_move(&mid_entry->qhead, &dispose_list);
864
			mid_entry->mid_flags |= MID_DELETED;
865 866 867 868 869 870
		}
		spin_unlock(&GlobalMid_Lock);

		/* now walk dispose list and issue callbacks */
		list_for_each_safe(tmp, tmp2, &dispose_list) {
			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
871
			cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
872 873
			list_del_init(&mid_entry->qhead);
			mid_entry->callback(mid_entry);
874
			cifs_mid_q_entry_release(mid_entry);
875 876 877 878 879 880 881 882 883 884 885 886 887 888
		}
		/* 1/8th of sec is more than enough time for them to exit */
		msleep(125);
	}

	if (!list_empty(&server->pending_mid_q)) {
		/*
		 * mpx threads have not exited yet give them at least the smb
		 * send timeout time for long ops.
		 *
		 * Due to delays on oplock break requests, we need to wait at
		 * least 45 seconds before giving up on a request getting a
		 * response and going ahead and killing cifsd.
		 */
889
		cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
890 891 892 893 894 895 896 897 898 899 900 901
		msleep(46000);
		/*
		 * If threads still have not exited they are probably never
		 * coming home not much else we can do but free the memory.
		 */
	}

	kfree(server->hostname);
	kfree(server);

	length = atomic_dec_return(&tcpSesAllocCount);
	if (length > 0)
902
		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
903 904
}

905 906 907 908 909
static int
standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
	int length;
	char *buf = server->smallbuf;
910
	unsigned int pdu_length = server->pdu_size;
911 912

	/* make sure this will fit in a large buffer */
913 914
	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
		server->vals->header_preamble_size) {
915
		cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
916
		cifs_reconnect(server);
917
		return -ECONNABORTED;
918 919 920 921 922
	}

	/* switch to large buffer if too big for a small one */
	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
		server->large_buf = true;
923
		memcpy(server->bigbuf, buf, server->total_read);
924 925 926 927
		buf = server->bigbuf;
	}

	/* now read the rest */
928
	length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
929 930 931
				       pdu_length - HEADER_SIZE(server) + 1
				       + server->vals->header_preamble_size);

932 933 934 935
	if (length < 0)
		return length;
	server->total_read += length;

936
	dump_smb(buf, server->total_read);
937

938 939 940 941 942 943 944 945 946
	return cifs_handle_standard(server, mid);
}

int
cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
	char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
	int length;

947 948 949 950 951 952 953 954 955
	/*
	 * We know that we received enough to get to the MID as we
	 * checked the pdu_length earlier. Now check to see
	 * if the rest of the header is OK. We borrow the length
	 * var for the rest of the loop to avoid a new stack var.
	 *
	 * 48 bytes is enough to display the header and a little bit
	 * into the payload for debugging purposes.
	 */
956
	length = server->ops->check_message(buf, server->total_read, server);
957 958 959 960
	if (length != 0)
		cifs_dump_mem("Bad SMB: ", buf,
			min_t(unsigned int, server->total_read, 48));

961 962 963 964 965 966
	if (server->ops->is_session_expired &&
	    server->ops->is_session_expired(buf)) {
		cifs_reconnect(server);
		return -1;
	}

P
Pavel Shilovsky 已提交
967
	if (server->ops->is_status_pending &&
968
	    server->ops->is_status_pending(buf, server))
P
Pavel Shilovsky 已提交
969 970
		return -1;

971 972
	if (!mid)
		return length;
973

974
	handle_mid(mid, server, buf, length);
975
	return 0;
976 977
}

978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
static void
smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;

	/*
	 * SMB1 does not use credits.
	 */
	if (server->vals->header_preamble_size)
		return;

	if (shdr->CreditRequest) {
		spin_lock(&server->req_lock);
		server->credits += le16_to_cpu(shdr->CreditRequest);
		spin_unlock(&server->req_lock);
		wake_up(&server->request_q);
	}
}


L
Linus Torvalds 已提交
998
static int
999
cifs_demultiplex_thread(void *p)
L
Linus Torvalds 已提交
1000
{
1001
	int i, num_mids, length;
1002
	struct TCP_Server_Info *server = p;
1003
	unsigned int pdu_length;
1004
	unsigned int next_offset;
1005
	char *buf = NULL;
1006
	struct task_struct *task_to_wake = NULL;
1007 1008
	struct mid_q_entry *mids[MAX_COMPOUND];
	char *bufs[MAX_COMPOUND];
1009
	unsigned int noreclaim_flag, num_io_timeout = 0;
L
Linus Torvalds 已提交
1010

1011
	noreclaim_flag = memalloc_noreclaim_save();
1012
	cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
1013 1014 1015

	length = atomic_inc_return(&tcpSesAllocCount);
	if (length > 1)
1016
		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
L
Linus Torvalds 已提交
1017

1018
	set_freezable();
1019
	allow_kernel_signal(SIGKILL);
1020
	while (server->tcpStatus != CifsExiting) {
1021 1022
		if (try_to_freeze())
			continue;
1023

1024
		if (!allocate_buffers(server))
1025
			continue;
1026

1027 1028
		server->large_buf = false;
		buf = server->smallbuf;
1029
		pdu_length = 4; /* enough to get RFC1001 header */
1030

J
Jeff Layton 已提交
1031
		length = cifs_read_from_socket(server, buf, pdu_length);
J
Jeff Layton 已提交
1032
		if (length < 0)
L
Linus Torvalds 已提交
1033
			continue;
1034 1035 1036 1037 1038

		if (server->vals->header_preamble_size == 0)
			server->total_read = 0;
		else
			server->total_read = length;
L
Linus Torvalds 已提交
1039

1040 1041 1042 1043
		/*
		 * The right amount was read from socket - 4 bytes,
		 * so we can now interpret the length field.
		 */
1044
		pdu_length = get_rfc1002_length(buf);
1045

1046
		cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
J
Jeff Layton 已提交
1047
		if (!is_smb_response(server, buf[0]))
S
Steve French 已提交
1048
			continue;
1049 1050
next_pdu:
		server->pdu_size = pdu_length;
1051

1052
		/* make sure we have enough to get to the MID */
1053
		if (server->pdu_size < HEADER_SIZE(server) - 1 -
1054
		    server->vals->header_preamble_size) {
1055
			cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
1056
				 server->pdu_size);
1057 1058
			cifs_reconnect(server);
			continue;
1059
		}
1060

1061
		/* read down to the MID */
1062 1063 1064 1065
		length = cifs_read_from_socket(server,
			     buf + server->vals->header_preamble_size,
			     HEADER_SIZE(server) - 1
			     - server->vals->header_preamble_size);
1066
		if (length < 0)
1067
			continue;
1068
		server->total_read += length;
L
Linus Torvalds 已提交
1069

1070 1071 1072 1073 1074 1075
		if (server->ops->next_header) {
			next_offset = server->ops->next_header(buf);
			if (next_offset)
				server->pdu_size = next_offset;
		}

1076 1077 1078 1079
		memset(mids, 0, sizeof(mids));
		memset(bufs, 0, sizeof(bufs));
		num_mids = 0;

1080 1081 1082 1083
		if (server->ops->is_transform_hdr &&
		    server->ops->receive_transform &&
		    server->ops->is_transform_hdr(buf)) {
			length = server->ops->receive_transform(server,
1084 1085 1086
								mids,
								bufs,
								&num_mids);
1087
		} else {
1088 1089
			mids[0] = server->ops->find_mid(server, buf);
			bufs[0] = buf;
1090
			num_mids = 1;
1091

1092 1093
			if (!mids[0] || !mids[0]->receive)
				length = standard_receive3(server, mids[0]);
1094
			else
1095
				length = mids[0]->receive(server, mids[0]);
1096
		}
1097

1098
		if (length < 0) {
1099 1100 1101
			for (i = 0; i < num_mids; i++)
				if (mids[i])
					cifs_mid_q_entry_release(mids[i]);
J
Jeff Layton 已提交
1102
			continue;
1103
		}
L
Linus Torvalds 已提交
1104

1105 1106 1107 1108 1109 1110 1111 1112 1113 1114
		if (server->ops->is_status_io_timeout &&
		    server->ops->is_status_io_timeout(buf)) {
			num_io_timeout++;
			if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
				cifs_reconnect(server);
				num_io_timeout = 0;
				continue;
			}
		}

1115
		server->lstrp = jiffies;
S
Sachin Prabhu 已提交
1116

1117 1118 1119
		for (i = 0; i < num_mids; i++) {
			if (mids[i] != NULL) {
				mids[i]->resp_buf_size = server->pdu_size;
1120

1121 1122 1123 1124 1125 1126 1127
				if (!mids[i]->multiRsp || mids[i]->multiEnd)
					mids[i]->callback(mids[i]);

				cifs_mid_q_entry_release(mids[i]);
			} else if (server->ops->is_oplock_break &&
				   server->ops->is_oplock_break(bufs[i],
								server)) {
1128
				smb2_add_credits_from_hdr(bufs[i], server);
1129 1130
				cifs_dbg(FYI, "Received oplock break\n");
			} else {
J
Joe Perches 已提交
1131 1132
				cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
						atomic_read(&midCount));
1133 1134
				cifs_dump_mem("Received Data is: ", bufs[i],
					      HEADER_SIZE(server));
1135
				smb2_add_credits_from_hdr(bufs[i], server);
1136
#ifdef CONFIG_CIFS_DEBUG2
1137 1138 1139 1140
				if (server->ops->dump_detail)
					server->ops->dump_detail(bufs[i],
								 server);
				cifs_dump_mids(server);
1141
#endif /* CIFS_DEBUG2 */
1142
			}
1143
		}
1144

1145 1146 1147 1148 1149 1150 1151 1152
		if (pdu_length > server->pdu_size) {
			if (!allocate_buffers(server))
				continue;
			pdu_length -= server->pdu_size;
			server->total_read = 0;
			server->large_buf = false;
			buf = server->smallbuf;
			goto next_pdu;
1153 1154 1155
		}
	} /* end while !EXITING */

1156
	/* buffer usually freed in free_mid - need to free it here on exit */
1157 1158 1159
	cifs_buf_release(server->bigbuf);
	if (server->smallbuf) /* no sense logging a debug message if NULL */
		cifs_small_buf_release(server->smallbuf);
L
Linus Torvalds 已提交
1160

1161
	task_to_wake = xchg(&server->tsk, NULL);
1162
	clean_demultiplex_info(server);
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173

	/* if server->tsk was NULL then wait for a signal before exiting */
	if (!task_to_wake) {
		set_current_state(TASK_INTERRUPTIBLE);
		while (!signal_pending(current)) {
			schedule();
			set_current_state(TASK_INTERRUPTIBLE);
		}
		set_current_state(TASK_RUNNING);
	}

1174
	memalloc_noreclaim_restore(noreclaim_flag);
1175
	module_put_and_exit(0);
L
Linus Torvalds 已提交
1176 1177
}

1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
/* extract the host portion of the UNC string */
static char *
extract_hostname(const char *unc)
{
	const char *src;
	char *dst, *delim;
	unsigned int len;

	/* skip double chars at beginning of string */
	/* BB: check validity of these bytes? */
1188 1189 1190 1191 1192 1193
	if (strlen(unc) < 3)
		return ERR_PTR(-EINVAL);
	for (src = unc; *src && *src == '\\'; src++)
		;
	if (!*src)
		return ERR_PTR(-EINVAL);
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210

	/* delimiter between hostname and sharename is always '\\' now */
	delim = strchr(src, '\\');
	if (!delim)
		return ERR_PTR(-EINVAL);

	len = delim - src;
	dst = kmalloc((len + 1), GFP_KERNEL);
	if (dst == NULL)
		return ERR_PTR(-ENOMEM);

	memcpy(dst, src, len);
	dst[len] = '\0';

	return dst;
}

1211 1212 1213 1214 1215 1216 1217 1218
static int get_option_ul(substring_t args[], unsigned long *option)
{
	int rc;
	char *string;

	string = match_strdup(args);
	if (string == NULL)
		return -ENOMEM;
1219
	rc = kstrtoul(string, 0, option);
1220 1221 1222 1223 1224
	kfree(string);

	return rc;
}

1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
static int get_option_uid(substring_t args[], kuid_t *result)
{
	unsigned long value;
	kuid_t uid;
	int rc;

	rc = get_option_ul(args, &value);
	if (rc)
		return rc;

	uid = make_kuid(current_user_ns(), value);
	if (!uid_valid(uid))
		return -EINVAL;

	*result = uid;
	return 0;
}

static int get_option_gid(substring_t args[], kgid_t *result)
{
	unsigned long value;
	kgid_t gid;
	int rc;

	rc = get_option_ul(args, &value);
	if (rc)
		return rc;

	gid = make_kgid(current_user_ns(), value);
	if (!gid_valid(gid))
		return -EINVAL;

	*result = gid;
	return 0;
}
1260

1261 1262 1263 1264 1265
/*
 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
 * fields with the result. Returns 0 on success and an error otherwise.
 */
static int
1266
cifs_parse_devname(const char *devname, struct smb3_fs_context *ctx)
1267 1268 1269 1270 1271
{
	char *pos;
	const char *delims = "/\\";
	size_t len;

1272
	if (unlikely(!devname || !*devname)) {
J
Joe Perches 已提交
1273
		cifs_dbg(VFS, "Device name not specified\n");
1274 1275 1276
		return -EINVAL;
	}

1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
	/* make sure we have a valid UNC double delimiter prefix */
	len = strspn(devname, delims);
	if (len != 2)
		return -EINVAL;

	/* find delimiter between host and sharename */
	pos = strpbrk(devname + 2, delims);
	if (!pos)
		return -EINVAL;

	/* skip past delimiter */
	++pos;

	/* now go until next delimiter or end of string */
	len = strcspn(pos, delims);

	/* move "pos" up to delimiter or NULL */
	pos += len;
1295 1296
	ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
	if (!ctx->UNC)
1297 1298
		return -ENOMEM;

1299
	convert_delimiter(ctx->UNC, '\\');
1300

1301 1302 1303 1304 1305 1306
	/* skip any delimiter */
	if (*pos == '/' || *pos == '\\')
		pos++;

	/* If pos is NULL then no prepath */
	if (!*pos)
1307 1308
		return 0;

1309 1310
	ctx->prepath = kstrdup(pos, GFP_KERNEL);
	if (!ctx->prepath)
1311 1312 1313 1314 1315
		return -ENOMEM;

	return 0;
}

L
Linus Torvalds 已提交
1316
static int
1317
cifs_parse_mount_options(const char *mountdata, const char *devname,
1318
			 struct smb3_fs_context *ctx, bool is_smb3)
L
Linus Torvalds 已提交
1319
{
1320
	char *data, *end;
1321
	char *mountdata_copy = NULL, *options;
L
Linus Torvalds 已提交
1322 1323
	unsigned int  temp_len, i, j;
	char separator[2];
1324 1325 1326 1327
	short int override_uid = -1;
	short int override_gid = -1;
	bool uid_specified = false;
	bool gid_specified = false;
1328 1329
	bool sloppy = false;
	char *invalid = NULL;
J
Jeff Layton 已提交
1330
	char *nodename = utsname()->nodename;
1331 1332 1333
	char *string = NULL;
	char *tmp_end, *value;
	char delim;
1334
	bool got_ip = false;
1335
	bool got_version = false;
1336
	unsigned short port = 0;
1337
	struct sockaddr *dstaddr = (struct sockaddr *)&ctx->dstaddr;
L
Linus Torvalds 已提交
1338 1339

	separator[0] = ',';
1340
	separator[1] = 0;
1341
	delim = separator[0];
L
Linus Torvalds 已提交
1342

1343 1344
	/* ensure we always start with zeroed-out ctx */
	memset(ctx, 0, sizeof(*ctx));
1345

J
Jeff Layton 已提交
1346 1347 1348 1349 1350
	/*
	 * does not have to be perfect mapping since field is
	 * informational, only used for servers that do not support
	 * port 445 and it can be overridden at mount time
	 */
1351
	memset(ctx->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1352
	for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
1353
		ctx->source_rfc1001_name[i] = toupper(nodename[i]);
J
Jeff Layton 已提交
1354

1355
	ctx->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1356 1357
	/* null target name indicates to use *SMBSERVR default called name
	   if we end up sending RFC1001 session initialize */
1358 1359 1360 1361 1362
	ctx->target_rfc1001_name[0] = 0;
	ctx->cred_uid = current_uid();
	ctx->linux_uid = current_uid();
	ctx->linux_gid = current_gid();
	ctx->bsize = 1024 * 1024; /* can improve cp performance significantly */
1363 1364 1365 1366 1367 1368
	/*
	 * default to SFM style remapping of seven reserved characters
	 * unless user overrides it or we negotiate CIFS POSIX where
	 * it is unnecessary.  Can not simultaneously use more than one mapping
	 * since then readdir could list files that open could not open
	 */
1369
	ctx->remap = true;
1370

1371
	/* default to only allowing write access to owner of the mount */
1372
	ctx->dir_mode = ctx->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
L
Linus Torvalds 已提交
1373

1374
	/* ctx->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1375
	/* default is always to request posix paths. */
1376
	ctx->posix_paths = 1;
1377
	/* default to using server inode numbers where available */
1378
	ctx->server_ino = 1;
1379

1380
	/* default is to use strict cifs caching semantics */
1381
	ctx->strict_io = true;
1382

1383
	ctx->actimeo = CIFS_DEF_ACTIMEO;
1384

1385
	/* Most clients set timeout to 0, allows server to use its default */
1386
	ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1387

1388
	/* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1389 1390
	ctx->ops = &smb30_operations;
	ctx->vals = &smbdefault_values;
1391

1392
	ctx->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
R
Rabin Vincent 已提交
1393

1394
	/* default to no multichannel (single server connection) */
1395 1396
	ctx->multichannel = false;
	ctx->max_channels = 1;
1397

1398 1399 1400 1401 1402 1403
	if (!mountdata)
		goto cifs_parse_mount_err;

	mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
	if (!mountdata_copy)
		goto cifs_parse_mount_err;
L
Linus Torvalds 已提交
1404

1405
	options = mountdata_copy;
1406
	end = options + strlen(options);
1407

1408
	if (strncmp(options, "sep=", 4) == 0) {
S
Steve French 已提交
1409
		if (options[4] != 0) {
L
Linus Torvalds 已提交
1410 1411 1412
			separator[0] = options[4];
			options += 5;
		} else {
1413
			cifs_dbg(FYI, "Null separator not allowed\n");
L
Linus Torvalds 已提交
1414 1415
		}
	}
1416 1417
	ctx->backupuid_specified = false; /* no backup intent for a user */
	ctx->backupgid_specified = false; /* no backup intent for a group */
1418

1419
	switch (cifs_parse_devname(devname, ctx)) {
1420 1421 1422
	case 0:
		break;
	case -ENOMEM:
J
Joe Perches 已提交
1423
		cifs_dbg(VFS, "Unable to allocate memory for devname\n");
1424 1425
		goto cifs_parse_mount_err;
	case -EINVAL:
J
Joe Perches 已提交
1426
		cifs_dbg(VFS, "Malformed UNC in devname\n");
1427 1428
		goto cifs_parse_mount_err;
	default:
J
Joe Perches 已提交
1429
		cifs_dbg(VFS, "Unknown error parsing devname\n");
1430
		goto cifs_parse_mount_err;
1431 1432
	}

L
Linus Torvalds 已提交
1433
	while ((data = strsep(&options, separator)) != NULL) {
1434 1435 1436 1437
		substring_t args[MAX_OPT_ARGS];
		unsigned long option;
		int token;

L
Linus Torvalds 已提交
1438 1439 1440
		if (!*data)
			continue;

1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
		token = match_token(data, cifs_mount_option_tokens, args);

		switch (token) {

		/* Ingnore the following */
		case Opt_ignore:
			break;

		/* Boolean values */
		case Opt_user_xattr:
1451
			ctx->no_xattr = 0;
1452 1453
			break;
		case Opt_nouser_xattr:
1454
			ctx->no_xattr = 1;
1455 1456
			break;
		case Opt_forceuid:
1457
			override_uid = 1;
1458 1459
			break;
		case Opt_noforceuid:
1460
			override_uid = 0;
1461
			break;
J
Jeff Layton 已提交
1462 1463 1464 1465 1466 1467
		case Opt_forcegid:
			override_gid = 1;
			break;
		case Opt_noforcegid:
			override_gid = 0;
			break;
1468
		case Opt_noblocksend:
1469
			ctx->noblocksnd = 1;
1470 1471
			break;
		case Opt_noautotune:
1472
			ctx->noautotune = 1;
1473
			break;
1474
		case Opt_nolease:
1475
			ctx->no_lease = 1;
1476
			break;
1477
		case Opt_hard:
1478
			ctx->retry = 1;
1479 1480
			break;
		case Opt_soft:
1481
			ctx->retry = 0;
1482 1483
			break;
		case Opt_perm:
1484
			ctx->noperm = 0;
1485 1486
			break;
		case Opt_noperm:
1487
			ctx->noperm = 1;
1488
			break;
S
Steve French 已提交
1489
		case Opt_nodelete:
1490
			ctx->nodelete = 1;
S
Steve French 已提交
1491
			break;
1492
		case Opt_mapchars:
1493 1494
			ctx->sfu_remap = true;
			ctx->remap = false; /* disable SFM mapping */
1495 1496
			break;
		case Opt_nomapchars:
1497
			ctx->sfu_remap = false;
1498 1499
			break;
		case Opt_mapposix:
1500 1501
			ctx->remap = true;
			ctx->sfu_remap = false; /* disable SFU mapping */
1502 1503
			break;
		case Opt_nomapposix:
1504
			ctx->remap = false;
1505 1506
			break;
		case Opt_sfu:
1507
			ctx->sfu_emul = 1;
1508 1509
			break;
		case Opt_nosfu:
1510
			ctx->sfu_emul = 0;
1511 1512
			break;
		case Opt_nodfs:
1513
			ctx->nodfs = 1;
1514
			break;
1515 1516
		case Opt_rootfs:
#ifdef CONFIG_CIFS_ROOT
1517
			ctx->rootfs = true;
1518 1519
#endif
			break;
1520
		case Opt_posixpaths:
1521
			ctx->posix_paths = 1;
1522 1523
			break;
		case Opt_noposixpaths:
1524
			ctx->posix_paths = 0;
1525 1526
			break;
		case Opt_nounix:
1527
			if (ctx->linux_ext)
1528 1529
				cifs_dbg(VFS,
					"conflicting unix mount options\n");
1530
			ctx->no_linux_ext = 1;
1531
			break;
1532
		case Opt_unix:
1533
			if (ctx->no_linux_ext)
1534 1535
				cifs_dbg(VFS,
					"conflicting unix mount options\n");
1536
			ctx->linux_ext = 1;
1537
			break;
1538
		case Opt_nocase:
1539
			ctx->nocase = 1;
1540 1541
			break;
		case Opt_brl:
1542
			ctx->nobrl =  0;
1543 1544
			break;
		case Opt_nobrl:
1545
			ctx->nobrl =  1;
1546 1547
			/*
			 * turn off mandatory locking in mode
1548
			 * if remote locking is turned off since the
1549 1550
			 * local vfs will do advisory
			 */
1551
			if (ctx->file_mode ==
1552
				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1553
				ctx->file_mode = S_IALLUGO;
1554
			break;
S
Steve French 已提交
1555
		case Opt_nohandlecache:
1556
			ctx->nohandlecache = 1;
S
Steve French 已提交
1557 1558
			break;
		case Opt_handlecache:
1559
			ctx->nohandlecache = 0;
S
Steve French 已提交
1560
			break;
1561
		case Opt_forcemandatorylock:
1562
			ctx->mand_lock = 1;
1563 1564
			break;
		case Opt_setuids:
1565
			ctx->setuids = 1;
1566 1567
			break;
		case Opt_nosetuids:
1568
			ctx->setuids = 0;
1569
			break;
1570
		case Opt_setuidfromacl:
1571
			ctx->setuidfromacl = 1;
1572
			break;
1573
		case Opt_dynperm:
1574
			ctx->dynperm = true;
1575 1576
			break;
		case Opt_nodynperm:
1577
			ctx->dynperm = false;
1578 1579
			break;
		case Opt_nohard:
1580
			ctx->retry = 0;
1581 1582
			break;
		case Opt_nosoft:
1583
			ctx->retry = 1;
1584 1585
			break;
		case Opt_nointr:
1586
			ctx->intr = 0;
1587 1588
			break;
		case Opt_intr:
1589
			ctx->intr = 1;
1590 1591
			break;
		case Opt_nostrictsync:
1592
			ctx->nostrictsync = 1;
1593 1594
			break;
		case Opt_strictsync:
1595
			ctx->nostrictsync = 0;
1596 1597
			break;
		case Opt_serverino:
1598
			ctx->server_ino = 1;
1599 1600
			break;
		case Opt_noserverino:
1601
			ctx->server_ino = 0;
1602 1603
			break;
		case Opt_rwpidforward:
1604
			ctx->rwpidforward = 1;
1605
			break;
1606
		case Opt_modesid:
1607
			ctx->mode_ace = 1;
1608
			break;
1609
		case Opt_cifsacl:
1610
			ctx->cifs_acl = 1;
1611 1612
			break;
		case Opt_nocifsacl:
1613
			ctx->cifs_acl = 0;
1614 1615
			break;
		case Opt_acl:
1616
			ctx->no_psx_acl = 0;
1617 1618
			break;
		case Opt_noacl:
1619
			ctx->no_psx_acl = 1;
1620 1621
			break;
		case Opt_locallease:
1622
			ctx->local_lease = 1;
1623 1624
			break;
		case Opt_sign:
1625
			ctx->sign = true;
1626
			break;
1627
		case Opt_ignore_signature:
1628 1629
			ctx->sign = true;
			ctx->ignore_signature = true;
1630
			break;
1631
		case Opt_seal:
1632
			/* we do not do the following in secFlags because seal
1633 1634
			 * is a per tree connection (mount) not a per socket
			 * or per-smb connection option in the protocol
1635
			 * ctx->secFlg |= CIFSSEC_MUST_SEAL;
1636
			 */
1637
			ctx->seal = 1;
1638 1639
			break;
		case Opt_noac:
J
Joe Perches 已提交
1640
			pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1641 1642
			break;
		case Opt_fsc:
1643
#ifndef CONFIG_CIFS_FSCACHE
1644
			cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
1645
			goto cifs_parse_mount_err;
1646
#endif
1647
			ctx->fsc = true;
1648 1649
			break;
		case Opt_mfsymlinks:
1650
			ctx->mfsymlinks = true;
1651 1652
			break;
		case Opt_multiuser:
1653
			ctx->multiuser = true;
1654
			break;
1655 1656 1657
		case Opt_sloppy:
			sloppy = true;
			break;
1658
		case Opt_nosharesock:
1659
			ctx->nosharesock = true;
1660
			break;
1661
		case Opt_nopersistent:
1662 1663
			ctx->nopersistent = true;
			if (ctx->persistent) {
1664 1665 1666 1667 1668 1669
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_persistent:
1670 1671
			ctx->persistent = true;
			if ((ctx->nopersistent) || (ctx->resilient)) {
1672 1673 1674 1675 1676
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
S
Steve French 已提交
1677
		case Opt_resilient:
1678 1679
			ctx->resilient = true;
			if (ctx->persistent) {
S
Steve French 已提交
1680 1681 1682 1683 1684 1685
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_noresilient:
1686
			ctx->resilient = false; /* already the default */
S
Steve French 已提交
1687
			break;
1688
		case Opt_domainauto:
1689
			ctx->domainauto = true;
1690
			break;
L
Long Li 已提交
1691
		case Opt_rdma:
1692
			ctx->rdma = true;
L
Long Li 已提交
1693
			break;
1694
		case Opt_multichannel:
1695
			ctx->multichannel = true;
1696
			/* if number of channels not specified, default to 2 */
1697 1698
			if (ctx->max_channels < 2)
				ctx->max_channels = 2;
1699 1700
			break;
		case Opt_nomultichannel:
1701 1702
			ctx->multichannel = false;
			ctx->max_channels = 1;
1703
			break;
1704
		case Opt_compress:
1705
			ctx->compression = UNKNOWN_TYPE;
1706 1707 1708
			cifs_dbg(VFS,
				"SMB3 compression support is experimental\n");
			break;
1709 1710 1711

		/* Numeric Values */
		case Opt_backupuid:
1712
			if (get_option_uid(args, &ctx->backupuid)) {
1713 1714
				cifs_dbg(VFS, "%s: Invalid backupuid value\n",
					 __func__);
1715 1716
				goto cifs_parse_mount_err;
			}
1717
			ctx->backupuid_specified = true;
1718 1719
			break;
		case Opt_backupgid:
1720
			if (get_option_gid(args, &ctx->backupgid)) {
1721 1722
				cifs_dbg(VFS, "%s: Invalid backupgid value\n",
					 __func__);
1723 1724
				goto cifs_parse_mount_err;
			}
1725
			ctx->backupgid_specified = true;
1726 1727
			break;
		case Opt_uid:
1728
			if (get_option_uid(args, &ctx->linux_uid)) {
1729 1730
				cifs_dbg(VFS, "%s: Invalid uid value\n",
					 __func__);
1731 1732 1733 1734 1735
				goto cifs_parse_mount_err;
			}
			uid_specified = true;
			break;
		case Opt_cruid:
1736
			if (get_option_uid(args, &ctx->cred_uid)) {
1737 1738
				cifs_dbg(VFS, "%s: Invalid cruid value\n",
					 __func__);
1739 1740 1741 1742
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_gid:
1743
			if (get_option_gid(args, &ctx->linux_gid)) {
1744 1745
				cifs_dbg(VFS, "%s: Invalid gid value\n",
					 __func__);
1746 1747 1748 1749 1750 1751
				goto cifs_parse_mount_err;
			}
			gid_specified = true;
			break;
		case Opt_file_mode:
			if (get_option_ul(args, &option)) {
1752 1753
				cifs_dbg(VFS, "%s: Invalid file_mode value\n",
					 __func__);
1754 1755
				goto cifs_parse_mount_err;
			}
1756
			ctx->file_mode = option;
1757 1758 1759
			break;
		case Opt_dirmode:
			if (get_option_ul(args, &option)) {
1760 1761
				cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
					 __func__);
1762 1763
				goto cifs_parse_mount_err;
			}
1764
			ctx->dir_mode = option;
1765 1766
			break;
		case Opt_port:
1767 1768
			if (get_option_ul(args, &option) ||
			    option > USHRT_MAX) {
1769 1770
				cifs_dbg(VFS, "%s: Invalid port value\n",
					 __func__);
1771 1772
				goto cifs_parse_mount_err;
			}
1773
			port = (unsigned short)option;
1774
			break;
1775 1776 1777 1778 1779
		case Opt_min_enc_offload:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
				goto cifs_parse_mount_err;
			}
1780
			ctx->min_offload = option;
1781
			break;
1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799
		case Opt_blocksize:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid blocksize value\n",
					__func__);
				goto cifs_parse_mount_err;
			}
			/*
			 * inode blocksize realistically should never need to be
			 * less than 16K or greater than 16M and default is 1MB.
			 * Note that small inode block sizes (e.g. 64K) can lead
			 * to very poor performance of common tools like cp and scp
			 */
			if ((option < CIFS_MAX_MSGSIZE) ||
			   (option > (4 * SMB3_DEFAULT_IOSIZE))) {
				cifs_dbg(VFS, "%s: Invalid blocksize\n",
					__func__);
				goto cifs_parse_mount_err;
			}
1800
			ctx->bsize = option;
1801
			break;
1802 1803
		case Opt_rsize:
			if (get_option_ul(args, &option)) {
1804 1805
				cifs_dbg(VFS, "%s: Invalid rsize value\n",
					 __func__);
1806
				goto cifs_parse_mount_err;
1807
			}
1808
			ctx->rsize = option;
1809 1810 1811
			break;
		case Opt_wsize:
			if (get_option_ul(args, &option)) {
1812 1813
				cifs_dbg(VFS, "%s: Invalid wsize value\n",
					 __func__);
1814 1815
				goto cifs_parse_mount_err;
			}
1816
			ctx->wsize = option;
1817 1818 1819
			break;
		case Opt_actimeo:
			if (get_option_ul(args, &option)) {
1820 1821
				cifs_dbg(VFS, "%s: Invalid actimeo value\n",
					 __func__);
1822 1823
				goto cifs_parse_mount_err;
			}
1824 1825
			ctx->actimeo = HZ * option;
			if (ctx->actimeo > CIFS_MAX_ACTIMEO) {
1826
				cifs_dbg(VFS, "attribute cache timeout too large\n");
1827 1828 1829
				goto cifs_parse_mount_err;
			}
			break;
1830 1831 1832 1833 1834 1835
		case Opt_handletimeout:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
1836 1837
			ctx->handle_timeout = option;
			if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
1838 1839 1840 1841
				cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
				goto cifs_parse_mount_err;
			}
			break;
S
Steve French 已提交
1842 1843 1844 1845 1846 1847
		case Opt_echo_interval:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid echo interval value\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
1848
			ctx->echo_interval = option;
S
Steve French 已提交
1849
			break;
1850 1851 1852 1853 1854 1855
		case Opt_snapshot:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid snapshot time\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
1856
			ctx->snapshot_time = option;
1857
			break;
1858 1859 1860 1861 1862 1863 1864
		case Opt_max_credits:
			if (get_option_ul(args, &option) || (option < 20) ||
			    (option > 60000)) {
				cifs_dbg(VFS, "%s: Invalid max_credits value\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
1865
			ctx->max_credits = option;
1866
			break;
1867 1868 1869 1870 1871 1872 1873
		case Opt_max_channels:
			if (get_option_ul(args, &option) || option < 1 ||
				option > CIFS_MAX_CHANNELS) {
				cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
					 __func__, CIFS_MAX_CHANNELS);
				goto cifs_parse_mount_err;
			}
1874
			ctx->max_channels = option;
1875
			break;
1876 1877 1878

		/* String Arguments */

1879 1880
		case Opt_blank_user:
			/* null user, ie. anonymous authentication */
1881 1882
			ctx->nullauth = 1;
			ctx->username = NULL;
1883
			break;
1884 1885 1886 1887 1888
		case Opt_user:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1889 1890
			if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
							CIFS_MAX_USERNAME_LEN) {
J
Joe Perches 已提交
1891
				pr_warn("username too long\n");
1892 1893
				goto cifs_parse_mount_err;
			}
1894

1895 1896 1897
			kfree(ctx->username);
			ctx->username = kstrdup(string, GFP_KERNEL);
			if (!ctx->username)
1898 1899 1900 1901 1902 1903 1904 1905
				goto cifs_parse_mount_err;
			break;
		case Opt_blank_pass:
			/* passwords have to be handled differently
			 * to allow the character used for deliminator
			 * to be passed within them
			 */

1906 1907 1908 1909 1910 1911 1912 1913
			/*
			 * Check if this is a case where the  password
			 * starts with a delimiter
			 */
			tmp_end = strchr(data, '=');
			tmp_end++;
			if (!(tmp_end < end && tmp_end[1] == delim)) {
				/* No it is not. Set the password to NULL */
1914 1915
				kfree_sensitive(ctx->password);
				ctx->password = NULL;
1916 1917
				break;
			}
1918
			fallthrough;	/* to Opt_pass below */
1919
		case Opt_pass:
1920 1921
			/* Obtain the value string */
			value = strchr(data, '=');
1922
			value++;
1923 1924 1925 1926 1927 1928 1929 1930

			/* Set tmp_end to end of the string */
			tmp_end = (char *) value + strlen(value);

			/* Check if following character is the deliminator
			 * If yes, we have encountered a double deliminator
			 * reset the NULL character to the deliminator
			 */
1931
			if (tmp_end < end && tmp_end[1] == delim) {
1932 1933
				tmp_end[0] = delim;

1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949
				/* Keep iterating until we get to a single
				 * deliminator OR the end
				 */
				while ((tmp_end = strchr(tmp_end, delim))
					!= NULL && (tmp_end[1] == delim)) {
						tmp_end = (char *) &tmp_end[2];
				}

				/* Reset var options to point to next element */
				if (tmp_end) {
					tmp_end[0] = '\0';
					options = (char *) &tmp_end[1];
				} else
					/* Reached the end of the mount option
					 * string */
					options = end;
1950 1951
			}

1952
			kfree_sensitive(ctx->password);
1953 1954
			/* Now build new password string */
			temp_len = strlen(value);
1955 1956
			ctx->password = kzalloc(temp_len+1, GFP_KERNEL);
			if (ctx->password == NULL) {
J
Joe Perches 已提交
1957
				pr_warn("no memory for password\n");
1958 1959 1960 1961
				goto cifs_parse_mount_err;
			}

			for (i = 0, j = 0; i < temp_len; i++, j++) {
1962
				ctx->password[j] = value[i];
1963 1964 1965 1966 1967
				if ((value[i] == delim) &&
				     value[i+1] == delim)
					/* skip the second deliminator */
					i++;
			}
1968
			ctx->password[j] = '\0';
1969
			break;
1970
		case Opt_blank_ip:
1971 1972
			/* FIXME: should this be an error instead? */
			got_ip = false;
1973
			break;
1974 1975 1976 1977 1978
		case Opt_ip:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1979 1980
			if (!cifs_convert_address(dstaddr, string,
					strlen(string))) {
J
Joe Perches 已提交
1981
				pr_err("bad ip= option (%s)\n", string);
1982 1983
				goto cifs_parse_mount_err;
			}
1984
			got_ip = true;
1985 1986 1987 1988 1989 1990
			break;
		case Opt_domain:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1991 1992
			if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
					== CIFS_MAX_DOMAINNAME_LEN) {
J
Joe Perches 已提交
1993
				pr_warn("domain name too long\n");
1994 1995 1996
				goto cifs_parse_mount_err;
			}

1997 1998 1999
			kfree(ctx->domainname);
			ctx->domainname = kstrdup(string, GFP_KERNEL);
			if (!ctx->domainname) {
J
Joe Perches 已提交
2000
				pr_warn("no memory for domainname\n");
2001 2002
				goto cifs_parse_mount_err;
			}
2003
			cifs_dbg(FYI, "Domain name set\n");
2004 2005 2006 2007 2008 2009
			break;
		case Opt_srcaddr:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2010
			if (!cifs_convert_address(
2011
					(struct sockaddr *)&ctx->srcaddr,
2012
					string, strlen(string))) {
J
Joe Perches 已提交
2013
				pr_warn("Could not parse srcaddr: %s\n",
2014
					string);
2015 2016 2017 2018 2019 2020 2021 2022
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_iocharset:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2023
			if (strnlen(string, 1024) >= 65) {
J
Joe Perches 已提交
2024
				pr_warn("iocharset name too long\n");
2025 2026 2027
				goto cifs_parse_mount_err;
			}

2028
			 if (strncasecmp(string, "default", 7) != 0) {
2029 2030
				kfree(ctx->iocharset);
				ctx->iocharset = kstrdup(string,
2031
							 GFP_KERNEL);
2032
				if (!ctx->iocharset) {
J
Joe Perches 已提交
2033
					pr_warn("no memory for charset\n");
2034 2035 2036 2037 2038 2039
					goto cifs_parse_mount_err;
				}
			}
			/* if iocharset not set then load_nls_default
			 * is used by caller
			 */
2040
			 cifs_dbg(FYI, "iocharset set to %s\n", string);
2041 2042 2043 2044 2045 2046
			break;
		case Opt_netbiosname:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2047
			memset(ctx->source_rfc1001_name, 0x20,
2048 2049 2050 2051 2052 2053 2054 2055 2056 2057
				RFC1001_NAME_LEN);
			/*
			 * FIXME: are there cases in which a comma can
			 * be valid in workstation netbios name (and
			 * need special handling)?
			 */
			for (i = 0; i < RFC1001_NAME_LEN; i++) {
				/* don't ucase netbiosname for user */
				if (string[i] == 0)
					break;
2058
				ctx->source_rfc1001_name[i] = string[i];
2059 2060 2061 2062 2063
			}
			/* The string has 16th byte zero still from
			 * set at top of the function
			 */
			if (i == RFC1001_NAME_LEN && string[i] != 0)
J
Joe Perches 已提交
2064
				pr_warn("netbiosname longer than 15 truncated\n");
2065 2066 2067 2068 2069 2070 2071 2072
			break;
		case Opt_servern:
			/* servernetbiosname specified override *SMBSERVER */
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

			/* last byte, type, is 0x20 for servr type */
2073
			memset(ctx->target_rfc1001_name, 0x20,
2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084
				RFC1001_NAME_LEN_WITH_NULL);

			/* BB are there cases in which a comma can be
			   valid in this workstation netbios name
			   (and need special handling)? */

			/* user or mount helper must uppercase the
			   netbios name */
			for (i = 0; i < 15; i++) {
				if (string[i] == 0)
					break;
2085
				ctx->target_rfc1001_name[i] = string[i];
2086 2087 2088 2089
			}
			/* The string has 16th byte zero still from
			   set at top of the function  */
			if (i == RFC1001_NAME_LEN && string[i] != 0)
J
Joe Perches 已提交
2090
				pr_warn("server netbiosname longer than 15 truncated\n");
2091 2092
			break;
		case Opt_ver:
2093
			/* version of mount userspace tools, not dialect */
2094 2095 2096 2097
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2098
			/* If interface changes in mount.cifs bump to new ver */
2099
			if (strncasecmp(string, "1", 1) == 0) {
2100
				if (strlen(string) > 1) {
J
Joe Perches 已提交
2101 2102
					pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
						string);
2103 2104
					goto cifs_parse_mount_err;
				}
2105 2106 2107 2108
				/* This is the default */
				break;
			}
			/* For all other value, error */
J
Joe Perches 已提交
2109
			pr_warn("Invalid mount helper version specified\n");
2110
			goto cifs_parse_mount_err;
2111
		case Opt_vers:
2112
			/* protocol version (dialect) */
2113 2114 2115 2116
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2117
			if (cifs_parse_smb_version(string, ctx, is_smb3) != 0)
2118
				goto cifs_parse_mount_err;
2119
			got_version = true;
2120
			break;
2121 2122 2123 2124 2125
		case Opt_sec:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2126
			if (cifs_parse_security_flavors(string, ctx) != 0)
2127 2128
				goto cifs_parse_mount_err;
			break;
2129 2130 2131 2132 2133
		case Opt_cache:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2134
			if (cifs_parse_cache_flavor(string, ctx) != 0)
2135 2136
				goto cifs_parse_mount_err;
			break;
2137
		default:
2138 2139 2140 2141 2142 2143
			/*
			 * An option we don't recognize. Save it off for later
			 * if we haven't already found one
			 */
			if (!invalid)
				invalid = data;
2144
			break;
L
Linus Torvalds 已提交
2145
		}
2146 2147 2148
		/* Free up any allocated string */
		kfree(string);
		string = NULL;
L
Linus Torvalds 已提交
2149
	}
J
Jeff Layton 已提交
2150

2151
	if (!sloppy && invalid) {
J
Joe Perches 已提交
2152
		pr_err("Unknown mount option \"%s\"\n", invalid);
2153 2154 2155
		goto cifs_parse_mount_err;
	}

2156
	if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
L
Long Li 已提交
2157 2158 2159 2160
		cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
		goto cifs_parse_mount_err;
	}

2161 2162
#ifndef CONFIG_KEYS
	/* Muliuser mounts require CONFIG_KEYS support */
2163
	if (ctx->multiuser) {
2164
		cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
2165
		goto cifs_parse_mount_err;
J
Jeff Layton 已提交
2166
	}
2167
#endif
2168
	if (!ctx->UNC) {
2169
		cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
2170 2171
		goto cifs_parse_mount_err;
	}
J
Jeff Layton 已提交
2172

2173
	/* make sure UNC has a share name */
2174
	if (!strchr(ctx->UNC + 3, '\\')) {
2175
		cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
2176 2177 2178
		goto cifs_parse_mount_err;
	}

2179
	if (!got_ip) {
2180 2181 2182
		int len;
		const char *slash;

2183
		/* No ip= option specified? Try to get it from UNC */
2184
		/* Use the address part of the UNC. */
2185 2186 2187
		slash = strchr(&ctx->UNC[2], '\\');
		len = slash - &ctx->UNC[2];
		if (!cifs_convert_address(dstaddr, &ctx->UNC[2], len)) {
J
Joe Perches 已提交
2188
			pr_err("Unable to determine destination address\n");
2189 2190 2191 2192 2193 2194
			goto cifs_parse_mount_err;
		}
	}

	/* set the port that we got earlier */
	cifs_set_port(dstaddr, port);
L
Linus Torvalds 已提交
2195

2196
	if (uid_specified)
2197
		ctx->override_uid = override_uid;
2198
	else if (override_uid == 1)
J
Joe Perches 已提交
2199
		pr_notice("ignoring forceuid mount option specified with no uid= option\n");
2200 2201

	if (gid_specified)
2202
		ctx->override_gid = override_gid;
2203
	else if (override_gid == 1)
J
Joe Perches 已提交
2204
		pr_notice("ignoring forcegid mount option specified with no gid= option\n");
2205

2206
	if (got_version == false)
J
Joe Perches 已提交
2207
		pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
2208

2209
	kfree(mountdata_copy);
L
Linus Torvalds 已提交
2210
	return 0;
2211

2212
out_nomem:
2213
	pr_warn("Could not allocate temporary buffer\n");
2214
cifs_parse_mount_err:
2215
	kfree(string);
2216 2217
	kfree(mountdata_copy);
	return 1;
L
Linus Torvalds 已提交
2218 2219
}

2220 2221 2222 2223
/** Returns true if srcaddr isn't specified and rhs isn't
 * specified, or if srcaddr is specified and
 * matches the IP address of the rhs argument.
 */
2224 2225
bool
cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
{
	switch (srcaddr->sa_family) {
	case AF_UNSPEC:
		return (rhs->sa_family == AF_UNSPEC);
	case AF_INET: {
		struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
		struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
		return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
	}
	case AF_INET6: {
		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
2237
		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
2238 2239 2240 2241 2242 2243 2244 2245
		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
	}
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
}

2246 2247 2248 2249 2250 2251 2252 2253
/*
 * If no port is specified in addr structure, we try to match with 445 port
 * and if it fails - with 139 ports. It should be called only if address
 * families of server and addr are equal.
 */
static bool
match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
{
2254
	__be16 port, *sport;
2255

2256 2257 2258 2259
	/* SMBDirect manages its own ports, don't match it here */
	if (server->rdma)
		return true;

2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283
	switch (addr->sa_family) {
	case AF_INET:
		sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
		port = ((struct sockaddr_in *) addr)->sin_port;
		break;
	case AF_INET6:
		sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
		port = ((struct sockaddr_in6 *) addr)->sin6_port;
		break;
	default:
		WARN_ON(1);
		return false;
	}

	if (!port) {
		port = htons(CIFS_PORT);
		if (port == *sport)
			return true;

		port = htons(RFC1001_PORT);
	}

	return port == *sport;
}
2284

2285
static bool
2286 2287
match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
	      struct sockaddr *srcaddr)
2288 2289
{
	switch (addr->sa_family) {
2290 2291 2292 2293 2294 2295
	case AF_INET: {
		struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
		struct sockaddr_in *srv_addr4 =
					(struct sockaddr_in *)&server->dstaddr;

		if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
2296 2297
			return false;
		break;
2298 2299 2300 2301 2302 2303
	}
	case AF_INET6: {
		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
		struct sockaddr_in6 *srv_addr6 =
					(struct sockaddr_in6 *)&server->dstaddr;

2304
		if (!ipv6_addr_equal(&addr6->sin6_addr,
2305
				     &srv_addr6->sin6_addr))
2306
			return false;
2307
		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
2308 2309 2310
			return false;
		break;
	}
2311 2312 2313 2314
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
2315

2316
	if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
2317 2318
		return false;

2319 2320 2321
	return true;
}

2322
static bool
2323
match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
2324
{
2325
	/*
2326
	 * The select_sectype function should either return the ctx->sectype
2327 2328 2329
	 * that was specified, or "Unspecified" if that sectype was not
	 * compatible with the given NEGOTIATE request.
	 */
2330
	if (server->ops->select_sectype(server, ctx->sectype)
S
Sachin Prabhu 已提交
2331
	     == Unspecified)
2332 2333
		return false;

2334 2335 2336 2337 2338
	/*
	 * Now check if signing mode is acceptable. No need to check
	 * global_secflags at this point since if MUST_SIGN is set then
	 * the server->sign had better be too.
	 */
2339
	if (ctx->sign && !server->sign)
2340
		return false;
2341 2342 2343 2344

	return true;
}

2345
static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
2346
{
2347
	struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
2348

2349
	if (ctx->nosharesock)
2350 2351
		return 0;

2352
	/* If multidialect negotiation see if existing sessions match one */
2353
	if (strcmp(ctx->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2354 2355
		if (server->vals->protocol_id < SMB30_PROT_ID)
			return 0;
2356
	} else if (strcmp(ctx->vals->version_string,
2357 2358 2359
		   SMBDEFAULT_VERSION_STRING) == 0) {
		if (server->vals->protocol_id < SMB21_PROT_ID)
			return 0;
2360
	} else if ((server->vals != ctx->vals) || (server->ops != ctx->ops))
2361 2362
		return 0;

2363 2364 2365 2366
	if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
		return 0;

	if (!match_address(server, addr,
2367
			   (struct sockaddr *)&ctx->srcaddr))
2368 2369 2370 2371 2372
		return 0;

	if (!match_port(server, addr))
		return 0;

2373
	if (!match_security(server, ctx))
2374 2375
		return 0;

2376
	if (server->echo_interval != ctx->echo_interval * HZ)
S
Steve French 已提交
2377 2378
		return 0;

2379
	if (server->rdma != ctx->rdma)
L
Long Li 已提交
2380 2381
		return 0;

2382
	if (server->ignore_signature != ctx->ignore_signature)
2383 2384
		return 0;

2385
	if (server->min_offload != ctx->min_offload)
2386 2387
		return 0;

2388 2389 2390
	return 1;
}

P
Paulo Alcantara 已提交
2391
struct TCP_Server_Info *
2392
cifs_find_tcp_session(struct smb3_fs_context *ctx)
L
Linus Torvalds 已提交
2393
{
2394 2395
	struct TCP_Server_Info *server;

2396
	spin_lock(&cifs_tcp_ses_lock);
2397
	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
2398 2399 2400 2401
		/*
		 * Skip ses channels since they're only handled in lower layers
		 * (e.g. cifs_send_recv).
		 */
2402
		if (server->is_channel || !match_server(server, ctx))
2403 2404
			continue;

2405
		++server->srv_count;
2406
		spin_unlock(&cifs_tcp_ses_lock);
2407
		cifs_dbg(FYI, "Existing tcp session with server found\n");
2408
		return server;
L
Linus Torvalds 已提交
2409
	}
2410
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
2411 2412
	return NULL;
}
2413

2414 2415
void
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
L
Linus Torvalds 已提交
2416
{
2417 2418
	struct task_struct *task;

2419
	spin_lock(&cifs_tcp_ses_lock);
2420
	if (--server->srv_count > 0) {
2421
		spin_unlock(&cifs_tcp_ses_lock);
2422
		return;
L
Linus Torvalds 已提交
2423
	}
2424

2425 2426
	put_net(cifs_net_ns(server));

2427
	list_del_init(&server->tcp_ses_list);
2428
	spin_unlock(&cifs_tcp_ses_lock);
2429

2430 2431
	cancel_delayed_work_sync(&server->echo);

2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442
	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);

2443 2444 2445
	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
2446

2447
	cifs_crypto_secmech_release(server);
2448 2449
	cifs_fscache_release_client_cookie(server);

2450 2451 2452
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
2453 2454 2455

	task = xchg(&server->tsk, NULL);
	if (task)
2456
		send_sig(SIGKILL, task, 1);
L
Linus Torvalds 已提交
2457 2458
}

2459
struct TCP_Server_Info *
2460
cifs_get_tcp_session(struct smb3_fs_context *ctx)
2461 2462 2463 2464
{
	struct TCP_Server_Info *tcp_ses = NULL;
	int rc;

2465
	cifs_dbg(FYI, "UNC: %s\n", ctx->UNC);
2466 2467

	/* see if we already have a matching tcp_ses */
2468
	tcp_ses = cifs_find_tcp_session(ctx);
2469 2470 2471 2472 2473 2474 2475 2476 2477
	if (tcp_ses)
		return tcp_ses;

	tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
	if (!tcp_ses) {
		rc = -ENOMEM;
		goto out_err;
	}

2478 2479
	tcp_ses->ops = ctx->ops;
	tcp_ses->vals = ctx->vals;
2480
	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
2481
	tcp_ses->hostname = extract_hostname(ctx->UNC);
2482 2483
	if (IS_ERR(tcp_ses->hostname)) {
		rc = PTR_ERR(tcp_ses->hostname);
2484
		goto out_err_crypto_release;
2485 2486
	}

2487 2488 2489 2490 2491
	tcp_ses->noblockcnt = ctx->rootfs;
	tcp_ses->noblocksnd = ctx->noblocksnd || ctx->rootfs;
	tcp_ses->noautotune = ctx->noautotune;
	tcp_ses->tcp_nodelay = ctx->sockopt_tcp_nodelay;
	tcp_ses->rdma = ctx->rdma;
P
Pavel Shilovsky 已提交
2492
	tcp_ses->in_flight = 0;
2493
	tcp_ses->max_in_flight = 0;
2494
	tcp_ses->credits = 1;
2495 2496 2497 2498 2499
	init_waitqueue_head(&tcp_ses->response_q);
	init_waitqueue_head(&tcp_ses->request_q);
	INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
	mutex_init(&tcp_ses->srv_mutex);
	memcpy(tcp_ses->workstation_RFC1001_name,
2500
		ctx->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2501
	memcpy(tcp_ses->server_RFC1001_name,
2502
		ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2503
	tcp_ses->session_estab = false;
2504
	tcp_ses->sequence_number = 0;
2505
	tcp_ses->reconnect_instance = 1;
2506
	tcp_ses->lstrp = jiffies;
2507
	tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);
2508
	spin_lock_init(&tcp_ses->req_lock);
2509 2510
	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
2511
	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
2512 2513
	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
	mutex_init(&tcp_ses->reconnect_mutex);
2514
	memcpy(&tcp_ses->srcaddr, &ctx->srcaddr,
2515
	       sizeof(tcp_ses->srcaddr));
2516
	memcpy(&tcp_ses->dstaddr, &ctx->dstaddr,
2517
		sizeof(tcp_ses->dstaddr));
2518 2519
	if (ctx->use_client_guid)
		memcpy(tcp_ses->client_guid, ctx->client_guid,
2520 2521 2522
		       SMB2_CLIENT_GUID_SIZE);
	else
		generate_random_uuid(tcp_ses->client_guid);
2523 2524 2525 2526 2527 2528 2529 2530
	/*
	 * at this point we are the only ones with the pointer
	 * to the struct since the kernel thread not created yet
	 * no need to spinlock this init of tcpStatus or srv_count
	 */
	tcp_ses->tcpStatus = CifsNew;
	++tcp_ses->srv_count;

2531 2532 2533
	if (ctx->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
		ctx->echo_interval <= SMB_ECHO_INTERVAL_MAX)
		tcp_ses->echo_interval = ctx->echo_interval * HZ;
S
Steve French 已提交
2534 2535
	else
		tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
2536 2537 2538 2539 2540 2541 2542
	if (tcp_ses->rdma) {
#ifndef CONFIG_CIFS_SMB_DIRECT
		cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
		rc = -ENOENT;
		goto out_err_crypto_release;
#endif
		tcp_ses->smbd_conn = smbd_get_connection(
2543
			tcp_ses, (struct sockaddr *)&ctx->dstaddr);
2544 2545 2546 2547 2548 2549 2550 2551 2552
		if (tcp_ses->smbd_conn) {
			cifs_dbg(VFS, "RDMA transport established\n");
			rc = 0;
			goto smbd_connected;
		} else {
			rc = -ENOENT;
			goto out_err_crypto_release;
		}
	}
2553
	rc = ip_connect(tcp_ses);
2554
	if (rc < 0) {
2555
		cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
2556
		goto out_err_crypto_release;
2557
	}
2558
smbd_connected:
2559 2560 2561 2562 2563
	/*
	 * since we're in a cifs function already, we know that
	 * this will succeed. No need for try_module_get().
	 */
	__module_get(THIS_MODULE);
2564
	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
2565 2566 2567
				  tcp_ses, "cifsd");
	if (IS_ERR(tcp_ses->tsk)) {
		rc = PTR_ERR(tcp_ses->tsk);
2568
		cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
2569
		module_put(THIS_MODULE);
2570
		goto out_err_crypto_release;
2571
	}
2572
	tcp_ses->min_offload = ctx->min_offload;
2573
	tcp_ses->tcpStatus = CifsNeedNegotiate;
2574

2575
	tcp_ses->nr_targets = 1;
2576
	tcp_ses->ignore_signature = ctx->ignore_signature;
2577
	/* thread spawned, put it on the list */
2578
	spin_lock(&cifs_tcp_ses_lock);
2579
	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
2580
	spin_unlock(&cifs_tcp_ses_lock);
2581

2582 2583
	cifs_fscache_get_client_cookie(tcp_ses);

2584
	/* queue echo request delayed work */
S
Steve French 已提交
2585
	queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
2586

2587 2588
	return tcp_ses;

2589
out_err_crypto_release:
2590
	cifs_crypto_secmech_release(tcp_ses);
2591

2592 2593
	put_net(cifs_net_ns(tcp_ses));

2594 2595
out_err:
	if (tcp_ses) {
2596 2597
		if (!IS_ERR(tcp_ses->hostname))
			kfree(tcp_ses->hostname);
2598 2599 2600 2601 2602 2603 2604
		if (tcp_ses->ssocket)
			sock_release(tcp_ses->ssocket);
		kfree(tcp_ses);
	}
	return ERR_PTR(rc);
}

2605
static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
2606
{
2607 2608
	if (ctx->sectype != Unspecified &&
	    ctx->sectype != ses->sectype)
2609 2610
		return 0;

2611 2612 2613 2614
	/*
	 * If an existing session is limited to less channels than
	 * requested, it should not be reused
	 */
2615
	if (ses->chan_max < ctx->max_channels)
2616 2617
		return 0;

2618
	switch (ses->sectype) {
2619
	case Kerberos:
2620
		if (!uid_eq(ctx->cred_uid, ses->cred_uid))
2621 2622 2623
			return 0;
		break;
	default:
J
Jeff Layton 已提交
2624 2625
		/* NULL username means anonymous session */
		if (ses->user_name == NULL) {
2626
			if (!ctx->nullauth)
J
Jeff Layton 已提交
2627 2628 2629 2630
				return 0;
			break;
		}

2631
		/* anything else takes username/password */
J
Jeff Layton 已提交
2632
		if (strncmp(ses->user_name,
2633
			    ctx->username ? ctx->username : "",
2634
			    CIFS_MAX_USERNAME_LEN))
2635
			return 0;
2636
		if ((ctx->username && strlen(ctx->username) != 0) &&
2637 2638
		    ses->password != NULL &&
		    strncmp(ses->password,
2639
			    ctx->password ? ctx->password : "",
2640
			    CIFS_MAX_PASSWORD_LEN))
2641 2642 2643 2644 2645
			return 0;
	}
	return 1;
}

A
Aurelien Aptel 已提交
2646 2647 2648 2649 2650 2651 2652
/**
 * cifs_setup_ipc - helper to setup the IPC tcon for the session
 *
 * A new IPC connection is made and stored in the session
 * tcon_ipc. The IPC tcon has the same lifetime as the session.
 */
static int
2653
cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
A
Aurelien Aptel 已提交
2654 2655 2656 2657 2658 2659
{
	int rc = 0, xid;
	struct cifs_tcon *tcon;
	struct nls_table *nls_codepage;
	char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
	bool seal = false;
2660
	struct TCP_Server_Info *server = ses->server;
A
Aurelien Aptel 已提交
2661 2662 2663 2664 2665

	/*
	 * If the mount request that resulted in the creation of the
	 * session requires encryption, force IPC to be encrypted too.
	 */
2666
	if (ctx->seal) {
2667
		if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
A
Aurelien Aptel 已提交
2668 2669
			seal = true;
		else {
2670
			cifs_server_dbg(VFS,
A
Aurelien Aptel 已提交
2671 2672 2673 2674 2675 2676 2677 2678 2679
				 "IPC: server doesn't support encryption\n");
			return -EOPNOTSUPP;
		}
	}

	tcon = tconInfoAlloc();
	if (tcon == NULL)
		return -ENOMEM;

2680
	scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
A
Aurelien Aptel 已提交
2681 2682 2683 2684 2685 2686 2687 2688

	/* cannot fail */
	nls_codepage = load_nls_default();

	xid = get_xid();
	tcon->ses = ses;
	tcon->ipc = true;
	tcon->seal = seal;
2689
	rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
A
Aurelien Aptel 已提交
2690 2691 2692
	free_xid(xid);

	if (rc) {
2693
		cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
A
Aurelien Aptel 已提交
2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733
		tconInfoFree(tcon);
		goto out;
	}

	cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);

	ses->tcon_ipc = tcon;
out:
	unload_nls(nls_codepage);
	return rc;
}

/**
 * cifs_free_ipc - helper to release the session IPC tcon
 *
 * Needs to be called everytime a session is destroyed
 */
static int
cifs_free_ipc(struct cifs_ses *ses)
{
	int rc = 0, xid;
	struct cifs_tcon *tcon = ses->tcon_ipc;

	if (tcon == NULL)
		return 0;

	if (ses->server->ops->tree_disconnect) {
		xid = get_xid();
		rc = ses->server->ops->tree_disconnect(xid, tcon);
		free_xid(xid);
	}

	if (rc)
		cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);

	tconInfoFree(tcon);
	ses->tcon_ipc = NULL;
	return rc;
}

2734
static struct cifs_ses *
2735
cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
L
Linus Torvalds 已提交
2736
{
2737
	struct cifs_ses *ses;
2738

2739
	spin_lock(&cifs_tcp_ses_lock);
2740
	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
2741 2742
		if (ses->status == CifsExiting)
			continue;
2743
		if (!match_session(ses, ctx))
2744
			continue;
2745
		++ses->ses_count;
2746
		spin_unlock(&cifs_tcp_ses_lock);
2747 2748
		return ses;
	}
2749
	spin_unlock(&cifs_tcp_ses_lock);
2750 2751
	return NULL;
}
2752

2753
void cifs_put_smb_ses(struct cifs_ses *ses)
2754
{
2755
	unsigned int rc, xid;
2756
	struct TCP_Server_Info *server = ses->server;
2757

2758
	cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
2759

2760
	spin_lock(&cifs_tcp_ses_lock);
2761 2762 2763 2764
	if (ses->status == CifsExiting) {
		spin_unlock(&cifs_tcp_ses_lock);
		return;
	}
2765
	if (--ses->ses_count > 0) {
2766
		spin_unlock(&cifs_tcp_ses_lock);
2767 2768
		return;
	}
2769 2770
	if (ses->status == CifsGood)
		ses->status = CifsExiting;
2771
	spin_unlock(&cifs_tcp_ses_lock);
2772

A
Aurelien Aptel 已提交
2773 2774
	cifs_free_ipc(ses);

2775
	if (ses->status == CifsExiting && server->ops->logoff) {
2776
		xid = get_xid();
2777 2778
		rc = server->ops->logoff(xid, ses);
		if (rc)
2779
			cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2780
				__func__, rc);
2781
		_free_xid(xid);
2782
	}
2783 2784 2785 2786 2787

	spin_lock(&cifs_tcp_ses_lock);
	list_del_init(&ses->smb_ses_list);
	spin_unlock(&cifs_tcp_ses_lock);

2788 2789 2790 2791 2792 2793 2794 2795
	/* close any extra channels */
	if (ses->chan_count > 1) {
		int i;

		for (i = 1; i < ses->chan_count; i++)
			cifs_put_tcp_session(ses->chans[i].server, 0);
	}

2796
	sesInfoFree(ses);
2797
	cifs_put_tcp_session(server, 0);
2798
}
2799

2800 2801
#ifdef CONFIG_KEYS

2802 2803
/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
2804 2805 2806

/* Populate username and pw fields from keyring if possible */
static int
2807
cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
2808 2809
{
	int rc = 0;
2810
	int is_domain = 0;
2811 2812
	const char *delim, *payload;
	char *desc;
2813 2814 2815 2816 2817
	ssize_t len;
	struct key *key;
	struct TCP_Server_Info *server = ses->server;
	struct sockaddr_in *sa;
	struct sockaddr_in6 *sa6;
2818
	const struct user_key_payload *upayload;
2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834

	desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
	if (!desc)
		return -ENOMEM;

	/* try to find an address key first */
	switch (server->dstaddr.ss_family) {
	case AF_INET:
		sa = (struct sockaddr_in *)&server->dstaddr;
		sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
		break;
	case AF_INET6:
		sa6 = (struct sockaddr_in6 *)&server->dstaddr;
		sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
		break;
	default:
2835 2836
		cifs_dbg(FYI, "Bad ss_family (%hu)\n",
			 server->dstaddr.ss_family);
2837 2838 2839 2840
		rc = -EINVAL;
		goto out_err;
	}

2841
	cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
2842
	key = request_key(&key_type_logon, desc, "");
2843 2844
	if (IS_ERR(key)) {
		if (!ses->domainName) {
2845
			cifs_dbg(FYI, "domainName is NULL\n");
2846 2847 2848 2849 2850 2851
			rc = PTR_ERR(key);
			goto out_err;
		}

		/* didn't work, try to find a domain key */
		sprintf(desc, "cifs:d:%s", ses->domainName);
2852
		cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
2853
		key = request_key(&key_type_logon, desc, "");
2854 2855 2856 2857
		if (IS_ERR(key)) {
			rc = PTR_ERR(key);
			goto out_err;
		}
2858
		is_domain = 1;
2859 2860 2861
	}

	down_read(&key->sem);
2862
	upayload = user_key_payload_locked(key);
2863
	if (IS_ERR_OR_NULL(upayload)) {
2864
		rc = upayload ? PTR_ERR(upayload) : -EINVAL;
2865 2866 2867 2868
		goto out_key_put;
	}

	/* find first : in payload */
2869
	payload = upayload->data;
2870
	delim = strnchr(payload, upayload->datalen, ':');
2871
	cifs_dbg(FYI, "payload=%s\n", payload);
2872
	if (!delim) {
2873 2874
		cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
			 upayload->datalen);
2875 2876 2877 2878 2879
		rc = -EINVAL;
		goto out_key_put;
	}

	len = delim - payload;
2880
	if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
2881 2882
		cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
			 len);
2883 2884 2885 2886
		rc = -EINVAL;
		goto out_key_put;
	}

2887 2888
	ctx->username = kstrndup(payload, len, GFP_KERNEL);
	if (!ctx->username) {
2889 2890
		cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
			 len);
2891 2892 2893
		rc = -ENOMEM;
		goto out_key_put;
	}
2894
	cifs_dbg(FYI, "%s: username=%s\n", __func__, ctx->username);
2895 2896

	len = key->datalen - (len + 1);
2897
	if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
2898
		cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
2899
		rc = -EINVAL;
2900 2901
		kfree(ctx->username);
		ctx->username = NULL;
2902 2903 2904 2905
		goto out_key_put;
	}

	++delim;
2906 2907
	ctx->password = kstrndup(delim, len, GFP_KERNEL);
	if (!ctx->password) {
2908 2909
		cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
			 len);
2910
		rc = -ENOMEM;
2911 2912
		kfree(ctx->username);
		ctx->username = NULL;
2913 2914 2915
		goto out_key_put;
	}

2916 2917 2918 2919 2920
	/*
	 * If we have a domain key then we must set the domainName in the
	 * for the request.
	 */
	if (is_domain && ses->domainName) {
2921
		ctx->domainname = kstrndup(ses->domainName,
2922 2923
					   strlen(ses->domainName),
					   GFP_KERNEL);
2924
		if (!ctx->domainname) {
J
Joe Perches 已提交
2925 2926
			cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
				 len);
2927
			rc = -ENOMEM;
2928 2929 2930 2931
			kfree(ctx->username);
			ctx->username = NULL;
			kfree_sensitive(ctx->password);
			ctx->password = NULL;
2932 2933 2934 2935
			goto out_key_put;
		}
	}

2936 2937 2938 2939 2940
out_key_put:
	up_read(&key->sem);
	key_put(key);
out_err:
	kfree(desc);
2941
	cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
2942 2943 2944 2945
	return rc;
}
#else /* ! CONFIG_KEYS */
static inline int
2946
cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)),
2947 2948 2949 2950 2951 2952
		   struct cifs_ses *ses __attribute__((unused)))
{
	return -ENOSYS;
}
#endif /* CONFIG_KEYS */

2953
/**
2954
 * cifs_get_smb_ses - get a session matching @ctx data from @server
2955 2956 2957 2958 2959
 *
 * This function assumes it is being called from cifs_mount() where we
 * already got a server reference (server refcount +1). See
 * cifs_get_tcon() for refcount explanations.
 */
2960
struct cifs_ses *
2961
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
2962
{
2963 2964
	int rc = -ENOMEM;
	unsigned int xid;
2965
	struct cifs_ses *ses;
2966 2967
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
2968

2969
	xid = get_xid();
2970

2971
	ses = cifs_find_smb_ses(server, ctx);
2972
	if (ses) {
2973 2974
		cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
			 ses->status);
2975 2976

		mutex_lock(&ses->session_mutex);
2977 2978 2979 2980 2981
		rc = cifs_negotiate_protocol(xid, ses);
		if (rc) {
			mutex_unlock(&ses->session_mutex);
			/* problem -- put our ses reference */
			cifs_put_smb_ses(ses);
2982
			free_xid(xid);
2983 2984
			return ERR_PTR(rc);
		}
2985
		if (ses->need_reconnect) {
2986
			cifs_dbg(FYI, "Session needs reconnect\n");
2987
			rc = cifs_setup_session(xid, ses,
2988
						ctx->local_nls);
2989 2990 2991 2992
			if (rc) {
				mutex_unlock(&ses->session_mutex);
				/* problem -- put our reference */
				cifs_put_smb_ses(ses);
2993
				free_xid(xid);
2994 2995 2996 2997
				return ERR_PTR(rc);
			}
		}
		mutex_unlock(&ses->session_mutex);
2998 2999

		/* existing SMB ses has a server reference already */
3000
		cifs_put_tcp_session(server, 0);
3001
		free_xid(xid);
3002 3003 3004
		return ses;
	}

3005
	cifs_dbg(FYI, "Existing smb sess not found\n");
3006 3007 3008 3009 3010 3011
	ses = sesInfoAlloc();
	if (ses == NULL)
		goto get_ses_fail;

	/* new SMB session uses our server ref */
	ses->server = server;
3012 3013
	if (server->dstaddr.ss_family == AF_INET6)
		sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
3014
	else
3015
		sprintf(ses->serverName, "%pI4", &addr->sin_addr);
3016

3017 3018
	if (ctx->username) {
		ses->user_name = kstrdup(ctx->username, GFP_KERNEL);
3019 3020 3021
		if (!ses->user_name)
			goto get_ses_fail;
	}
3022

3023 3024 3025
	/* ctx->password freed at unmount */
	if (ctx->password) {
		ses->password = kstrdup(ctx->password, GFP_KERNEL);
3026 3027 3028
		if (!ses->password)
			goto get_ses_fail;
	}
3029 3030
	if (ctx->domainname) {
		ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL);
3031 3032
		if (!ses->domainName)
			goto get_ses_fail;
3033
	}
3034 3035 3036 3037
	if (ctx->domainauto)
		ses->domainAuto = ctx->domainauto;
	ses->cred_uid = ctx->cred_uid;
	ses->linux_uid = ctx->linux_uid;
3038

3039 3040
	ses->sectype = ctx->sectype;
	ses->sign = ctx->sign;
3041
	mutex_lock(&ses->session_mutex);
3042 3043 3044 3045

	/* add server as first channel */
	ses->chans[0].server = server;
	ses->chan_count = 1;
3046
	ses->chan_max = ctx->multichannel ? ctx->max_channels:1;
3047

3048 3049
	rc = cifs_negotiate_protocol(xid, ses);
	if (!rc)
3050
		rc = cifs_setup_session(xid, ses, ctx->local_nls);
3051 3052 3053 3054 3055

	/* each channel uses a different signing key */
	memcpy(ses->chans[0].signkey, ses->smb3signingkey,
	       sizeof(ses->smb3signingkey));

3056
	mutex_unlock(&ses->session_mutex);
3057
	if (rc)
3058 3059
		goto get_ses_fail;

3060
	/* success, put it on the list and add it as first channel */
3061
	spin_lock(&cifs_tcp_ses_lock);
3062
	list_add(&ses->smb_ses_list, &server->smb_ses_list);
3063
	spin_unlock(&cifs_tcp_ses_lock);
3064

3065
	free_xid(xid);
A
Aurelien Aptel 已提交
3066

3067
	cifs_setup_ipc(ses, ctx);
A
Aurelien Aptel 已提交
3068

3069 3070 3071 3072
	return ses;

get_ses_fail:
	sesInfoFree(ses);
3073
	free_xid(xid);
3074 3075 3076
	return ERR_PTR(rc);
}

3077
static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
3078 3079 3080
{
	if (tcon->tidStatus == CifsExiting)
		return 0;
3081
	if (strncmp(tcon->treeName, ctx->UNC, MAX_TREE_SIZE))
3082
		return 0;
3083
	if (tcon->seal != ctx->seal)
3084
		return 0;
3085
	if (tcon->snapshot_time != ctx->snapshot_time)
3086
		return 0;
3087
	if (tcon->handle_timeout != ctx->handle_timeout)
3088
		return 0;
3089
	if (tcon->no_lease != ctx->no_lease)
3090
		return 0;
3091
	if (tcon->nodelete != ctx->nodelete)
S
Steve French 已提交
3092
		return 0;
3093 3094 3095
	return 1;
}

3096
static struct cifs_tcon *
3097
cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
3098 3099
{
	struct list_head *tmp;
3100
	struct cifs_tcon *tcon;
3101

3102
	spin_lock(&cifs_tcp_ses_lock);
3103
	list_for_each(tmp, &ses->tcon_list) {
3104
		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
3105 3106 3107 3108
#ifdef CONFIG_CIFS_DFS_UPCALL
		if (tcon->dfs_path)
			continue;
#endif
3109
		if (!match_tcon(tcon, ctx))
3110 3111
			continue;
		++tcon->tc_count;
3112
		spin_unlock(&cifs_tcp_ses_lock);
3113
		return tcon;
L
Linus Torvalds 已提交
3114
	}
3115
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
3116 3117 3118
	return NULL;
}

3119
void
3120
cifs_put_tcon(struct cifs_tcon *tcon)
3121
{
3122
	unsigned int xid;
A
Aurelien Aptel 已提交
3123
	struct cifs_ses *ses;
3124

A
Aurelien Aptel 已提交
3125 3126 3127 3128 3129 3130 3131 3132
	/*
	 * IPC tcon share the lifetime of their session and are
	 * destroyed in the session put function
	 */
	if (tcon == NULL || tcon->ipc)
		return;

	ses = tcon->ses;
3133
	cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
3134
	spin_lock(&cifs_tcp_ses_lock);
3135
	if (--tcon->tc_count > 0) {
3136
		spin_unlock(&cifs_tcp_ses_lock);
3137 3138 3139 3140
		return;
	}

	list_del_init(&tcon->tcon_list);
3141
	spin_unlock(&cifs_tcp_ses_lock);
3142

3143
	xid = get_xid();
3144 3145
	if (ses->server->ops->tree_disconnect)
		ses->server->ops->tree_disconnect(xid, tcon);
3146
	_free_xid(xid);
3147

3148
	cifs_fscache_release_super_cookie(tcon);
3149
	tconInfoFree(tcon);
3150 3151 3152
	cifs_put_smb_ses(ses);
}

3153
/**
3154
 * cifs_get_tcon - get a tcon matching @ctx data from @ses
3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172
 *
 * - tcon refcount is the number of mount points using the tcon.
 * - ses refcount is the number of tcon using the session.
 *
 * 1. This function assumes it is being called from cifs_mount() where
 *    we already got a session reference (ses refcount +1).
 *
 * 2. Since we're in the context of adding a mount point, the end
 *    result should be either:
 *
 * a) a new tcon already allocated with refcount=1 (1 mount point) and
 *    its session refcount incremented (1 new tcon). This +1 was
 *    already done in (1).
 *
 * b) an existing tcon with refcount+1 (add a mount point to it) and
 *    identical ses refcount (no new tcon). Because of (1) we need to
 *    decrement the ses refcount.
 */
3173
static struct cifs_tcon *
3174
cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
3175 3176
{
	int rc, xid;
3177
	struct cifs_tcon *tcon;
3178

3179
	tcon = cifs_find_tcon(ses, ctx);
3180
	if (tcon) {
3181 3182 3183 3184
		/*
		 * tcon has refcount already incremented but we need to
		 * decrement extra ses reference gotten by caller (case b)
		 */
3185
		cifs_dbg(FYI, "Found match on UNC path\n");
3186 3187 3188 3189
		cifs_put_smb_ses(ses);
		return tcon;
	}

3190 3191 3192 3193 3194
	if (!ses->server->ops->tree_connect) {
		rc = -ENOSYS;
		goto out_fail;
	}

3195 3196 3197 3198 3199 3200
	tcon = tconInfoAlloc();
	if (tcon == NULL) {
		rc = -ENOMEM;
		goto out_fail;
	}

3201
	if (ctx->snapshot_time) {
3202 3203 3204 3205 3206 3207
		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
3208
			tcon->snapshot_time = ctx->snapshot_time;
3209 3210
	}

3211
	if (ctx->handle_timeout) {
3212 3213 3214 3215 3216 3217
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "Use SMB2.1 or later for handle timeout option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
3218
			tcon->handle_timeout = ctx->handle_timeout;
3219 3220
	}

3221
	tcon->ses = ses;
3222 3223
	if (ctx->password) {
		tcon->password = kstrdup(ctx->password, GFP_KERNEL);
3224 3225 3226 3227 3228 3229
		if (!tcon->password) {
			rc = -ENOMEM;
			goto out_fail;
		}
	}

3230
	if (ctx->seal) {
3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
				 "SMB3 or later required for encryption\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else if (tcon->ses->server->capabilities &
					SMB2_GLOBAL_CAP_ENCRYPTION)
			tcon->seal = true;
		else {
			cifs_dbg(VFS, "Encryption is not supported on share\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		}
	}

3246
	if (ctx->linux_ext) {
3247
		if (ses->server->posix_ext_supported) {
3248
			tcon->posix_extensions = true;
J
Joe Perches 已提交
3249
			pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
3250
		} else {
J
Joe Perches 已提交
3251
			cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
3252 3253
			rc = -EOPNOTSUPP;
			goto out_fail;
3254
		}
3255 3256
	}

3257 3258 3259 3260
	/*
	 * BB Do we need to wrap session_mutex around this TCon call and Unix
	 * SetFS as we do on SessSetup and reconnect?
	 */
3261
	xid = get_xid();
3262 3263
	rc = ses->server->ops->tree_connect(xid, ses, ctx->UNC, tcon,
					    ctx->local_nls);
3264
	free_xid(xid);
3265
	cifs_dbg(FYI, "Tcon rc = %d\n", rc);
3266 3267 3268
	if (rc)
		goto out_fail;

3269 3270
	tcon->use_persistent = false;
	/* check if SMB2 or later, CIFS does not support persistent handles */
3271
	if (ctx->persistent) {
3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "SMB3 or later required for persistent handles\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else if (ses->server->capabilities &
			   SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
			tcon->use_persistent = true;
		else /* persistent handles requested but not supported */ {
			cifs_dbg(VFS,
				"Persistent handles not supported on share\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		}
	} else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
	     && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3288
	     && (ctx->nopersistent == false)) {
3289 3290
		cifs_dbg(FYI, "enabling persistent handles\n");
		tcon->use_persistent = true;
3291
	} else if (ctx->resilient) {
S
Steve French 已提交
3292 3293 3294 3295 3296 3297 3298
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "SMB2.1 or later required for resilient handles\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		}
		tcon->use_resilient = true;
3299 3300
	}

3301 3302
	/* If the user really knows what they are doing they can override */
	if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3303
		if (ctx->cache_ro)
3304
			cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3305
		else if (ctx->cache_rw)
3306 3307 3308
			cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
	}

3309
	if (ctx->no_lease) {
3310 3311 3312 3313 3314 3315
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
				"SMB2 or later required for nolease option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
3316
			tcon->no_lease = ctx->no_lease;
3317 3318
	}

3319 3320 3321 3322 3323
	/*
	 * We can have only one retry value for a connection to a share so for
	 * resources mounted more than once to the same server share the last
	 * value passed in for the retry flag is used.
	 */
3324 3325
	tcon->retry = ctx->retry;
	tcon->nocase = ctx->nocase;
3326
	if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
3327
		tcon->nohandlecache = ctx->nohandlecache;
3328 3329
	else
		tcon->nohandlecache = 1;
3330 3331
	tcon->nodelete = ctx->nodelete;
	tcon->local_lease = ctx->local_lease;
3332
	INIT_LIST_HEAD(&tcon->pending_opens);
3333

3334
	spin_lock(&cifs_tcp_ses_lock);
3335
	list_add(&tcon->tcon_list, &ses->tcon_list);
3336
	spin_unlock(&cifs_tcp_ses_lock);
3337

3338 3339
	cifs_fscache_get_super_cookie(tcon);

3340 3341 3342 3343 3344 3345 3346
	return tcon;

out_fail:
	tconInfoFree(tcon);
	return ERR_PTR(rc);
}

3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363
void
cifs_put_tlink(struct tcon_link *tlink)
{
	if (!tlink || IS_ERR(tlink))
		return;

	if (!atomic_dec_and_test(&tlink->tl_count) ||
	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
		tlink->tl_time = jiffies;
		return;
	}

	if (!IS_ERR(tlink_tcon(tlink)))
		cifs_put_tcon(tlink_tcon(tlink));
	kfree(tlink);
	return;
}
3364

3365 3366 3367 3368 3369
static int
compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
{
	struct cifs_sb_info *old = CIFS_SB(sb);
	struct cifs_sb_info *new = mnt_data->cifs_sb;
3370 3371
	unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
	unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
3372 3373 3374 3375

	if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
		return 0;

3376 3377 3378 3379
	if (old->mnt_cifs_serverino_autodisabled)
		newflags &= ~CIFS_MOUNT_SERVER_INUM;

	if (oldflags != newflags)
3380 3381 3382
		return 0;

	/*
3383 3384
	 * We want to share sb only if we don't specify an r/wsize or
	 * specified r/wsize is greater than or equal to existing one.
3385 3386 3387 3388
	 */
	if (new->wsize && new->wsize < old->wsize)
		return 0;

3389 3390 3391
	if (new->rsize && new->rsize < old->rsize)
		return 0;

3392
	if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407
		return 0;

	if (old->mnt_file_mode != new->mnt_file_mode ||
	    old->mnt_dir_mode != new->mnt_dir_mode)
		return 0;

	if (strcmp(old->local_nls->charset, new->local_nls->charset))
		return 0;

	if (old->actimeo != new->actimeo)
		return 0;

	return 1;
}

3408 3409 3410 3411 3412
static int
match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
{
	struct cifs_sb_info *old = CIFS_SB(sb);
	struct cifs_sb_info *new = mnt_data->cifs_sb;
3413 3414 3415 3416
	bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
		old->prepath;
	bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
		new->prepath;
3417

S
Sachin Prabhu 已提交
3418
	if (old_set && new_set && !strcmp(new->prepath, old->prepath))
3419
		return 1;
S
Sachin Prabhu 已提交
3420 3421 3422
	else if (!old_set && !new_set)
		return 1;

3423 3424 3425
	return 0;
}

3426 3427 3428 3429
int
cifs_match_super(struct super_block *sb, void *data)
{
	struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3430
	struct smb3_fs_context *ctx;
3431 3432
	struct cifs_sb_info *cifs_sb;
	struct TCP_Server_Info *tcp_srv;
3433 3434
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448
	struct tcon_link *tlink;
	int rc = 0;

	spin_lock(&cifs_tcp_ses_lock);
	cifs_sb = CIFS_SB(sb);
	tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
	if (IS_ERR(tlink)) {
		spin_unlock(&cifs_tcp_ses_lock);
		return rc;
	}
	tcon = tlink_tcon(tlink);
	ses = tcon->ses;
	tcp_srv = ses->server;

3449
	ctx = mnt_data->ctx;
3450

3451 3452 3453
	if (!match_server(tcp_srv, ctx) ||
	    !match_session(ses, ctx) ||
	    !match_tcon(tcon, ctx) ||
3454
	    !match_prepath(sb, mnt_data)) {
3455 3456 3457 3458 3459 3460 3461
		rc = 0;
		goto out;
	}

	rc = compare_mount_options(sb, mnt_data);
out:
	spin_unlock(&cifs_tcp_ses_lock);
3462
	cifs_put_tlink(tlink);
3463 3464 3465
	return rc;
}

3466 3467 3468 3469 3470 3471 3472 3473
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key cifs_key[2];
static struct lock_class_key cifs_slock_key[2];

static inline void
cifs_reclassify_socket4(struct socket *sock)
{
	struct sock *sk = sock->sk;
3474
	BUG_ON(!sock_allow_reclassification(sk));
3475 3476 3477 3478 3479 3480 3481 3482
	sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
		&cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
}

static inline void
cifs_reclassify_socket6(struct socket *sock)
{
	struct sock *sk = sock->sk;
3483
	BUG_ON(!sock_allow_reclassification(sk));
3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498
	sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
		&cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
}
#else
static inline void
cifs_reclassify_socket4(struct socket *sock)
{
}

static inline void
cifs_reclassify_socket6(struct socket *sock)
{
}
#endif

L
Linus Torvalds 已提交
3499
/* See RFC1001 section 14 on representation of Netbios names */
3500
static void rfc1002mangle(char *target, char *source, unsigned int length)
L
Linus Torvalds 已提交
3501
{
3502
	unsigned int i, j;
L
Linus Torvalds 已提交
3503

3504
	for (i = 0, j = 0; i < (length); i++) {
L
Linus Torvalds 已提交
3505 3506 3507
		/* mask a nibble at a time and encode */
		target[j] = 'A' + (0x0F & (source[i] >> 4));
		target[j+1] = 'A' + (0x0F & source[i]);
3508
		j += 2;
L
Linus Torvalds 已提交
3509 3510 3511 3512
	}

}

3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528
static int
bind_socket(struct TCP_Server_Info *server)
{
	int rc = 0;
	if (server->srcaddr.ss_family != AF_UNSPEC) {
		/* Bind to the specified local IP address */
		struct socket *socket = server->ssocket;
		rc = socket->ops->bind(socket,
				       (struct sockaddr *) &server->srcaddr,
				       sizeof(server->srcaddr));
		if (rc < 0) {
			struct sockaddr_in *saddr4;
			struct sockaddr_in6 *saddr6;
			saddr4 = (struct sockaddr_in *)&server->srcaddr;
			saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
			if (saddr6->sin6_family == AF_INET6)
3529
				cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3530
					 &saddr6->sin6_addr, rc);
3531
			else
3532
				cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3533
					 &saddr4->sin_addr.s_addr, rc);
3534 3535 3536 3537
		}
	}
	return rc;
}
L
Linus Torvalds 已提交
3538 3539

static int
3540
ip_rfc1001_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
3541 3542
{
	int rc = 0;
3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554
	/*
	 * some servers require RFC1001 sessinit before sending
	 * negprot - BB check reconnection in case where second
	 * sessinit is sent but no second negprot
	 */
	struct rfc1002_session_packet *ses_init_buf;
	struct smb_hdr *smb_buf;
	ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
			       GFP_KERNEL);
	if (ses_init_buf) {
		ses_init_buf->trailer.session_req.called_len = 32;

3555
		if (server->server_RFC1001_name[0] != 0)
3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571
			rfc1002mangle(ses_init_buf->trailer.
				      session_req.called_name,
				      server->server_RFC1001_name,
				      RFC1001_NAME_LEN_WITH_NULL);
		else
			rfc1002mangle(ses_init_buf->trailer.
				      session_req.called_name,
				      DEFAULT_CIFS_CALLED_NAME,
				      RFC1001_NAME_LEN_WITH_NULL);

		ses_init_buf->trailer.session_req.calling_len = 32;

		/*
		 * calling name ends in null (byte 16) from old smb
		 * convention.
		 */
3572
		if (server->workstation_RFC1001_name[0] != 0)
3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587
			rfc1002mangle(ses_init_buf->trailer.
				      session_req.calling_name,
				      server->workstation_RFC1001_name,
				      RFC1001_NAME_LEN_WITH_NULL);
		else
			rfc1002mangle(ses_init_buf->trailer.
				      session_req.calling_name,
				      "LINUX_CIFS_CLNT",
				      RFC1001_NAME_LEN_WITH_NULL);

		ses_init_buf->trailer.session_req.scope1 = 0;
		ses_init_buf->trailer.session_req.scope2 = 0;
		smb_buf = (struct smb_hdr *)ses_init_buf;

		/* sizeof RFC1002_SESSION_REQUEST with no scope */
3588
		smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614
		rc = smb_send(server, smb_buf, 0x44);
		kfree(ses_init_buf);
		/*
		 * RFC1001 layer in at least one server
		 * requires very short break before negprot
		 * presumably because not expecting negprot
		 * to follow so fast.  This is a simple
		 * solution that works without
		 * complicating the code and causes no
		 * significant slowing down on mount
		 * for everyone else
		 */
		usleep_range(1000, 2000);
	}
	/*
	 * else the negprot may still work without this
	 * even though malloc failed
	 */

	return rc;
}

static int
generic_ip_connect(struct TCP_Server_Info *server)
{
	int rc = 0;
3615
	__be16 sport;
3616
	int slen, sfamily;
3617
	struct socket *socket = server->ssocket;
3618 3619 3620 3621 3622
	struct sockaddr *saddr;

	saddr = (struct sockaddr *) &server->dstaddr;

	if (server->dstaddr.ss_family == AF_INET6) {
3623 3624 3625
		struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr;

		sport = ipv6->sin6_port;
3626 3627
		slen = sizeof(struct sockaddr_in6);
		sfamily = AF_INET6;
3628 3629
		cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr,
				ntohs(sport));
3630
	} else {
3631 3632 3633
		struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr;

		sport = ipv4->sin_port;
3634 3635
		slen = sizeof(struct sockaddr_in);
		sfamily = AF_INET;
3636 3637
		cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr,
				ntohs(sport));
3638
	}
L
Linus Torvalds 已提交
3639

3640
	if (socket == NULL) {
3641 3642
		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
				   IPPROTO_TCP, &socket, 1);
L
Linus Torvalds 已提交
3643
		if (rc < 0) {
3644
			cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
3645
			server->ssocket = NULL;
L
Linus Torvalds 已提交
3646 3647
			return rc;
		}
3648 3649

		/* BB other socket options to set KEEPALIVE, NODELAY? */
3650
		cifs_dbg(FYI, "Socket created\n");
3651 3652
		server->ssocket = socket;
		socket->sk->sk_allocation = GFP_NOFS;
3653 3654 3655 3656
		if (sfamily == AF_INET6)
			cifs_reclassify_socket6(socket);
		else
			cifs_reclassify_socket4(socket);
L
Linus Torvalds 已提交
3657 3658
	}

3659 3660 3661 3662
	rc = bind_socket(server);
	if (rc < 0)
		return rc;

3663 3664
	/*
	 * Eventually check for other socket options to change from
3665 3666
	 * the default. sock_setsockopt not used because it expects
	 * user space buffer
3667 3668
	 */
	socket->sk->sk_rcvtimeo = 7 * HZ;
3669
	socket->sk->sk_sndtimeo = 5 * HZ;
3670

3671
	/* make the bufsizes depend on wsize/rsize and max requests */
3672 3673 3674 3675 3676
	if (server->noautotune) {
		if (socket->sk->sk_sndbuf < (200 * 1024))
			socket->sk->sk_sndbuf = 200 * 1024;
		if (socket->sk->sk_rcvbuf < (140 * 1024))
			socket->sk->sk_rcvbuf = 140 * 1024;
3677
	}
L
Linus Torvalds 已提交
3678

3679 3680
	if (server->tcp_nodelay)
		tcp_sock_set_nodelay(socket->sk);
3681

3682
	cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
3683
		 socket->sk->sk_sndbuf,
3684
		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3685

3686 3687
	rc = socket->ops->connect(socket, saddr, slen,
				  server->noblockcnt ? O_NONBLOCK : 0);
3688 3689 3690 3691 3692 3693
	/*
	 * When mounting SMB root file systems, we do not want to block in
	 * connect. Otherwise bail out and then let cifs_reconnect() perform
	 * reconnect failover - if possible.
	 */
	if (server->noblockcnt && rc == -EINPROGRESS)
3694
		rc = 0;
3695
	if (rc < 0) {
3696
		cifs_dbg(FYI, "Error %d connecting to server\n", rc);
3697 3698 3699 3700 3701
		sock_release(socket);
		server->ssocket = NULL;
		return rc;
	}

3702 3703
	if (sport == htons(RFC1001_PORT))
		rc = ip_rfc1001_connect(server);
3704

L
Linus Torvalds 已提交
3705 3706 3707 3708
	return rc;
}

static int
3709
ip_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
3710
{
3711
	__be16 *sport;
3712 3713
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
L
Linus Torvalds 已提交
3714

3715 3716 3717 3718
	if (server->dstaddr.ss_family == AF_INET6)
		sport = &addr6->sin6_port;
	else
		sport = &addr->sin_port;
L
Linus Torvalds 已提交
3719

3720 3721
	if (*sport == 0) {
		int rc;
L
Linus Torvalds 已提交
3722

3723 3724
		/* try with 445 port at first */
		*sport = htons(CIFS_PORT);
3725

3726
		rc = generic_ip_connect(server);
L
Linus Torvalds 已提交
3727
		if (rc >= 0)
3728
			return rc;
3729

3730 3731
		/* if it failed, try with 139 port */
		*sport = htons(RFC1001_PORT);
3732 3733
	}

3734
	return generic_ip_connect(server);
L
Linus Torvalds 已提交
3735 3736
}

3737
void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
3738
			  struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749
{
	/* if we are reconnecting then should we check to see if
	 * any requested capabilities changed locally e.g. via
	 * remount but we can not do much about it here
	 * if they have (even if we could detect it by the following)
	 * Perhaps we could add a backpointer to array of sb from tcon
	 * or if we change to make all sb to same share the same
	 * sb as NFS - then we only have one backpointer to sb.
	 * What if we wanted to mount the server share twice once with
	 * and once without posixacls or posix paths? */
	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3750

3751
	if (ctx && ctx->no_linux_ext) {
3752 3753
		tcon->fsUnixInfo.Capability = 0;
		tcon->unix_ext = 0; /* Unix Extensions disabled */
3754
		cifs_dbg(FYI, "Linux protocol extensions disabled\n");
3755
		return;
3756
	} else if (ctx)
3757 3758 3759
		tcon->unix_ext = 1; /* Unix Extensions supported */

	if (tcon->unix_ext == 0) {
3760
		cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
3761 3762
		return;
	}
3763

S
Steve French 已提交
3764
	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
3765
		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3766
		cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
3767 3768
		/* check for reconnect case in which we do not
		   want to change the mount behavior if we can avoid it */
3769
		if (ctx == NULL) {
3770
			/* turn off POSIX ACL and PATHNAMES if not set
3771 3772 3773
			   originally at mount time */
			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
3774 3775
			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
3776
					cifs_dbg(VFS, "POSIXPATH support change\n");
3777
				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
3778
			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3779 3780
				cifs_dbg(VFS, "possible reconnect error\n");
				cifs_dbg(VFS, "server disabled POSIX path support\n");
3781
			}
3782
		}
3783

3784
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3785
			cifs_dbg(VFS, "per-share encryption not supported yet\n");
3786

3787
		cap &= CIFS_UNIX_CAP_MASK;
3788
		if (ctx && ctx->no_psx_acl)
3789
			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
3790
		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
3791
			cifs_dbg(FYI, "negotiated posix acl support\n");
3792 3793 3794
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
					CIFS_MOUNT_POSIXACL;
3795 3796
		}

3797
		if (ctx && ctx->posix_paths == 0)
3798
			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
3799
		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3800
			cifs_dbg(FYI, "negotiate posix pathnames\n");
3801 3802
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
3803 3804
					CIFS_MOUNT_POSIX_PATHS;
		}
3805

3806
		cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
3807
#ifdef CONFIG_CIFS_DEBUG2
3808
		if (cap & CIFS_UNIX_FCNTL_CAP)
3809
			cifs_dbg(FYI, "FCNTL cap\n");
3810
		if (cap & CIFS_UNIX_EXTATTR_CAP)
3811
			cifs_dbg(FYI, "EXTATTR cap\n");
3812
		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
3813
			cifs_dbg(FYI, "POSIX path cap\n");
3814
		if (cap & CIFS_UNIX_XATTR_CAP)
3815
			cifs_dbg(FYI, "XATTR cap\n");
3816
		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
3817
			cifs_dbg(FYI, "POSIX ACL cap\n");
3818
		if (cap & CIFS_UNIX_LARGE_READ_CAP)
3819
			cifs_dbg(FYI, "very large read cap\n");
3820
		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
3821
			cifs_dbg(FYI, "very large write cap\n");
3822
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3823
			cifs_dbg(FYI, "transport encryption cap\n");
3824
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3825
			cifs_dbg(FYI, "mandatory transport encryption cap\n");
3826 3827
#endif /* CIFS_DEBUG2 */
		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
3828
			if (ctx == NULL)
3829
				cifs_dbg(FYI, "resetting capabilities failed\n");
3830
			else
3831
				cifs_dbg(VFS, "Negotiating Unix capabilities with the server failed. Consider mounting with the Unix Extensions disabled if problems are found by specifying the nounix mount option.\n");
3832

3833 3834 3835 3836
		}
	}
}

3837
int cifs_setup_cifs_sb(struct smb3_fs_context *ctx,
3838
			struct cifs_sb_info *cifs_sb)
3839
{
3840 3841
	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);

3842 3843 3844
	spin_lock_init(&cifs_sb->tlink_tree_lock);
	cifs_sb->tlink_tree = RB_ROOT;

3845
	cifs_sb->bsize = ctx->bsize;
3846
	/*
3847 3848
	 * Temporarily set r/wsize for matching superblock. If we end up using
	 * new sb then client will later negotiate it downward if needed.
3849
	 */
3850 3851
	cifs_sb->rsize = ctx->rsize;
	cifs_sb->wsize = ctx->wsize;
3852

3853 3854 3855 3856
	cifs_sb->mnt_uid = ctx->linux_uid;
	cifs_sb->mnt_gid = ctx->linux_gid;
	cifs_sb->mnt_file_mode = ctx->file_mode;
	cifs_sb->mnt_dir_mode = ctx->dir_mode;
3857
	cifs_dbg(FYI, "file mode: %04ho  dir mode: %04ho\n",
3858
		 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
S
Steve French 已提交
3859

3860 3861
	cifs_sb->actimeo = ctx->actimeo;
	cifs_sb->local_nls = ctx->local_nls;
3862

3863
	if (ctx->nodfs)
3864
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
3865
	if (ctx->noperm)
S
Steve French 已提交
3866
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
3867
	if (ctx->setuids)
S
Steve French 已提交
3868
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3869
	if (ctx->setuidfromacl)
3870
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
3871
	if (ctx->server_ino)
S
Steve French 已提交
3872
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
3873
	if (ctx->remap)
3874
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
3875
	if (ctx->sfu_remap)
S
Steve French 已提交
3876
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
3877
	if (ctx->no_xattr)
S
Steve French 已提交
3878
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
3879
	if (ctx->sfu_emul)
S
Steve French 已提交
3880
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
3881
	if (ctx->nobrl)
S
Steve French 已提交
3882
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
3883
	if (ctx->nohandlecache)
S
Steve French 已提交
3884
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
3885
	if (ctx->nostrictsync)
S
Steve French 已提交
3886
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
3887
	if (ctx->mand_lock)
3888
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
3889
	if (ctx->rwpidforward)
3890
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
3891
	if (ctx->mode_ace)
3892
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
3893
	if (ctx->cifs_acl)
S
Steve French 已提交
3894
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
3895
	if (ctx->backupuid_specified) {
3896
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
3897
		cifs_sb->mnt_backupuid = ctx->backupuid;
3898
	}
3899
	if (ctx->backupgid_specified) {
3900
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
3901
		cifs_sb->mnt_backupgid = ctx->backupgid;
3902
	}
3903
	if (ctx->override_uid)
S
Steve French 已提交
3904
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
3905
	if (ctx->override_gid)
S
Steve French 已提交
3906
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
3907
	if (ctx->dynperm)
S
Steve French 已提交
3908
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
3909
	if (ctx->fsc)
3910
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
3911
	if (ctx->multiuser)
J
Jeff Layton 已提交
3912 3913
		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
					    CIFS_MOUNT_NO_PERM);
3914
	if (ctx->strict_io)
3915
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
3916
	if (ctx->direct_io) {
3917
		cifs_dbg(FYI, "mounting share using direct i/o\n");
S
Steve French 已提交
3918 3919
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
	}
3920
	if (ctx->cache_ro) {
3921 3922
		cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
3923
	} else if (ctx->cache_rw) {
3924 3925 3926
		cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
					    CIFS_MOUNT_RW_CACHE);
3927
	}
3928 3929
	if (ctx->mfsymlinks) {
		if (ctx->sfu_emul) {
3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941
			/*
			 * Our SFU ("Services for Unix" emulation does not allow
			 * creating symlinks but does allow reading existing SFU
			 * symlinks (it does allow both creating and reading SFU
			 * style mknod and FIFOs though). When "mfsymlinks" and
			 * "sfu" are both enabled at the same time, it allows
			 * reading both types of symlinks, but will only create
			 * them with mfsymlinks format. This allows better
			 * Apple compatibility (probably better for Samba too)
			 * while still recognizing old Windows style symlinks.
			 */
			cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
3942
		}
3943
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3944
	}
S
Steve French 已提交
3945

3946
	if ((ctx->cifs_acl) && (ctx->dynperm))
3947
		cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
3948

3949 3950
	if (ctx->prepath) {
		cifs_sb->prepath = kstrdup(ctx->prepath, GFP_KERNEL);
3951 3952 3953 3954 3955
		if (cifs_sb->prepath == NULL)
			return -ENOMEM;
	}

	return 0;
3956 3957
}

P
Paulo Alcantara 已提交
3958
void
3959
cifs_cleanup_volume_info_contents(struct smb3_fs_context *ctx)
I
Igor Mammedov 已提交
3960
{
3961 3962 3963 3964 3965 3966
	kfree(ctx->username);
	kfree_sensitive(ctx->password);
	kfree(ctx->UNC);
	kfree(ctx->domainname);
	kfree(ctx->iocharset);
	kfree(ctx->prepath);
J
Jeff Layton 已提交
3967 3968 3969
}

void
3970
cifs_cleanup_volume_info(struct smb3_fs_context *ctx)
J
Jeff Layton 已提交
3971
{
3972
	if (!ctx)
J
Jeff Layton 已提交
3973
		return;
3974 3975
	cifs_cleanup_volume_info_contents(ctx);
	kfree(ctx);
I
Igor Mammedov 已提交
3976 3977
}

P
Paulo Alcantara 已提交
3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996
/* Release all succeed connections */
static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
				   unsigned int xid,
				   struct TCP_Server_Info *server,
				   struct cifs_ses *ses, struct cifs_tcon *tcon)
{
	int rc = 0;

	if (tcon)
		cifs_put_tcon(tcon);
	else if (ses)
		cifs_put_smb_ses(ses);
	else if (server)
		cifs_put_tcp_session(server, 0);
	cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
	free_xid(xid);
}

/* Get connections for tcp, ses and tcon */
3997
static int mount_get_conns(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb,
P
Paulo Alcantara 已提交
3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013
			   unsigned int *xid,
			   struct TCP_Server_Info **nserver,
			   struct cifs_ses **nses, struct cifs_tcon **ntcon)
{
	int rc = 0;
	struct TCP_Server_Info *server;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;

	*nserver = NULL;
	*nses = NULL;
	*ntcon = NULL;

	*xid = get_xid();

	/* get a reference to a tcp session */
4014
	server = cifs_get_tcp_session(ctx);
P
Paulo Alcantara 已提交
4015 4016 4017 4018 4019 4020 4021
	if (IS_ERR(server)) {
		rc = PTR_ERR(server);
		return rc;
	}

	*nserver = server;

4022
	if ((ctx->max_credits < 20) || (ctx->max_credits > 60000))
P
Paulo Alcantara 已提交
4023 4024
		server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
	else
4025
		server->max_credits = ctx->max_credits;
P
Paulo Alcantara 已提交
4026 4027

	/* get a reference to a SMB session */
4028
	ses = cifs_get_smb_ses(server, ctx);
P
Paulo Alcantara 已提交
4029 4030 4031 4032 4033 4034 4035
	if (IS_ERR(ses)) {
		rc = PTR_ERR(ses);
		return rc;
	}

	*nses = ses;

4036
	if ((ctx->persistent == true) && (!(ses->server->capabilities &
P
Paulo Alcantara 已提交
4037
					    SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
4038
		cifs_server_dbg(VFS, "persistent handles not supported by server\n");
P
Paulo Alcantara 已提交
4039 4040 4041 4042
		return -EOPNOTSUPP;
	}

	/* search for existing tcon to this server share */
4043
	tcon = cifs_get_tcon(ses, ctx);
P
Paulo Alcantara 已提交
4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060
	if (IS_ERR(tcon)) {
		rc = PTR_ERR(tcon);
		return rc;
	}

	*ntcon = tcon;

	/* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
	if (tcon->posix_extensions)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;

	/* tell server which Unix caps we support */
	if (cap_unix(tcon->ses)) {
		/*
		 * reset of caps checks mount to see if unix extensions disabled
		 * for just this mount.
		 */
4061
		reset_cifs_unix_caps(*xid, tcon, cifs_sb, ctx);
P
Paulo Alcantara 已提交
4062 4063 4064 4065 4066 4067 4068 4069
		if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
		    (le64_to_cpu(tcon->fsUnixInfo.Capability) &
		     CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
			return -EACCES;
	} else
		tcon->unix_ext = 0; /* server does not support them */

	/* do not care if a following call succeed - informational */
4070
	if (!tcon->pipe && server->ops->qfs_tcon) {
4071
		server->ops->qfs_tcon(*xid, tcon, cifs_sb);
4072 4073
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
			if (tcon->fsDevInfo.DeviceCharacteristics &
4074
			    cpu_to_le32(FILE_READ_ONLY_DEVICE))
4075
				cifs_dbg(VFS, "mounted to read only share\n");
4076 4077
			else if ((cifs_sb->mnt_cifs_flags &
				  CIFS_MOUNT_RW_CACHE) == 0)
4078
				cifs_dbg(VFS, "read only mount of RW share\n");
4079
			/* no need to log a RW mount of a typical RW share */
4080 4081
		}
	}
P
Paulo Alcantara 已提交
4082

4083 4084
	cifs_sb->wsize = server->ops->negotiate_wsize(tcon, ctx);
	cifs_sb->rsize = server->ops->negotiate_rsize(tcon, ctx);
P
Paulo Alcantara 已提交
4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113

	return 0;
}

static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
			     struct cifs_tcon *tcon)
{
	struct tcon_link *tlink;

	/* hang the tcon off of the superblock */
	tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
	if (tlink == NULL)
		return -ENOMEM;

	tlink->tl_uid = ses->linux_uid;
	tlink->tl_tcon = tcon;
	tlink->tl_time = jiffies;
	set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
	set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);

	cifs_sb->master_tlink = tlink;
	spin_lock(&cifs_sb->tlink_tree_lock);
	tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
	spin_unlock(&cifs_sb->tlink_tree_lock);

	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
				TLINK_IDLE_EXPIRE);
	return 0;
}
J
Jeff Layton 已提交
4114

S
Steve French 已提交
4115
#ifdef CONFIG_CIFS_DFS_UPCALL
4116 4117 4118 4119
/*
 * cifs_build_path_to_root returns full path to root when we do not have an
 * exiting connection (tcon)
 */
I
Igor Mammedov 已提交
4120
static char *
4121
build_unc_path_to_root(const struct smb3_fs_context *ctx,
4122
		       const struct cifs_sb_info *cifs_sb, bool useppath)
I
Igor Mammedov 已提交
4123
{
4124
	char *full_path, *pos;
4125 4126 4127
	unsigned int pplen = useppath && ctx->prepath ?
		strlen(ctx->prepath) + 1 : 0;
	unsigned int unc_len = strnlen(ctx->UNC, MAX_TREE_SIZE + 1);
I
Igor Mammedov 已提交
4128

4129 4130 4131
	if (unc_len > MAX_TREE_SIZE)
		return ERR_PTR(-EINVAL);

4132
	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
I
Igor Mammedov 已提交
4133 4134 4135
	if (full_path == NULL)
		return ERR_PTR(-ENOMEM);

4136
	memcpy(full_path, ctx->UNC, unc_len);
4137 4138 4139
	pos = full_path + unc_len;

	if (pplen) {
4140
		*pos = CIFS_DIR_SEP(cifs_sb);
4141
		memcpy(pos + 1, ctx->prepath, pplen);
4142 4143 4144 4145
		pos += pplen;
	}

	*pos = '\0'; /* add trailing null */
4146
	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
4147
	cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
I
Igor Mammedov 已提交
4148 4149
	return full_path;
}
4150

4151 4152 4153
/**
 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
 *
4154
 *
4155 4156 4157
 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
 * to a string containing updated options for the submount.  Otherwise it
 * will be left untouched.
4158 4159 4160 4161 4162
 *
 * Returns the rc from get_dfs_path to the caller, which can be used to
 * determine whether there were referrals.
 */
static int
4163
expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
4164
		    struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb,
4165
		    char *ref_path)
4166 4167
{
	int rc;
4168
	struct dfs_info3_param referral = {0};
4169
	char *full_path = NULL, *mdata = NULL;
4170

4171 4172 4173
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
		return -EREMOTE;

4174
	full_path = build_unc_path_to_root(ctx, cifs_sb, true);
4175 4176 4177
	if (IS_ERR(full_path))
		return PTR_ERR(full_path);

4178 4179 4180
	rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
			    ref_path, &referral, NULL);
	if (!rc) {
4181 4182 4183
		char *fake_devname = NULL;

		mdata = cifs_compose_mount_options(cifs_sb->mountdata,
4184
						   full_path + 1, &referral,
4185
						   &fake_devname);
4186
		free_dfs_info_param(&referral);
4187

4188 4189 4190
		if (IS_ERR(mdata)) {
			rc = PTR_ERR(mdata);
			mdata = NULL;
J
Jeff Layton 已提交
4191
		} else {
4192 4193
			cifs_cleanup_volume_info_contents(ctx);
			rc = cifs_setup_volume_info(ctx, mdata,
4194
						    fake_devname, false);
4195
		}
J
Jeff Layton 已提交
4196 4197
		kfree(fake_devname);
		kfree(cifs_sb->mountdata);
4198
		cifs_sb->mountdata = mdata;
4199 4200 4201 4202
	}
	kfree(full_path);
	return rc;
}
4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215

static inline int get_next_dfs_tgt(const char *path,
				   struct dfs_cache_tgt_list *tgt_list,
				   struct dfs_cache_tgt_iterator **tgt_it)
{
	if (!*tgt_it)
		*tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
	else
		*tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
	return !*tgt_it ? -EHOSTDOWN : 0;
}

static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4216
			   struct smb3_fs_context *fake_ctx, struct smb3_fs_context *ctx)
4217 4218 4219 4220 4221 4222 4223 4224
{
	const char *tgt = dfs_cache_get_tgt_name(tgt_it);
	int len = strlen(tgt) + 2;
	char *new_unc;

	new_unc = kmalloc(len, GFP_KERNEL);
	if (!new_unc)
		return -ENOMEM;
4225
	scnprintf(new_unc, len, "\\%s", tgt);
4226

4227 4228
	kfree(ctx->UNC);
	ctx->UNC = new_unc;
4229

4230 4231 4232 4233
	if (fake_ctx->prepath) {
		kfree(ctx->prepath);
		ctx->prepath = fake_ctx->prepath;
		fake_ctx->prepath = NULL;
4234
	}
4235
	memcpy(&ctx->dstaddr, &fake_ctx->dstaddr, sizeof(ctx->dstaddr));
4236 4237 4238 4239

	return 0;
}

4240
static int setup_dfs_tgt_conn(const char *path, const char *full_path,
4241
			      const struct dfs_cache_tgt_iterator *tgt_it,
4242 4243 4244
			      struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx,
			      unsigned int *xid, struct TCP_Server_Info **server,
			      struct cifs_ses **ses, struct cifs_tcon **tcon)
4245 4246 4247 4248
{
	int rc;
	struct dfs_info3_param ref = {0};
	char *mdata = NULL, *fake_devname = NULL;
4249
	struct smb3_fs_context fake_ctx = {NULL};
4250 4251 4252 4253 4254 4255 4256

	cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);

	rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
	if (rc)
		return rc;

4257
	mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname);
4258 4259 4260 4261 4262 4263 4264
	free_dfs_info_param(&ref);

	if (IS_ERR(mdata)) {
		rc = PTR_ERR(mdata);
		mdata = NULL;
	} else {
		cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4265 4266
		rc = cifs_setup_volume_info((struct smb3_fs_context *)&fake_ctx,
					    mdata, fake_devname, false);
4267 4268 4269 4270 4271 4272
	}
	kfree(mdata);
	kfree(fake_devname);

	if (!rc) {
		/*
4273
		 * We use a 'fake_ctx' here because we need pass it down to the
4274 4275 4276 4277
		 * mount_{get,put} functions to test connection against new DFS
		 * targets.
		 */
		mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4278
		rc = mount_get_conns(&fake_ctx, cifs_sb, xid, server, ses,
4279
				     tcon);
4280
		if (!rc || (*server && *ses)) {
4281 4282
			/*
			 * We were able to connect to new target server.
4283
			 * Update current context with new target server.
4284
			 */
4285
			rc = update_vol_info(tgt_it, &fake_ctx, ctx);
4286 4287
		}
	}
4288
	cifs_cleanup_volume_info_contents((struct smb3_fs_context *)&fake_ctx);
4289 4290 4291
	return rc;
}

4292
static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb,
4293 4294 4295
			   struct smb3_fs_context *ctx, struct cifs_ses *root_ses,
			   unsigned int *xid, struct TCP_Server_Info **server,
			   struct cifs_ses **ses, struct cifs_tcon **tcon)
4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313
{
	int rc;
	struct dfs_cache_tgt_list tgt_list;
	struct dfs_cache_tgt_iterator *tgt_it = NULL;

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
		return -EOPNOTSUPP;

	rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
	if (rc)
		return rc;

	for (;;) {
		/* Get next DFS target server - if any */
		rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
		if (rc)
			break;
		/* Connect to next DFS target */
4314
		rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, ctx, xid, server, ses,
4315 4316
					tcon);
		if (!rc || (*server && *ses))
4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331
			break;
	}
	if (!rc) {
		/*
		 * Update DFS target hint in DFS referral cache with the target
		 * server we successfully reconnected to.
		 */
		rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
					      cifs_sb->local_nls,
					      cifs_remap(cifs_sb), path,
					      tgt_it);
	}
	dfs_cache_free_tgts(&tgt_list);
	return rc;
}
S
Steve French 已提交
4332
#endif
I
Igor Mammedov 已提交
4333

4334
int
4335
cifs_setup_volume_info(struct smb3_fs_context *ctx, char *mount_data,
4336
			const char *devname, bool is_smb3)
L
Linus Torvalds 已提交
4337
{
4338
	int rc = 0;
L
Linus Torvalds 已提交
4339

4340
	if (cifs_parse_mount_options(mount_data, devname, ctx, is_smb3))
4341
		return -EINVAL;
L
Linus Torvalds 已提交
4342

4343
	if (ctx->nullauth) {
4344
		cifs_dbg(FYI, "Anonymous login\n");
4345 4346 4347
		kfree(ctx->username);
		ctx->username = NULL;
	} else if (ctx->username) {
L
Linus Torvalds 已提交
4348
		/* BB fixme parse for domain name here */
4349
		cifs_dbg(FYI, "Username: %s\n", ctx->username);
L
Linus Torvalds 已提交
4350
	} else {
4351
		cifs_dbg(VFS, "No username specified\n");
4352 4353
	/* In userspace mount helper we can get user name from alternate
	   locations such as env variables and files on disk */
4354
		return -EINVAL;
L
Linus Torvalds 已提交
4355 4356 4357
	}

	/* this is needed for ASCII cp to Unicode converts */
4358
	if (ctx->iocharset == NULL) {
4359
		/* load_nls_default cannot return null */
4360
		ctx->local_nls = load_nls_default();
L
Linus Torvalds 已提交
4361
	} else {
4362 4363
		ctx->local_nls = load_nls(ctx->iocharset);
		if (ctx->local_nls == NULL) {
4364
			cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
4365
				 ctx->iocharset);
4366
			return -ELIBACC;
L
Linus Torvalds 已提交
4367 4368
		}
	}
4369 4370 4371 4372

	return rc;
}

4373
struct smb3_fs_context *
4374
cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
4375 4376
{
	int rc;
4377
	struct smb3_fs_context *ctx;
4378

4379 4380
	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
	if (!ctx)
4381 4382
		return ERR_PTR(-ENOMEM);

4383
	rc = cifs_setup_volume_info(ctx, mount_data, devname, is_smb3);
4384
	if (rc) {
4385 4386
		cifs_cleanup_volume_info(ctx);
		ctx = ERR_PTR(rc);
4387 4388
	}

4389
	return ctx;
4390 4391
}

4392 4393 4394 4395 4396
static int
cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
					unsigned int xid,
					struct cifs_tcon *tcon,
					struct cifs_sb_info *cifs_sb,
4397 4398
					char *full_path,
					int added_treename)
4399 4400 4401 4402
{
	int rc;
	char *s;
	char sep, tmp;
4403
	int skip = added_treename ? 1 : 0;
4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417

	sep = CIFS_DIR_SEP(cifs_sb);
	s = full_path;

	rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
	while (rc == 0) {
		/* skip separators */
		while (*s == sep)
			s++;
		if (!*s)
			break;
		/* next separator */
		while (*s && *s != sep)
			s++;
4418 4419 4420 4421 4422 4423 4424 4425
		/*
		 * if the treename is added, we then have to skip the first
		 * part within the separators
		 */
		if (skip) {
			skip = 0;
			continue;
		}
4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438
		/*
		 * temporarily null-terminate the path at the end of
		 * the current component
		 */
		tmp = *s;
		*s = 0;
		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
						     full_path);
		*s = tmp;
	}
	return rc;
}

P
Paulo Alcantara 已提交
4439 4440 4441 4442
/*
 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
 * otherwise 0.
 */
4443
static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx,
P
Paulo Alcantara 已提交
4444 4445 4446
			  const unsigned int xid,
			  struct TCP_Server_Info *server,
			  struct cifs_tcon *tcon)
4447
{
4448
	int rc;
P
Paulo Alcantara 已提交
4449
	char *full_path;
4450

P
Paulo Alcantara 已提交
4451 4452
	if (!server->ops->is_path_accessible)
		return -EOPNOTSUPP;
4453

P
Paulo Alcantara 已提交
4454 4455 4456
	/*
	 * cifs_build_path_to_root works only when we have a valid tcon
	 */
4457
	full_path = cifs_build_path_to_root(ctx, cifs_sb, tcon,
P
Paulo Alcantara 已提交
4458 4459 4460
					    tcon->Flags & SMB_SHARE_IS_IN_DFS);
	if (full_path == NULL)
		return -ENOMEM;
4461

P
Paulo Alcantara 已提交
4462
	cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
L
Linus Torvalds 已提交
4463

P
Paulo Alcantara 已提交
4464 4465 4466 4467 4468
	rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
					     full_path);
	if (rc != 0 && rc != -EREMOTE) {
		kfree(full_path);
		return rc;
4469
	}
S
Steve French 已提交
4470

P
Paulo Alcantara 已提交
4471 4472
	if (rc != -EREMOTE) {
		rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4473
			cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
P
Paulo Alcantara 已提交
4474
		if (rc != 0) {
J
Joe Perches 已提交
4475
			cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
P
Paulo Alcantara 已提交
4476 4477 4478
			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
			rc = 0;
		}
4479
	}
I
Igor Mammedov 已提交
4480

P
Paulo Alcantara 已提交
4481 4482 4483
	kfree(full_path);
	return rc;
}
4484

P
Paulo Alcantara 已提交
4485
#ifdef CONFIG_CIFS_DFS_UPCALL
4486 4487
static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
			 struct cifs_ses **root_ses)
4488
{
4489 4490 4491
	if (ses) {
		spin_lock(&cifs_tcp_ses_lock);
		ses->ses_count++;
4492 4493
		if (ses->tcon_ipc)
			ses->tcon_ipc->remap = cifs_remap(cifs_sb);
4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505
		spin_unlock(&cifs_tcp_ses_lock);
	}
	*root_ses = ses;
}

static void put_root_ses(struct cifs_ses *ses)
{
	if (ses)
		cifs_put_smb_ses(ses);
}

/* Check if a path component is remote and then update @dfs_path accordingly */
4506
static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx,
4507 4508 4509 4510 4511 4512 4513 4514 4515 4516
			     const unsigned int xid, struct TCP_Server_Info *server,
			     struct cifs_tcon *tcon, char **dfs_path)
{
	char *path, *s;
	char sep = CIFS_DIR_SEP(cifs_sb), tmp;
	char *npath;
	int rc = 0;
	int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS;
	int skip = added_treename;

4517
	path = cifs_build_path_to_root(ctx, cifs_sb, tcon, added_treename);
4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547
	if (!path)
		return -ENOMEM;

	/*
	 * Walk through the path components in @path and check if they're accessible. In case any of
	 * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path
	 * (NOT including the remaining components).
	 */
	s = path;
	do {
		/* skip separators */
		while (*s && *s == sep)
			s++;
		if (!*s)
			break;
		/* next separator */
		while (*s && *s != sep)
			s++;
		/*
		 * if the treename is added, we then have to skip the first
		 * part within the separators
		 */
		if (skip) {
			skip = 0;
			continue;
		}
		tmp = *s;
		*s = 0;
		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path);
		if (rc && rc == -EREMOTE) {
4548
			struct smb3_fs_context v = {NULL};
4549 4550 4551 4552 4553 4554 4555 4556 4557
			/* if @path contains a tree name, skip it in the prefix path */
			if (added_treename) {
				rc = cifs_parse_devname(path, &v);
				if (rc)
					break;
				rc = -EREMOTE;
				npath = build_unc_path_to_root(&v, cifs_sb, true);
				cifs_cleanup_volume_info_contents(&v);
			} else {
4558
				v.UNC = ctx->UNC;
4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573
				v.prepath = path + 1;
				npath = build_unc_path_to_root(&v, cifs_sb, true);
			}
			if (IS_ERR(npath)) {
				rc = PTR_ERR(npath);
				break;
			}
			kfree(*dfs_path);
			*dfs_path = npath;
		}
		*s = tmp;
	} while (rc == 0);

	kfree(path);
	return rc;
4574 4575
}

4576
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
P
Paulo Alcantara 已提交
4577 4578 4579
{
	int rc = 0;
	unsigned int xid;
4580 4581
	struct TCP_Server_Info *server = NULL;
	struct cifs_ses *ses = NULL, *root_ses = NULL;
P
Paulo Alcantara 已提交
4582
	struct cifs_tcon *tcon = NULL;
4583 4584 4585 4586
	int count = 0;
	char *ref_path = NULL, *full_path = NULL;
	char *oldmnt = NULL;
	char *mntdata = NULL;
4587

4588
	rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon);
4589
	/*
4590 4591
	 * Unconditionally try to get an DFS referral (even cached) to determine whether it is an
	 * DFS mount.
4592
	 *
4593 4594
	 * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem
	 * to respond with PATH_NOT_COVERED to requests that include the prefix.
4595
	 */
4596
	if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), ctx->UNC + 1, NULL,
4597 4598 4599 4600 4601
			   NULL)) {
		/* No DFS referral was returned.  Looks like a regular share. */
		if (rc)
			goto error;
		/* Check if it is fully accessible and then mount it */
4602
		rc = is_path_remote(cifs_sb, ctx, xid, server, tcon);
4603 4604 4605 4606
		if (!rc)
			goto out;
		if (rc != -EREMOTE)
			goto error;
4607
	}
4608 4609 4610
	/* Save mount options */
	mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL);
	if (!mntdata) {
4611 4612 4613
		rc = -ENOMEM;
		goto error;
	}
4614
	/* Get path of DFS root */
4615
	ref_path = build_unc_path_to_root(ctx, cifs_sb, false);
4616 4617 4618
	if (IS_ERR(ref_path)) {
		rc = PTR_ERR(ref_path);
		ref_path = NULL;
4619 4620
		goto error;
	}
I
Igor Mammedov 已提交
4621

4622 4623 4624
	set_root_ses(cifs_sb, ses, &root_ses);
	do {
		/* Save full path of last DFS path we used to resolve final target server */
4625
		kfree(full_path);
4626
		full_path = build_unc_path_to_root(ctx, cifs_sb, !!count);
4627 4628
		if (IS_ERR(full_path)) {
			rc = PTR_ERR(full_path);
4629
			full_path = NULL;
4630 4631
			break;
		}
4632 4633
		/* Chase referral */
		oldmnt = cifs_sb->mountdata;
4634
		rc = expand_dfs_referral(xid, root_ses, ctx, cifs_sb, ref_path + 1);
P
Paulo Alcantara 已提交
4635 4636
		if (rc)
			break;
4637 4638
		/* Connect to new DFS target only if we were redirected */
		if (oldmnt != cifs_sb->mountdata) {
P
Paulo Alcantara 已提交
4639
			mount_put_conns(cifs_sb, xid, server, ses, tcon);
4640
			rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon);
P
Paulo Alcantara 已提交
4641
		}
4642 4643
		if (rc && !server && !ses) {
			/* Failed to connect. Try to connect to other targets in the referral. */
4644
			rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, ctx, root_ses, &xid,
4645
					     &server, &ses, &tcon);
I
Igor Mammedov 已提交
4646
		}
4647 4648 4649 4650 4651
		if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses)
			break;
		if (!tcon)
			continue;
		/* Make sure that requests go through new root servers */
4652
		if (is_tcon_dfs(tcon)) {
4653 4654 4655 4656
			put_root_ses(root_ses);
			set_root_ses(cifs_sb, ses, &root_ses);
		}
		/* Check for remaining path components and then continue chasing them (-EREMOTE) */
4657
		rc = check_dfs_prepath(cifs_sb, ctx, xid, server, tcon, &ref_path);
4658 4659 4660 4661
		/* Prevent recursion on broken link referrals */
		if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS)
			rc = -ELOOP;
	} while (rc == -EREMOTE);
I
Igor Mammedov 已提交
4662

4663
	if (rc)
P
Paulo Alcantara 已提交
4664
		goto error;
4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677
	put_root_ses(root_ses);
	root_ses = NULL;
	kfree(ref_path);
	ref_path = NULL;
	/*
	 * Store DFS full path in both superblock and tree connect structures.
	 *
	 * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so
	 * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS
	 * links, the prefix path is included in both and may be changed during reconnect.  See
	 * cifs_tree_connect().
	 */
	cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL);
4678 4679 4680 4681
	if (!cifs_sb->origin_fullpath) {
		rc = -ENOMEM;
		goto error;
	}
4682 4683 4684 4685
	spin_lock(&cifs_tcp_ses_lock);
	tcon->dfs_path = full_path;
	full_path = NULL;
	tcon->remap = cifs_remap(cifs_sb);
4686 4687
	spin_unlock(&cifs_tcp_ses_lock);

4688 4689
	/* Add original context for DFS cache to be used when refreshing referrals */
	rc = dfs_cache_add_vol(mntdata, ctx, cifs_sb->origin_fullpath);
4690
	if (rc)
4691
		goto error;
4692 4693 4694 4695 4696 4697
	/*
	 * After reconnecting to a different server, unique ids won't
	 * match anymore, so we disable serverino. This prevents
	 * dentry revalidation to think the dentry are stale (ESTALE).
	 */
	cifs_autodisable_serverino(cifs_sb);
4698 4699 4700 4701 4702 4703
	/*
	 * Force the use of prefix path to support failover on DFS paths that
	 * resolve to targets that have different prefix paths.
	 */
	cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
	kfree(cifs_sb->prepath);
4704 4705
	cifs_sb->prepath = ctx->prepath;
	ctx->prepath = NULL;
4706

P
Paulo Alcantara 已提交
4707 4708
out:
	free_xid(xid);
4709
	cifs_try_adding_channels(ses);
P
Paulo Alcantara 已提交
4710
	return mount_setup_tlink(cifs_sb, ses, tcon);
4711

P
Paulo Alcantara 已提交
4712
error:
4713
	kfree(ref_path);
4714
	kfree(full_path);
4715 4716 4717
	kfree(mntdata);
	kfree(cifs_sb->origin_fullpath);
	put_root_ses(root_ses);
P
Paulo Alcantara 已提交
4718 4719 4720 4721
	mount_put_conns(cifs_sb, xid, server, ses, tcon);
	return rc;
}
#else
4722
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
P
Paulo Alcantara 已提交
4723 4724 4725 4726 4727 4728
{
	int rc = 0;
	unsigned int xid;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
4729

4730
	rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon);
P
Paulo Alcantara 已提交
4731 4732
	if (rc)
		goto error;
4733

P
Paulo Alcantara 已提交
4734
	if (tcon) {
4735
		rc = is_path_remote(cifs_sb, ctx, xid, server, tcon);
P
Paulo Alcantara 已提交
4736 4737 4738 4739
		if (rc == -EREMOTE)
			rc = -EOPNOTSUPP;
		if (rc)
			goto error;
I
Igor Mammedov 已提交
4740 4741
	}

4742
	free_xid(xid);
P
Paulo Alcantara 已提交
4743 4744 4745 4746 4747

	return mount_setup_tlink(cifs_sb, ses, tcon);

error:
	mount_put_conns(cifs_sb, xid, server, ses, tcon);
L
Linus Torvalds 已提交
4748 4749
	return rc;
}
P
Paulo Alcantara 已提交
4750
#endif
L
Linus Torvalds 已提交
4751

4752
/*
A
Aurelien Aptel 已提交
4753
 * Issue a TREE_CONNECT request.
4754
 */
L
Linus Torvalds 已提交
4755
int
4756
CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
4757
	 const char *tree, struct cifs_tcon *tcon,
L
Linus Torvalds 已提交
4758 4759 4760 4761 4762 4763 4764 4765
	 const struct nls_table *nls_codepage)
{
	struct smb_hdr *smb_buffer;
	struct smb_hdr *smb_buffer_response;
	TCONX_REQ *pSMB;
	TCONX_RSP *pSMBr;
	unsigned char *bcc_ptr;
	int rc = 0;
4766 4767
	int length;
	__u16 bytes_left, count;
L
Linus Torvalds 已提交
4768 4769 4770 4771 4772

	if (ses == NULL)
		return -EIO;

	smb_buffer = cifs_buf_get();
S
Steve French 已提交
4773
	if (smb_buffer == NULL)
L
Linus Torvalds 已提交
4774
		return -ENOMEM;
S
Steve French 已提交
4775

L
Linus Torvalds 已提交
4776 4777 4778 4779
	smb_buffer_response = smb_buffer;

	header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
			NULL /*no tid */ , 4 /*wct */ );
4780

4781
	smb_buffer->Mid = get_next_mid(ses->server);
L
Linus Torvalds 已提交
4782 4783 4784 4785 4786 4787 4788
	smb_buffer->Uid = ses->Suid;
	pSMB = (TCONX_REQ *) smb_buffer;
	pSMBr = (TCONX_RSP *) smb_buffer_response;

	pSMB->AndXCommand = 0xFF;
	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
	bcc_ptr = &pSMB->Password[0];
A
Aurelien Aptel 已提交
4789
	if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
4790
		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
4791
		*bcc_ptr = 0; /* password is null byte */
4792
		bcc_ptr++;              /* skip password */
4793
		/* already aligned so no need to do it below */
4794
	} else {
4795
		pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
4796 4797 4798
		/* BB FIXME add code to fail this if NTLMv2 or Kerberos
		   specified as required (when that support is added to
		   the vfs in the future) as only NTLM or the much
4799
		   weaker LANMAN (which we do not send by default) is accepted
4800 4801
		   by Samba (not sure whether other servers allow
		   NTLMv2 password here) */
4802
#ifdef CONFIG_CIFS_WEAK_PW_HASH
4803
		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
4804
		    (ses->sectype == LANMAN))
4805
			calc_lanman_hash(tcon->password, ses->server->cryptkey,
4806
					 ses->server->sec_mode &
4807 4808
					    SECMODE_PW_ENCRYPT ? true : false,
					 bcc_ptr);
4809 4810
		else
#endif /* CIFS_WEAK_PW_HASH */
4811
		rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
4812
					bcc_ptr, nls_codepage);
4813 4814 4815 4816 4817 4818
		if (rc) {
			cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
				 __func__, rc);
			cifs_buf_release(smb_buffer);
			return rc;
		}
4819

4820
		bcc_ptr += CIFS_AUTH_RESP_SIZE;
S
Steve French 已提交
4821
		if (ses->capabilities & CAP_UNICODE) {
4822 4823 4824 4825
			/* must align unicode strings */
			*bcc_ptr = 0; /* null byte password */
			bcc_ptr++;
		}
4826
	}
L
Linus Torvalds 已提交
4827

4828
	if (ses->server->sign)
L
Linus Torvalds 已提交
4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839
		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;

	if (ses->capabilities & CAP_STATUS32) {
		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
	}
	if (ses->capabilities & CAP_DFS) {
		smb_buffer->Flags2 |= SMBFLG2_DFS;
	}
	if (ses->capabilities & CAP_UNICODE) {
		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
		length =
4840
		    cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
4841
			6 /* max utf8 char length in bytes */ *
4842 4843
			(/* server len*/ + 256 /* share len */), nls_codepage);
		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
L
Linus Torvalds 已提交
4844 4845 4846 4847 4848 4849 4850 4851 4852
		bcc_ptr += 2;	/* skip trailing null */
	} else {		/* ASCII */
		strcpy(bcc_ptr, tree);
		bcc_ptr += strlen(tree) + 1;
	}
	strcpy(bcc_ptr, "?????");
	bcc_ptr += strlen("?????");
	bcc_ptr += 1;
	count = bcc_ptr - &pSMB->Password[0];
4853
	be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
L
Linus Torvalds 已提交
4854 4855
	pSMB->ByteCount = cpu_to_le16(count);

4856
	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
4857
			 0);
L
Linus Torvalds 已提交
4858 4859

	/* above now done in SendReceive */
A
Aurelien Aptel 已提交
4860
	if (rc == 0) {
4861 4862
		bool is_unicode;

L
Linus Torvalds 已提交
4863
		tcon->tidStatus = CifsGood;
S
Steve French 已提交
4864
		tcon->need_reconnect = false;
L
Linus Torvalds 已提交
4865 4866
		tcon->tid = smb_buffer_response->Tid;
		bcc_ptr = pByteArea(smb_buffer_response);
4867
		bytes_left = get_bcc(smb_buffer_response);
4868
		length = strnlen(bcc_ptr, bytes_left - 2);
4869 4870 4871 4872 4873
		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
			is_unicode = true;
		else
			is_unicode = false;

4874

4875
		/* skip service field (NB: this field is always ASCII) */
4876 4877 4878
		if (length == 3) {
			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
			    (bcc_ptr[2] == 'C')) {
4879
				cifs_dbg(FYI, "IPC connection\n");
A
Aurelien Aptel 已提交
4880 4881
				tcon->ipc = true;
				tcon->pipe = true;
4882 4883 4884 4885
			}
		} else if (length == 2) {
			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
				/* the most common case */
4886
				cifs_dbg(FYI, "disk share connection\n");
4887 4888
			}
		}
4889
		bcc_ptr += length + 1;
4890
		bytes_left -= (length + 1);
4891
		strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
4892 4893

		/* mostly informational -- no need to fail on error here */
4894
		kfree(tcon->nativeFileSystem);
4895
		tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
4896
						      bytes_left, is_unicode,
4897 4898
						      nls_codepage);

4899
		cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
4900

S
Steve French 已提交
4901
		if ((smb_buffer_response->WordCount == 3) ||
S
Steve French 已提交
4902 4903
			 (smb_buffer_response->WordCount == 7))
			/* field is in same location */
4904 4905 4906
			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
		else
			tcon->Flags = 0;
4907
		cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
L
Linus Torvalds 已提交
4908 4909
	}

4910
	cifs_buf_release(smb_buffer);
L
Linus Torvalds 已提交
4911 4912 4913
	return rc;
}

4914 4915 4916 4917 4918 4919 4920
static void delayed_free(struct rcu_head *p)
{
	struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
	unload_nls(sbi->local_nls);
	kfree(sbi);
}

A
Al Viro 已提交
4921 4922
void
cifs_umount(struct cifs_sb_info *cifs_sb)
L
Linus Torvalds 已提交
4923
{
J
Jeff Layton 已提交
4924 4925 4926
	struct rb_root *root = &cifs_sb->tlink_tree;
	struct rb_node *node;
	struct tcon_link *tlink;
4927

4928 4929
	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);

J
Jeff Layton 已提交
4930 4931 4932 4933 4934 4935
	spin_lock(&cifs_sb->tlink_tree_lock);
	while ((node = rb_first(root))) {
		tlink = rb_entry(node, struct tcon_link, tl_rbnode);
		cifs_get_tlink(tlink);
		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
		rb_erase(node, root);
L
Linus Torvalds 已提交
4936

J
Jeff Layton 已提交
4937 4938 4939 4940 4941
		spin_unlock(&cifs_sb->tlink_tree_lock);
		cifs_put_tlink(tlink);
		spin_lock(&cifs_sb->tlink_tree_lock);
	}
	spin_unlock(&cifs_sb->tlink_tree_lock);
4942

4943
	kfree(cifs_sb->mountdata);
4944
	kfree(cifs_sb->prepath);
4945
#ifdef CONFIG_CIFS_DFS_UPCALL
4946
	dfs_cache_del_vol(cifs_sb->origin_fullpath);
4947 4948
	kfree(cifs_sb->origin_fullpath);
#endif
4949
	call_rcu(&cifs_sb->rcu, delayed_free);
4950
}
L
Linus Torvalds 已提交
4951

4952 4953
int
cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
L
Linus Torvalds 已提交
4954 4955
{
	int rc = 0;
4956
	struct TCP_Server_Info *server = cifs_ses_server(ses);
L
Linus Torvalds 已提交
4957

4958 4959 4960
	if (!server->ops->need_neg || !server->ops->negotiate)
		return -ENOSYS;

4961
	/* only send once per connect */
4962
	if (!server->ops->need_neg(server))
4963 4964
		return 0;

4965
	rc = server->ops->negotiate(xid, ses);
4966 4967
	if (rc == 0) {
		spin_lock(&GlobalMid_Lock);
4968
		if (server->tcpStatus == CifsNeedNegotiate)
4969 4970 4971 4972 4973 4974 4975 4976 4977
			server->tcpStatus = CifsGood;
		else
			rc = -EHOSTDOWN;
		spin_unlock(&GlobalMid_Lock);
	}

	return rc;
}

4978 4979 4980
int
cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
		   struct nls_table *nls_info)
4981
{
4982
	int rc = -ENOSYS;
4983
	struct TCP_Server_Info *server = cifs_ses_server(ses);
4984

4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997
	if (!ses->binding) {
		ses->capabilities = server->capabilities;
		if (linuxExtEnabled == 0)
			ses->capabilities &= (~server->vals->cap_unix);

		if (ses->auth_key.response) {
			cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
				 ses->auth_key.response);
			kfree(ses->auth_key.response);
			ses->auth_key.response = NULL;
			ses->auth_key.len = 0;
		}
	}
4998

4999
	cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
5000
		 server->sec_mode, server->capabilities, server->timeAdj);
5001

5002 5003 5004
	if (server->ops->sess_setup)
		rc = server->ops->sess_setup(xid, ses, nls_info);

5005
	if (rc)
5006
		cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
5007

L
Linus Torvalds 已提交
5008 5009 5010
	return rc;
}

5011
static int
5012
cifs_set_vol_auth(struct smb3_fs_context *ctx, struct cifs_ses *ses)
5013
{
5014
	ctx->sectype = ses->sectype;
5015 5016

	/* krb5 is special, since we don't need username or pw */
5017
	if (ctx->sectype == Kerberos)
5018 5019
		return 0;

5020
	return cifs_set_cifscreds(ctx, ses);
5021 5022
}

5023
static struct cifs_tcon *
5024
cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
5025
{
5026
	int rc;
5027 5028 5029
	struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
	struct cifs_ses *ses;
	struct cifs_tcon *tcon = NULL;
5030
	struct smb3_fs_context *ctx;
5031

5032 5033
	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
	if (ctx == NULL)
5034
		return ERR_PTR(-ENOMEM);
5035

5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054
	ctx->local_nls = cifs_sb->local_nls;
	ctx->linux_uid = fsuid;
	ctx->cred_uid = fsuid;
	ctx->UNC = master_tcon->treeName;
	ctx->retry = master_tcon->retry;
	ctx->nocase = master_tcon->nocase;
	ctx->nohandlecache = master_tcon->nohandlecache;
	ctx->local_lease = master_tcon->local_lease;
	ctx->no_lease = master_tcon->no_lease;
	ctx->resilient = master_tcon->use_resilient;
	ctx->persistent = master_tcon->use_persistent;
	ctx->handle_timeout = master_tcon->handle_timeout;
	ctx->no_linux_ext = !master_tcon->unix_ext;
	ctx->linux_ext = master_tcon->posix_extensions;
	ctx->sectype = master_tcon->ses->sectype;
	ctx->sign = master_tcon->ses->sign;
	ctx->seal = master_tcon->seal;

	rc = cifs_set_vol_auth(ctx, master_tcon->ses);
5055 5056 5057 5058
	if (rc) {
		tcon = ERR_PTR(rc);
		goto out;
	}
5059 5060

	/* get a reference for the same TCP session */
5061
	spin_lock(&cifs_tcp_ses_lock);
5062
	++master_tcon->ses->server->srv_count;
5063
	spin_unlock(&cifs_tcp_ses_lock);
5064

5065
	ses = cifs_get_smb_ses(master_tcon->ses->server, ctx);
5066
	if (IS_ERR(ses)) {
5067
		tcon = (struct cifs_tcon *)ses;
5068
		cifs_put_tcp_session(master_tcon->ses->server, 0);
5069 5070 5071
		goto out;
	}

5072
	tcon = cifs_get_tcon(ses, ctx);
5073 5074 5075 5076 5077
	if (IS_ERR(tcon)) {
		cifs_put_smb_ses(ses);
		goto out;
	}

5078
	if (cap_unix(ses))
5079
		reset_cifs_unix_caps(0, tcon, NULL, ctx);
5080

5081
out:
5082 5083 5084
	kfree(ctx->username);
	kfree_sensitive(ctx->password);
	kfree(ctx);
5085 5086 5087 5088

	return tcon;
}

5089
struct cifs_tcon *
5090 5091 5092 5093 5094
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
{
	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
}

J
Jeff Layton 已提交
5095 5096
/* find and return a tlink with given uid */
static struct tcon_link *
5097
tlink_rb_search(struct rb_root *root, kuid_t uid)
J
Jeff Layton 已提交
5098 5099 5100 5101 5102 5103 5104
{
	struct rb_node *node = root->rb_node;
	struct tcon_link *tlink;

	while (node) {
		tlink = rb_entry(node, struct tcon_link, tl_rbnode);

5105
		if (uid_gt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
5106
			node = node->rb_left;
5107
		else if (uid_lt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125
			node = node->rb_right;
		else
			return tlink;
	}
	return NULL;
}

/* insert a tcon_link into the tree */
static void
tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
{
	struct rb_node **new = &(root->rb_node), *parent = NULL;
	struct tcon_link *tlink;

	while (*new) {
		tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
		parent = *new;

5126
		if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
J
Jeff Layton 已提交
5127 5128 5129 5130 5131 5132 5133 5134 5135
			new = &((*new)->rb_left);
		else
			new = &((*new)->rb_right);
	}

	rb_link_node(&new_tlink->tl_rbnode, parent, new);
	rb_insert_color(&new_tlink->tl_rbnode, root);
}

5136 5137 5138 5139 5140 5141 5142
/*
 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
 * current task.
 *
 * If the superblock doesn't refer to a multiuser mount, then just return
 * the master tcon for the mount.
 *
5143
 * First, search the rbtree for an existing tcon for this fsuid. If one
5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155
 * exists, then check to see if it's pending construction. If it is then wait
 * for construction to complete. Once it's no longer pending, check to see if
 * it failed and either return an error or retry construction, depending on
 * the timeout.
 *
 * If one doesn't exist then insert a new tcon_link struct into the tree and
 * try to construct a new one.
 */
struct tcon_link *
cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
{
	int ret;
5156
	kuid_t fsuid = current_fsuid();
5157 5158 5159 5160 5161 5162
	struct tcon_link *tlink, *newtlink;

	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
		return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));

	spin_lock(&cifs_sb->tlink_tree_lock);
J
Jeff Layton 已提交
5163
	tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
5164 5165 5166 5167 5168 5169 5170 5171
	if (tlink)
		cifs_get_tlink(tlink);
	spin_unlock(&cifs_sb->tlink_tree_lock);

	if (tlink == NULL) {
		newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
		if (newtlink == NULL)
			return ERR_PTR(-ENOMEM);
J
Jeff Layton 已提交
5172
		newtlink->tl_uid = fsuid;
5173 5174 5175 5176 5177 5178 5179
		newtlink->tl_tcon = ERR_PTR(-EACCES);
		set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
		set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
		cifs_get_tlink(newtlink);

		spin_lock(&cifs_sb->tlink_tree_lock);
		/* was one inserted after previous search? */
J
Jeff Layton 已提交
5180
		tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
5181 5182 5183 5184 5185 5186 5187
		if (tlink) {
			cifs_get_tlink(tlink);
			spin_unlock(&cifs_sb->tlink_tree_lock);
			kfree(newtlink);
			goto wait_for_construction;
		}
		tlink = newtlink;
J
Jeff Layton 已提交
5188 5189
		tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
		spin_unlock(&cifs_sb->tlink_tree_lock);
5190 5191 5192 5193 5194 5195
	} else {
wait_for_construction:
		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
				  TASK_INTERRUPTIBLE);
		if (ret) {
			cifs_put_tlink(tlink);
5196
			return ERR_PTR(-ERESTARTSYS);
5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223
		}

		/* if it's good, return it */
		if (!IS_ERR(tlink->tl_tcon))
			return tlink;

		/* return error if we tried this already recently */
		if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
			cifs_put_tlink(tlink);
			return ERR_PTR(-EACCES);
		}

		if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
			goto wait_for_construction;
	}

	tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
	clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
	wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);

	if (IS_ERR(tlink->tl_tcon)) {
		cifs_put_tlink(tlink);
		return ERR_PTR(-EACCES);
	}

	return tlink;
}
5224 5225 5226 5227 5228 5229 5230 5231 5232 5233

/*
 * periodic workqueue job that scans tcon_tree for a superblock and closes
 * out tcons.
 */
static void
cifs_prune_tlinks(struct work_struct *work)
{
	struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
						    prune_tlinks.work);
J
Jeff Layton 已提交
5234
	struct rb_root *root = &cifs_sb->tlink_tree;
5235
	struct rb_node *node;
J
Jeff Layton 已提交
5236 5237
	struct rb_node *tmp;
	struct tcon_link *tlink;
5238

J
Jeff Layton 已提交
5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256
	/*
	 * Because we drop the spinlock in the loop in order to put the tlink
	 * it's not guarded against removal of links from the tree. The only
	 * places that remove entries from the tree are this function and
	 * umounts. Because this function is non-reentrant and is canceled
	 * before umount can proceed, this is safe.
	 */
	spin_lock(&cifs_sb->tlink_tree_lock);
	node = rb_first(root);
	while (node != NULL) {
		tmp = node;
		node = rb_next(tmp);
		tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);

		if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
		    atomic_read(&tlink->tl_count) != 0 ||
		    time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
			continue;
5257

J
Jeff Layton 已提交
5258 5259 5260 5261 5262 5263 5264 5265 5266
		cifs_get_tlink(tlink);
		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
		rb_erase(tmp, root);

		spin_unlock(&cifs_sb->tlink_tree_lock);
		cifs_put_tlink(tlink);
		spin_lock(&cifs_sb->tlink_tree_lock);
	}
	spin_unlock(&cifs_sb->tlink_tree_lock);
5267

J
Jeff Layton 已提交
5268
	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
5269 5270
				TLINK_IDLE_EXPIRE);
}
5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284

#ifdef CONFIG_CIFS_DFS_UPCALL
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
	int rc;
	struct TCP_Server_Info *server = tcon->ses->server;
	const struct smb_version_operations *ops = server->ops;
	struct dfs_cache_tgt_list tl;
	struct dfs_cache_tgt_iterator *it = NULL;
	char *tree;
	const char *tcp_host;
	size_t tcp_host_len;
	const char *dfs_host;
	size_t dfs_host_len;
5285
	char *share = NULL, *prefix = NULL;
5286 5287
	struct dfs_info3_param ref = {0};
	bool isroot;
5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302

	tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
	if (!tree)
		return -ENOMEM;

	if (!tcon->dfs_path) {
		if (tcon->ipc) {
			scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
		} else {
			rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
		}
		goto out;
	}

5303
	rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl);
5304 5305
	if (rc)
		goto out;
5306 5307
	isroot = ref.server_type == DFS_TYPE_ROOT;
	free_dfs_info_param(&ref);
5308 5309 5310 5311 5312 5313

	extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);

	for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) {
		bool target_match;

5314 5315
		kfree(share);
		kfree(prefix);
5316 5317
		share = NULL;
		prefix = NULL;
5318 5319

		rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix);
5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345
		if (rc) {
			cifs_dbg(VFS, "%s: failed to parse target share %d\n",
				 __func__, rc);
			continue;
		}

		extract_unc_hostname(share, &dfs_host, &dfs_host_len);

		if (dfs_host_len != tcp_host_len
		    || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
			cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
				 dfs_host, (int)tcp_host_len, tcp_host);

			rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match);
			if (rc) {
				cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
				break;
			}

			if (!target_match) {
				cifs_dbg(FYI, "%s: skipping target\n", __func__);
				continue;
			}
		}

		if (tcon->ipc) {
5346
			scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share);
5347 5348
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
		} else {
5349
			scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
5350
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5351 5352
			/* Only handle prefix paths of DFS link targets */
			if (!rc && !isroot) {
5353
				rc = update_super_prepath(tcon, prefix);
5354 5355 5356 5357 5358 5359 5360
				break;
			}
		}
		if (rc == -EREMOTE)
			break;
	}

5361 5362 5363
	kfree(share);
	kfree(prefix);

5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382
	if (!rc) {
		if (it)
			rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it);
		else
			rc = -ENOENT;
	}
	dfs_cache_free_tgts(&tl);
out:
	kfree(tree);
	return rc;
}
#else
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
	const struct smb_version_operations *ops = tcon->ses->server->ops;

	return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
}
#endif