connect.c 120.6 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/signal.h>
L
Linus Torvalds 已提交
25 26
#include <linux/list.h>
#include <linux/wait.h>
27
#include <linux/slab.h>
L
Linus Torvalds 已提交
28 29 30 31
#include <linux/pagemap.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
#include <linux/mempool.h>
32
#include <linux/delay.h>
33
#include <linux/completion.h>
34
#include <linux/kthread.h>
35
#include <linux/pagevec.h>
36
#include <linux/freezer.h>
37
#include <linux/namei.h>
38
#include <linux/uuid.h>
39
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
40
#include <asm/processor.h>
41
#include <linux/inet.h>
42
#include <linux/module.h>
43
#include <keys/user-type.h>
44
#include <net/ipv6.h>
45
#include <linux/parser.h>
46
#include <linux/bvec.h>
L
Linus Torvalds 已提交
47 48 49 50 51 52 53 54 55
#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"
56
#include "fscache.h"
57
#include "smb2proto.h"
58
#include "smbdirect.h"
L
Linus Torvalds 已提交
59 60

extern mempool_t *cifs_req_poolp;
61
extern bool disable_legacy_dialects;
L
Linus Torvalds 已提交
62

63
/* FIXME: should these be tunable? */
64
#define TLINK_ERROR_EXPIRE	(1 * HZ)
65
#define TLINK_IDLE_EXPIRE	(600 * HZ)
66

67 68 69 70
enum {
	/* Mount options that take no arguments */
	Opt_user_xattr, Opt_nouser_xattr,
	Opt_forceuid, Opt_noforceuid,
J
Jeff Layton 已提交
71
	Opt_forcegid, Opt_noforcegid,
72 73
	Opt_noblocksend, Opt_noautotune,
	Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
74
	Opt_mapposix, Opt_nomapposix,
75 76
	Opt_mapchars, Opt_nomapchars, Opt_sfu,
	Opt_nosfu, Opt_nodfs, Opt_posixpaths,
77
	Opt_noposixpaths, Opt_nounix, Opt_unix,
78 79
	Opt_nocase,
	Opt_brl, Opt_nobrl,
S
Steve French 已提交
80
	Opt_handlecache, Opt_nohandlecache,
81
	Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
82 83 84 85 86 87 88
	Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
	Opt_nohard, Opt_nosoft,
	Opt_nointr, Opt_intr,
	Opt_nostrictsync, Opt_strictsync,
	Opt_serverino, Opt_noserverino,
	Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
	Opt_acl, Opt_noacl, Opt_locallease,
89
	Opt_sign, Opt_seal, Opt_noac,
90
	Opt_fsc, Opt_mfsymlinks,
91
	Opt_multiuser, Opt_sloppy, Opt_nosharesock,
92
	Opt_persistent, Opt_nopersistent,
S
Steve French 已提交
93
	Opt_resilient, Opt_noresilient,
L
Long Li 已提交
94
	Opt_domainauto, Opt_rdma,
95 96 97 98 99 100

	/* Mount options which take numeric value */
	Opt_backupuid, Opt_backupgid, Opt_uid,
	Opt_cruid, Opt_gid, Opt_file_mode,
	Opt_dirmode, Opt_port,
	Opt_rsize, Opt_wsize, Opt_actimeo,
101
	Opt_echo_interval, Opt_max_credits,
102
	Opt_snapshot,
103 104 105

	/* Mount options which take string value */
	Opt_user, Opt_pass, Opt_ip,
106
	Opt_domain, Opt_srcaddr, Opt_iocharset,
107
	Opt_netbiosname, Opt_servern,
108
	Opt_ver, Opt_vers, Opt_sec, Opt_cache,
109 110 111 112 113 114

	/* Mount options to be ignored */
	Opt_ignore,

	/* Options which could be blank */
	Opt_blank_pass,
115 116
	Opt_blank_user,
	Opt_blank_ip,
117 118 119 120 121 122 123 124 125 126

	Opt_err
};

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 已提交
127 128
	{ Opt_forcegid, "forcegid" },
	{ Opt_noforcegid, "noforcegid" },
129 130 131 132 133 134
	{ Opt_noblocksend, "noblocksend" },
	{ Opt_noautotune, "noautotune" },
	{ Opt_hard, "hard" },
	{ Opt_soft, "soft" },
	{ Opt_perm, "perm" },
	{ Opt_noperm, "noperm" },
135
	{ Opt_mapchars, "mapchars" }, /* SFU style */
136
	{ Opt_nomapchars, "nomapchars" },
137 138
	{ Opt_mapposix, "mapposix" }, /* SFM style */
	{ Opt_nomapposix, "nomapposix" },
139 140 141 142 143 144 145
	{ Opt_sfu, "sfu" },
	{ Opt_nosfu, "nosfu" },
	{ Opt_nodfs, "nodfs" },
	{ Opt_posixpaths, "posixpaths" },
	{ Opt_noposixpaths, "noposixpaths" },
	{ Opt_nounix, "nounix" },
	{ Opt_nounix, "nolinux" },
146 147 148 149
	{ Opt_nounix, "noposix" },
	{ Opt_unix, "unix" },
	{ Opt_unix, "linux" },
	{ Opt_unix, "posix" },
150 151 152 153
	{ Opt_nocase, "nocase" },
	{ Opt_nocase, "ignorecase" },
	{ Opt_brl, "brl" },
	{ Opt_nobrl, "nobrl" },
S
Steve French 已提交
154 155
	{ Opt_handlecache, "handlecache" },
	{ Opt_nohandlecache, "nohandlecache" },
156 157
	{ Opt_nobrl, "nolock" },
	{ Opt_forcemandatorylock, "forcemandatorylock" },
158
	{ Opt_forcemandatorylock, "forcemand" },
159 160
	{ Opt_setuids, "setuids" },
	{ Opt_nosetuids, "nosetuids" },
161
	{ Opt_setuidfromacl, "idsfromsid" },
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
	{ 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" },
	{ Opt_cifsacl, "cifsacl" },
	{ Opt_nocifsacl, "nocifsacl" },
	{ Opt_acl, "acl" },
	{ Opt_noacl, "noacl" },
	{ Opt_locallease, "locallease" },
	{ Opt_sign, "sign" },
	{ Opt_seal, "seal" },
	{ Opt_noac, "noac" },
	{ Opt_fsc, "fsc" },
	{ Opt_mfsymlinks, "mfsymlinks" },
	{ Opt_multiuser, "multiuser" },
184
	{ Opt_sloppy, "sloppy" },
185
	{ Opt_nosharesock, "nosharesock" },
186 187
	{ Opt_persistent, "persistenthandles"},
	{ Opt_nopersistent, "nopersistenthandles"},
S
Steve French 已提交
188 189
	{ Opt_resilient, "resilienthandles"},
	{ Opt_noresilient, "noresilienthandles"},
190
	{ Opt_domainauto, "domainauto"},
L
Long Li 已提交
191
	{ Opt_rdma, "rdma"},
192 193 194 195 196 197 198 199 200 201 202 203 204

	{ 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" },
	{ Opt_rsize, "rsize=%s" },
	{ Opt_wsize, "wsize=%s" },
	{ Opt_actimeo, "actimeo=%s" },
S
Steve French 已提交
205
	{ Opt_echo_interval, "echo_interval=%s" },
206
	{ Opt_max_credits, "max_credits=%s" },
207
	{ Opt_snapshot, "snapshot=%s" },
208

209 210
	{ Opt_blank_user, "user=" },
	{ Opt_blank_user, "username=" },
211 212 213
	{ Opt_user, "user=%s" },
	{ Opt_user, "username=%s" },
	{ Opt_blank_pass, "pass=" },
214
	{ Opt_blank_pass, "password=" },
215 216
	{ Opt_pass, "pass=%s" },
	{ Opt_pass, "password=%s" },
217 218
	{ Opt_blank_ip, "ip=" },
	{ Opt_blank_ip, "addr=" },
219 220
	{ Opt_ip, "ip=%s" },
	{ Opt_ip, "addr=%s" },
221 222 223
	{ Opt_ignore, "unc=%s" },
	{ Opt_ignore, "target=%s" },
	{ Opt_ignore, "path=%s" },
224 225 226 227
	{ Opt_domain, "dom=%s" },
	{ Opt_domain, "domain=%s" },
	{ Opt_domain, "workgroup=%s" },
	{ Opt_srcaddr, "srcaddr=%s" },
228
	{ Opt_ignore, "prefixpath=%s" },
229 230 231 232
	{ Opt_iocharset, "iocharset=%s" },
	{ Opt_netbiosname, "netbiosname=%s" },
	{ Opt_servern, "servern=%s" },
	{ Opt_ver, "ver=%s" },
233
	{ Opt_vers, "vers=%s" },
234
	{ Opt_sec, "sec=%s" },
235
	{ Opt_cache, "cache=%s" },
236 237 238

	{ Opt_ignore, "cred" },
	{ Opt_ignore, "credentials" },
239 240
	{ Opt_ignore, "cred=%s" },
	{ Opt_ignore, "credentials=%s" },
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
	{ 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" },
	{ Opt_ignore, "_netdev" },

	{ Opt_err, NULL }
};

enum {
	Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
	Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
261 262
	Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
	Opt_sec_ntlmv2i, Opt_sec_lanman,
263 264 265 266 267 268 269 270 271 272 273 274 275
	Opt_sec_none,

	Opt_sec_err
};

static const match_table_t cifs_secflavor_tokens = {
	{ Opt_sec_krb5, "krb5" },
	{ Opt_sec_krb5i, "krb5i" },
	{ Opt_sec_krb5p, "krb5p" },
	{ Opt_sec_ntlmsspi, "ntlmsspi" },
	{ Opt_sec_ntlmssp, "ntlmssp" },
	{ Opt_ntlm, "ntlm" },
	{ Opt_sec_ntlmi, "ntlmi" },
276 277
	{ Opt_sec_ntlmv2, "nontlm" },
	{ Opt_sec_ntlmv2, "ntlmv2" },
278 279 280 281 282 283 284
	{ Opt_sec_ntlmv2i, "ntlmv2i" },
	{ Opt_sec_lanman, "lanman" },
	{ Opt_sec_none, "none" },

	{ Opt_sec_err, NULL }
};

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
/* cache flavors */
enum {
	Opt_cache_loose,
	Opt_cache_strict,
	Opt_cache_none,
	Opt_cache_err
};

static const match_table_t cifs_cacheflavor_tokens = {
	{ Opt_cache_loose, "loose" },
	{ Opt_cache_strict, "strict" },
	{ Opt_cache_none, "none" },
	{ Opt_cache_err, NULL }
};

300 301
static const match_table_t cifs_smb_version_tokens = {
	{ Smb_1, SMB1_VERSION_STRING },
S
Steve French 已提交
302
	{ Smb_20, SMB20_VERSION_STRING},
303
	{ Smb_21, SMB21_VERSION_STRING },
304
	{ Smb_30, SMB30_VERSION_STRING },
S
Steve French 已提交
305
	{ Smb_302, SMB302_VERSION_STRING },
306
	{ Smb_311, SMB311_VERSION_STRING },
307
	{ Smb_311, ALT_SMB311_VERSION_STRING },
308 309
	{ Smb_3any, SMB3ANY_VERSION_STRING },
	{ Smb_default, SMBDEFAULT_VERSION_STRING },
310
	{ Smb_version_err, NULL }
311 312
};

313 314
static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
J
Jeff Layton 已提交
315
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
316
static void cifs_prune_tlinks(struct work_struct *work);
J
Jeff Layton 已提交
317
static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
318
					const char *devname, bool is_smb3);
L
Linus Torvalds 已提交
319

320 321 322 323 324 325 326 327
/*
 * 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 已提交
328
int
L
Linus Torvalds 已提交
329 330 331
cifs_reconnect(struct TCP_Server_Info *server)
{
	int rc = 0;
332
	struct list_head *tmp, *tmp2;
333 334
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
S
Steve French 已提交
335
	struct mid_q_entry *mid_entry;
336
	struct list_head retry_list;
337

L
Linus Torvalds 已提交
338
	spin_lock(&GlobalMid_Lock);
339
	if (server->tcpStatus == CifsExiting) {
S
Steve French 已提交
340
		/* the demux thread will exit normally
L
Linus Torvalds 已提交
341 342 343 344 345 346 347
		next time through the loop */
		spin_unlock(&GlobalMid_Lock);
		return rc;
	} else
		server->tcpStatus = CifsNeedReconnect;
	spin_unlock(&GlobalMid_Lock);
	server->maxBuf = 0;
348
	server->max_read = 0;
L
Linus Torvalds 已提交
349

350
	cifs_dbg(FYI, "Reconnecting tcp session\n");
L
Linus Torvalds 已提交
351 352 353

	/* before reconnecting the tcp session, mark the smb session (uid)
		and the tid bad so they are not used until reconnected */
354 355
	cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
		 __func__);
356
	spin_lock(&cifs_tcp_ses_lock);
357
	list_for_each(tmp, &server->smb_ses_list) {
358
		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
359
		ses->need_reconnect = true;
360
		list_for_each(tmp2, &ses->tcon_list) {
361
			tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
S
Steve French 已提交
362
			tcon->need_reconnect = true;
L
Linus Torvalds 已提交
363
		}
A
Aurelien Aptel 已提交
364 365
		if (ses->tcon_ipc)
			ses->tcon_ipc->need_reconnect = true;
L
Linus Torvalds 已提交
366
	}
367
	spin_unlock(&cifs_tcp_ses_lock);
368

L
Linus Torvalds 已提交
369
	/* do not want to be sending data on a socket we are freeing */
370
	cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
J
Jeff Layton 已提交
371
	mutex_lock(&server->srv_mutex);
S
Steve French 已提交
372
	if (server->ssocket) {
373 374
		cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
			 server->ssocket->state, server->ssocket->flags);
375
		kernel_sock_shutdown(server->ssocket, SHUT_WR);
376 377
		cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
			 server->ssocket->state, server->ssocket->flags);
L
Linus Torvalds 已提交
378 379 380
		sock_release(server->ssocket);
		server->ssocket = NULL;
	}
381 382
	server->sequence_number = 0;
	server->session_estab = false;
383 384 385
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
386
	server->lstrp = jiffies;
L
Linus Torvalds 已提交
387

388
	/* mark submitted MIDs for retry and issue callback */
389
	INIT_LIST_HEAD(&retry_list);
390
	cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
L
Linus Torvalds 已提交
391
	spin_lock(&GlobalMid_Lock);
392 393
	list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
394 395
		if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
			mid_entry->mid_state = MID_RETRY_NEEDED;
396 397 398
		list_move(&mid_entry->qhead, &retry_list);
	}
	spin_unlock(&GlobalMid_Lock);
399
	mutex_unlock(&server->srv_mutex);
400

401
	cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
402 403
	list_for_each_safe(tmp, tmp2, &retry_list) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
404 405
		list_del_init(&mid_entry->qhead);
		mid_entry->callback(mid_entry);
L
Linus Torvalds 已提交
406 407
	}

408
	do {
409
		try_to_freeze();
410 411

		/* we should try only the port we connected to before */
412
		mutex_lock(&server->srv_mutex);
413 414 415 416
		if (cifs_rdma_enabled(server))
			rc = smbd_reconnect(server);
		else
			rc = generic_ip_connect(server);
S
Steve French 已提交
417
		if (rc) {
418
			cifs_dbg(FYI, "reconnect error %d\n", rc);
419
			mutex_unlock(&server->srv_mutex);
420
			msleep(3000);
L
Linus Torvalds 已提交
421 422 423
		} else {
			atomic_inc(&tcpSesReconnectCount);
			spin_lock(&GlobalMid_Lock);
424
			if (server->tcpStatus != CifsExiting)
425
				server->tcpStatus = CifsNeedNegotiate;
S
Steve French 已提交
426
			spin_unlock(&GlobalMid_Lock);
427
			mutex_unlock(&server->srv_mutex);
L
Linus Torvalds 已提交
428
		}
429
	} while (server->tcpStatus == CifsNeedReconnect);
430

431 432 433
	if (server->tcpStatus == CifsNeedNegotiate)
		mod_delayed_work(cifsiod_wq, &server->echo, 0);

L
Linus Torvalds 已提交
434 435 436
	return rc;
}

437 438 439 440 441 442
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);
443 444 445 446 447 448 449 450 451 452
	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;
453

454
	/*
455 456
	 * We cannot send an echo if it is disabled.
	 * Also, no need to ping if we got a response recently.
457
	 */
458 459

	if (server->tcpStatus == CifsNeedReconnect ||
460 461
	    server->tcpStatus == CifsExiting ||
	    server->tcpStatus == CifsNew ||
462
	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
S
Steve French 已提交
463
	    time_before(jiffies, server->lstrp + echo_interval - HZ))
464 465
		goto requeue_echo;

466
	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
467
	if (rc)
468 469
		cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
			 server->hostname);
470 471

requeue_echo:
472
	queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
473 474
}

475
static bool
476
allocate_buffers(struct TCP_Server_Info *server)
477
{
478 479 480
	if (!server->bigbuf) {
		server->bigbuf = (char *)cifs_buf_get();
		if (!server->bigbuf) {
481
			cifs_dbg(VFS, "No memory for large SMB response\n");
482 483 484 485
			msleep(3000);
			/* retry will check if exiting */
			return false;
		}
486
	} else if (server->large_buf) {
487
		/* we are reusing a dirty large buf, clear its start */
488
		memset(server->bigbuf, 0, HEADER_SIZE(server));
489 490
	}

491 492 493
	if (!server->smallbuf) {
		server->smallbuf = (char *)cifs_small_buf_get();
		if (!server->smallbuf) {
494
			cifs_dbg(VFS, "No memory for SMB response\n");
495 496 497 498 499 500 501
			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 */
502
		memset(server->smallbuf, 0, HEADER_SIZE(server));
503 504 505 506 507
	}

	return true;
}

508 509 510
static bool
server_unresponsive(struct TCP_Server_Info *server)
{
511 512 513 514 515 516 517 518 519 520 521
	/*
	 * We need to wait 2 echo intervals to make sure we handle such
	 * situations right:
	 * 1s  client sends a normal SMB request
	 * 2s  client gets a response
	 * 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.
	 */
522 523
	if ((server->tcpStatus == CifsGood ||
	    server->tcpStatus == CifsNeedNegotiate) &&
S
Steve French 已提交
524 525 526
	    time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
		cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
			 server->hostname, (2 * server->echo_interval) / HZ);
527 528 529 530 531 532 533 534
		cifs_reconnect(server);
		wake_up(&server->response_q);
		return true;
	}

	return false;
}

535 536
static int
cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
537
{
J
Jeff Layton 已提交
538 539
	int length = 0;
	int total_read;
540

541 542
	smb_msg->msg_control = NULL;
	smb_msg->msg_controllen = 0;
543

544
	for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
545 546
		try_to_freeze();

547 548
		if (server_unresponsive(server))
			return -ECONNABORTED;
549 550 551 552
		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);
553

554 555
		if (server->tcpStatus == CifsExiting)
			return -ESHUTDOWN;
556

557
		if (server->tcpStatus == CifsNeedReconnect) {
558
			cifs_reconnect(server);
559 560 561 562 563 564
			return -ECONNABORTED;
		}

		if (length == -ERESTARTSYS ||
		    length == -EAGAIN ||
		    length == -EINTR) {
565 566 567 568 569 570 571
			/*
			 * 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 已提交
572
			continue;
573 574 575
		}

		if (length <= 0) {
576
			cifs_dbg(FYI, "Received no data or error: %d\n", length);
577
			cifs_reconnect(server);
578
			return -ECONNABORTED;
579 580
		}
	}
J
Jeff Layton 已提交
581
	return total_read;
582 583
}

J
Jeff Layton 已提交
584 585 586
int
cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
		      unsigned int to_read)
587
{
588 589 590
	struct msghdr smb_msg;
	struct kvec iov = {.iov_base = buf, .iov_len = to_read};
	iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
591

592 593
	return cifs_readv_from_socket(server, &smb_msg);
}
594

595 596
int
cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
L
Long Li 已提交
597
	unsigned int page_offset, unsigned int to_read)
598 599
{
	struct msghdr smb_msg;
L
Long Li 已提交
600 601
	struct bio_vec bv = {
		.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
602 603
	iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
	return cifs_readv_from_socket(server, &smb_msg);
604 605
}

606
static bool
J
Jeff Layton 已提交
607
is_smb_response(struct TCP_Server_Info *server, unsigned char type)
608 609 610 611 612 613
{
	/*
	 * 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 已提交
614 615 616 617 618
	switch (type) {
	case RFC1002_SESSION_MESSAGE:
		/* Regular SMB response */
		return true;
	case RFC1002_SESSION_KEEP_ALIVE:
619
		cifs_dbg(FYI, "RFC 1002 session keep alive\n");
J
Jeff Layton 已提交
620 621
		break;
	case RFC1002_POSITIVE_SESSION_RESPONSE:
622
		cifs_dbg(FYI, "RFC 1002 positive session response\n");
J
Jeff Layton 已提交
623 624
		break;
	case RFC1002_NEGATIVE_SESSION_RESPONSE:
625 626 627 628
		/*
		 * We get this from Windows 98 instead of an error on
		 * SMB negprot response.
		 */
629
		cifs_dbg(FYI, "RFC 1002 negative session response\n");
630 631 632 633 634 635 636 637
		/* 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 已提交
638
		cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
639 640
		cifs_reconnect(server);
		wake_up(&server->response_q);
J
Jeff Layton 已提交
641 642
		break;
	default:
643
		cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
644 645 646
		cifs_reconnect(server);
	}

J
Jeff Layton 已提交
647
	return false;
648 649
}

J
Jeff Layton 已提交
650 651
void
dequeue_mid(struct mid_q_entry *mid, bool malformed)
652
{
653
#ifdef CONFIG_CIFS_STATS2
654
	mid->when_received = jiffies;
655
#endif
656 657
	spin_lock(&GlobalMid_Lock);
	if (!malformed)
658
		mid->mid_state = MID_RESPONSE_RECEIVED;
659
	else
660
		mid->mid_state = MID_RESPONSE_MALFORMED;
661
	list_del_init(&mid->qhead);
662
	spin_unlock(&GlobalMid_Lock);
663
}
664

665 666
static void
handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
667
	   char *buf, int malformed)
668
{
669 670
	if (server->ops->check_trans2 &&
	    server->ops->check_trans2(mid, server, buf, malformed))
671
		return;
672
	mid->resp_buf = buf;
673
	mid->large_buf = server->large_buf;
674 675 676 677 678 679 680 681
	/* 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;
	}
682
	dequeue_mid(mid, malformed);
683 684
}

685 686 687 688 689 690 691 692 693 694 695 696 697 698
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);

	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
	wake_up_all(&server->response_q);

699
	/* check if we have blocked requests that need to free */
P
Pavel Shilovsky 已提交
700
	spin_lock(&server->req_lock);
701 702
	if (server->credits <= 0)
		server->credits = 1;
P
Pavel Shilovsky 已提交
703
	spin_unlock(&server->req_lock);
704 705 706 707 708 709 710 711 712 713
	/*
	 * 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);
714 715 716 717
	if (cifs_rdma_enabled(server) && server->smbd_conn) {
		smbd_destroy(server->smbd_conn);
		server->smbd_conn = NULL;
	}
718 719 720 721 722 723 724 725 726 727 728 729 730 731
	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);
732
			cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
733
			mid_entry->mid_state = MID_SHUTDOWN;
734 735 736 737 738 739 740
			list_move(&mid_entry->qhead, &dispose_list);
		}
		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);
741
			cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
			list_del_init(&mid_entry->qhead);
			mid_entry->callback(mid_entry);
		}
		/* 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.
		 */
758
		cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
759 760 761 762 763 764 765 766 767 768 769 770
		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)
771
		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
772 773
}

774 775 776 777 778
static int
standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
	int length;
	char *buf = server->smallbuf;
779
	unsigned int pdu_length = server->pdu_size;
780 781

	/* make sure this will fit in a large buffer */
782 783
	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
		server->vals->header_preamble_size) {
784
		cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
785 786
		cifs_reconnect(server);
		wake_up(&server->response_q);
787
		return -ECONNABORTED;
788 789 790 791 792
	}

	/* switch to large buffer if too big for a small one */
	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
		server->large_buf = true;
793
		memcpy(server->bigbuf, buf, server->total_read);
794 795 796 797
		buf = server->bigbuf;
	}

	/* now read the rest */
798
	length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
799 800 801
				       pdu_length - HEADER_SIZE(server) + 1
				       + server->vals->header_preamble_size);

802 803 804 805
	if (length < 0)
		return length;
	server->total_read += length;

806
	dump_smb(buf, server->total_read);
807

808 809 810 811 812 813 814 815 816
	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;

817 818 819 820 821 822 823 824 825
	/*
	 * 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.
	 */
826
	length = server->ops->check_message(buf, server->total_read, server);
827 828 829 830
	if (length != 0)
		cifs_dump_mem("Bad SMB: ", buf,
			min_t(unsigned int, server->total_read, 48));

831 832 833 834 835 836 837
	if (server->ops->is_session_expired &&
	    server->ops->is_session_expired(buf)) {
		cifs_reconnect(server);
		wake_up(&server->response_q);
		return -1;
	}

P
Pavel Shilovsky 已提交
838 839 840 841
	if (server->ops->is_status_pending &&
	    server->ops->is_status_pending(buf, server, length))
		return -1;

842 843
	if (!mid)
		return length;
844

845
	handle_mid(mid, server, buf, length);
846
	return 0;
847 848
}

L
Linus Torvalds 已提交
849
static int
850
cifs_demultiplex_thread(void *p)
L
Linus Torvalds 已提交
851 852
{
	int length;
853
	struct TCP_Server_Info *server = p;
854
	unsigned int pdu_length;
855
	unsigned int next_offset;
856
	char *buf = NULL;
857
	struct task_struct *task_to_wake = NULL;
L
Linus Torvalds 已提交
858 859 860
	struct mid_q_entry *mid_entry;

	current->flags |= PF_MEMALLOC;
861
	cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
862 863 864

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

867
	set_freezable();
868
	while (server->tcpStatus != CifsExiting) {
869 870
		if (try_to_freeze())
			continue;
871

872
		if (!allocate_buffers(server))
873
			continue;
874

875 876
		server->large_buf = false;
		buf = server->smallbuf;
877
		pdu_length = 4; /* enough to get RFC1001 header */
878

J
Jeff Layton 已提交
879
		length = cifs_read_from_socket(server, buf, pdu_length);
J
Jeff Layton 已提交
880
		if (length < 0)
L
Linus Torvalds 已提交
881
			continue;
882 883 884 885 886

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

888 889 890 891
		/*
		 * The right amount was read from socket - 4 bytes,
		 * so we can now interpret the length field.
		 */
892
		pdu_length = get_rfc1002_length(buf);
893

894
		cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
J
Jeff Layton 已提交
895
		if (!is_smb_response(server, buf[0]))
S
Steve French 已提交
896
			continue;
897 898
next_pdu:
		server->pdu_size = pdu_length;
899

900
		/* make sure we have enough to get to the MID */
901
		if (server->pdu_size < HEADER_SIZE(server) - 1 -
902
		    server->vals->header_preamble_size) {
903
			cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
904
				 server->pdu_size);
905 906 907
			cifs_reconnect(server);
			wake_up(&server->response_q);
			continue;
908
		}
909

910
		/* read down to the MID */
911 912 913 914
		length = cifs_read_from_socket(server,
			     buf + server->vals->header_preamble_size,
			     HEADER_SIZE(server) - 1
			     - server->vals->header_preamble_size);
915
		if (length < 0)
916
			continue;
917
		server->total_read += length;
L
Linus Torvalds 已提交
918

919 920 921 922 923 924
		if (server->ops->next_header) {
			next_offset = server->ops->next_header(buf);
			if (next_offset)
				server->pdu_size = next_offset;
		}

925
		mid_entry = NULL;
926 927 928 929 930 931 932
		if (server->ops->is_transform_hdr &&
		    server->ops->receive_transform &&
		    server->ops->is_transform_hdr(buf)) {
			length = server->ops->receive_transform(server,
								&mid_entry);
		} else {
			mid_entry = server->ops->find_mid(server, buf);
933

934 935 936 937 938
			if (!mid_entry || !mid_entry->receive)
				length = standard_receive3(server, mid_entry);
			else
				length = mid_entry->receive(server, mid_entry);
		}
939

940 941 942
		if (length < 0) {
			if (mid_entry)
				cifs_mid_q_entry_release(mid_entry);
J
Jeff Layton 已提交
943
			continue;
944
		}
L
Linus Torvalds 已提交
945

946
		if (server->large_buf)
947
			buf = server->bigbuf;
948 949

		server->lstrp = jiffies;
950
		if (mid_entry != NULL) {
951
			mid_entry->resp_buf_size = server->pdu_size;
S
Sachin Prabhu 已提交
952 953 954 955 956 957 958
			if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
			     mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
					server->ops->handle_cancelled_mid)
				server->ops->handle_cancelled_mid(
							mid_entry->resp_buf,
							server);

959 960
			if (!mid_entry->multiRsp || mid_entry->multiEnd)
				mid_entry->callback(mid_entry);
961 962

			cifs_mid_q_entry_release(mid_entry);
S
Sachin Prabhu 已提交
963 964 965 966
		} else if (server->ops->is_oplock_break &&
			   server->ops->is_oplock_break(buf, server)) {
			cifs_dbg(FYI, "Received oplock break\n");
		} else {
967 968
			cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
				 atomic_read(&midCount));
969 970
			cifs_dump_mem("Received Data is: ", buf,
				      HEADER_SIZE(server));
971
#ifdef CONFIG_CIFS_DEBUG2
972
			if (server->ops->dump_detail)
973
				server->ops->dump_detail(buf, server);
974 975
			cifs_dump_mids(server);
#endif /* CIFS_DEBUG2 */
976 977 978 979 980 981 982 983 984
		}
		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;
985 986 987
		}
	} /* end while !EXITING */

988
	/* buffer usually freed in free_mid - need to free it here on exit */
989 990 991
	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 已提交
992

993
	task_to_wake = xchg(&server->tsk, NULL);
994
	clean_demultiplex_info(server);
995 996 997 998 999 1000 1001 1002 1003 1004 1005

	/* 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);
	}

1006
	module_put_and_exit(0);
L
Linus Torvalds 已提交
1007 1008
}

1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
/* 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? */
	src = unc + 2;

	/* 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;
}

1037 1038 1039 1040 1041 1042 1043 1044
static int get_option_ul(substring_t args[], unsigned long *option)
{
	int rc;
	char *string;

	string = match_strdup(args);
	if (string == NULL)
		return -ENOMEM;
1045
	rc = kstrtoul(string, 0, option);
1046 1047 1048 1049 1050
	kfree(string);

	return rc;
}

1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
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;
}
1086 1087 1088 1089 1090 1091 1092

static int cifs_parse_security_flavors(char *value,
				       struct smb_vol *vol)
{

	substring_t args[MAX_OPT_ARGS];

1093 1094 1095 1096 1097 1098 1099
	/*
	 * With mount options, the last one should win. Reset any existing
	 * settings back to default.
	 */
	vol->sectype = Unspecified;
	vol->sign = false;

1100
	switch (match_token(value, cifs_secflavor_tokens, args)) {
1101 1102 1103 1104 1105 1106
	case Opt_sec_krb5p:
		cifs_dbg(VFS, "sec=krb5p is not supported!\n");
		return 1;
	case Opt_sec_krb5i:
		vol->sign = true;
		/* Fallthrough */
1107
	case Opt_sec_krb5:
1108
		vol->sectype = Kerberos;
1109
		break;
1110
	case Opt_sec_ntlmsspi:
1111
		vol->sign = true;
1112
		/* Fallthrough */
1113
	case Opt_sec_ntlmssp:
1114
		vol->sectype = RawNTLMSSP;
1115
		break;
1116
	case Opt_sec_ntlmi:
1117
		vol->sign = true;
1118
		/* Fallthrough */
1119
	case Opt_ntlm:
1120
		vol->sectype = NTLM;
1121
		break;
1122
	case Opt_sec_ntlmv2i:
1123
		vol->sign = true;
1124
		/* Fallthrough */
1125
	case Opt_sec_ntlmv2:
1126
		vol->sectype = NTLMv2;
1127 1128 1129
		break;
#ifdef CONFIG_CIFS_WEAK_PW_HASH
	case Opt_sec_lanman:
1130
		vol->sectype = LANMAN;
1131 1132 1133 1134 1135 1136
		break;
#endif
	case Opt_sec_none:
		vol->nullauth = 1;
		break;
	default:
1137
		cifs_dbg(VFS, "bad security option: %s\n", value);
1138 1139 1140 1141 1142 1143
		return 1;
	}

	return 0;
}

1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
static int
cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
{
	substring_t args[MAX_OPT_ARGS];

	switch (match_token(value, cifs_cacheflavor_tokens, args)) {
	case Opt_cache_loose:
		vol->direct_io = false;
		vol->strict_io = false;
		break;
	case Opt_cache_strict:
		vol->direct_io = false;
		vol->strict_io = true;
		break;
	case Opt_cache_none:
		vol->direct_io = true;
		vol->strict_io = false;
		break;
	default:
1163
		cifs_dbg(VFS, "bad cache= option: %s\n", value);
1164 1165 1166 1167 1168
		return 1;
	}
	return 0;
}

1169
static int
1170
cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
1171 1172 1173 1174
{
	substring_t args[MAX_OPT_ARGS];

	switch (match_token(value, cifs_smb_version_tokens, args)) {
1175
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
1176
	case Smb_1:
1177 1178 1179 1180
		if (disable_legacy_dialects) {
			cifs_dbg(VFS, "mount with legacy dialect disabled\n");
			return 1;
		}
1181 1182 1183 1184
		if (is_smb3) {
			cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
			return 1;
		}
1185 1186 1187
		vol->ops = &smb1_operations;
		vol->vals = &smb1_values;
		break;
S
Steve French 已提交
1188
	case Smb_20:
1189 1190 1191 1192
		if (disable_legacy_dialects) {
			cifs_dbg(VFS, "mount with legacy dialect disabled\n");
			return 1;
		}
1193 1194 1195 1196
		if (is_smb3) {
			cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
			return 1;
		}
1197
		vol->ops = &smb20_operations;
S
Steve French 已提交
1198 1199
		vol->vals = &smb20_values;
		break;
1200 1201 1202 1203 1204 1205 1206 1207
#else
	case Smb_1:
		cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
		return 1;
	case Smb_20:
		cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
		return 1;
#endif /* CIFS_ALLOW_INSECURE_LEGACY */
1208 1209 1210 1211
	case Smb_21:
		vol->ops = &smb21_operations;
		vol->vals = &smb21_values;
		break;
1212
	case Smb_30:
1213
		vol->ops = &smb30_operations;
1214 1215
		vol->vals = &smb30_values;
		break;
S
Steve French 已提交
1216 1217 1218 1219
	case Smb_302:
		vol->ops = &smb30_operations; /* currently identical with 3.0 */
		vol->vals = &smb302_values;
		break;
1220
	case Smb_311:
1221
		vol->ops = &smb311_operations;
1222 1223
		vol->vals = &smb311_values;
		break;
1224 1225 1226 1227 1228 1229 1230 1231
	case Smb_3any:
		vol->ops = &smb30_operations; /* currently identical with 3.0 */
		vol->vals = &smb3any_values;
		break;
	case Smb_default:
		vol->ops = &smb30_operations; /* currently identical with 3.0 */
		vol->vals = &smbdefault_values;
		break;
1232
	default:
1233
		cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
1234 1235 1236 1237 1238
		return 1;
	}
	return 0;
}

1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
/*
 * 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
cifs_parse_devname(const char *devname, struct smb_vol *vol)
{
	char *pos;
	const char *delims = "/\\";
	size_t len;

	/* 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;
	vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
	if (!vol->UNC)
		return -ENOMEM;

	convert_delimiter(vol->UNC, '\\');

1274 1275 1276 1277 1278 1279
	/* skip any delimiter */
	if (*pos == '/' || *pos == '\\')
		pos++;

	/* If pos is NULL then no prepath */
	if (!*pos)
1280 1281 1282 1283 1284 1285 1286 1287 1288
		return 0;

	vol->prepath = kstrdup(pos, GFP_KERNEL);
	if (!vol->prepath)
		return -ENOMEM;

	return 0;
}

L
Linus Torvalds 已提交
1289
static int
1290
cifs_parse_mount_options(const char *mountdata, const char *devname,
1291
			 struct smb_vol *vol, bool is_smb3)
L
Linus Torvalds 已提交
1292
{
1293
	char *data, *end;
1294
	char *mountdata_copy = NULL, *options;
L
Linus Torvalds 已提交
1295 1296
	unsigned int  temp_len, i, j;
	char separator[2];
1297 1298 1299 1300
	short int override_uid = -1;
	short int override_gid = -1;
	bool uid_specified = false;
	bool gid_specified = false;
1301 1302
	bool sloppy = false;
	char *invalid = NULL;
J
Jeff Layton 已提交
1303
	char *nodename = utsname()->nodename;
1304 1305 1306
	char *string = NULL;
	char *tmp_end, *value;
	char delim;
1307
	bool got_ip = false;
1308
	bool got_version = false;
1309 1310
	unsigned short port = 0;
	struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
L
Linus Torvalds 已提交
1311 1312

	separator[0] = ',';
1313
	separator[1] = 0;
1314
	delim = separator[0];
L
Linus Torvalds 已提交
1315

1316 1317 1318
	/* ensure we always start with zeroed-out smb_vol */
	memset(vol, 0, sizeof(*vol));

J
Jeff Layton 已提交
1319 1320 1321 1322 1323
	/*
	 * 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
	 */
1324 1325
	memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
	for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
J
Jeff Layton 已提交
1326 1327
		vol->source_rfc1001_name[i] = toupper(nodename[i]);

1328
	vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
1329 1330 1331
	/* null target name indicates to use *SMBSERVR default called name
	   if we end up sending RFC1001 session initialize */
	vol->target_rfc1001_name[0] = 0;
1332 1333
	vol->cred_uid = current_uid();
	vol->linux_uid = current_uid();
1334
	vol->linux_gid = current_gid();
1335

1336 1337 1338 1339 1340 1341 1342 1343
	/*
	 * 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
	 */
	vol->remap = true;

1344 1345
	/* default to only allowing write access to owner of the mount */
	vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
L
Linus Torvalds 已提交
1346 1347

	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
1348 1349
	/* default is always to request posix paths. */
	vol->posix_paths = 1;
1350 1351
	/* default to using server inode numbers where available */
	vol->server_ino = 1;
1352

1353 1354 1355
	/* default is to use strict cifs caching semantics */
	vol->strict_io = true;

1356 1357
	vol->actimeo = CIFS_DEF_ACTIMEO;

1358 1359 1360
	/* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
	vol->ops = &smb30_operations;
	vol->vals = &smbdefault_values;
1361

R
Rabin Vincent 已提交
1362 1363
	vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;

1364 1365 1366 1367 1368 1369
	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 已提交
1370

1371
	options = mountdata_copy;
1372
	end = options + strlen(options);
1373

1374
	if (strncmp(options, "sep=", 4) == 0) {
S
Steve French 已提交
1375
		if (options[4] != 0) {
L
Linus Torvalds 已提交
1376 1377 1378
			separator[0] = options[4];
			options += 5;
		} else {
1379
			cifs_dbg(FYI, "Null separator not allowed\n");
L
Linus Torvalds 已提交
1380 1381
		}
	}
1382 1383
	vol->backupuid_specified = false; /* no backup intent for a user */
	vol->backupgid_specified = false; /* no backup intent for a group */
1384

1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396
	switch (cifs_parse_devname(devname, vol)) {
	case 0:
		break;
	case -ENOMEM:
		cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
		goto cifs_parse_mount_err;
	case -EINVAL:
		cifs_dbg(VFS, "Malformed UNC in devname.\n");
		goto cifs_parse_mount_err;
	default:
		cifs_dbg(VFS, "Unknown error parsing devname.\n");
		goto cifs_parse_mount_err;
1397 1398
	}

L
Linus Torvalds 已提交
1399
	while ((data = strsep(&options, separator)) != NULL) {
1400 1401 1402 1403
		substring_t args[MAX_OPT_ARGS];
		unsigned long option;
		int token;

L
Linus Torvalds 已提交
1404 1405 1406
		if (!*data)
			continue;

1407 1408 1409 1410 1411 1412 1413 1414 1415 1416
		token = match_token(data, cifs_mount_option_tokens, args);

		switch (token) {

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

		/* Boolean values */
		case Opt_user_xattr:
L
Linus Torvalds 已提交
1417
			vol->no_xattr = 0;
1418 1419
			break;
		case Opt_nouser_xattr:
L
Linus Torvalds 已提交
1420
			vol->no_xattr = 1;
1421 1422
			break;
		case Opt_forceuid:
1423
			override_uid = 1;
1424 1425
			break;
		case Opt_noforceuid:
1426
			override_uid = 0;
1427
			break;
J
Jeff Layton 已提交
1428 1429 1430 1431 1432 1433
		case Opt_forcegid:
			override_gid = 1;
			break;
		case Opt_noforcegid:
			override_gid = 0;
			break;
1434
		case Opt_noblocksend:
1435
			vol->noblocksnd = 1;
1436 1437
			break;
		case Opt_noautotune:
1438
			vol->noautotune = 1;
1439 1440
			break;
		case Opt_hard:
L
Linus Torvalds 已提交
1441
			vol->retry = 1;
1442 1443
			break;
		case Opt_soft:
L
Linus Torvalds 已提交
1444
			vol->retry = 0;
1445 1446
			break;
		case Opt_perm:
L
Linus Torvalds 已提交
1447
			vol->noperm = 0;
1448 1449
			break;
		case Opt_noperm:
L
Linus Torvalds 已提交
1450
			vol->noperm = 1;
1451 1452
			break;
		case Opt_mapchars:
1453 1454
			vol->sfu_remap = true;
			vol->remap = false; /* disable SFM mapping */
1455 1456
			break;
		case Opt_nomapchars:
1457 1458 1459 1460 1461 1462 1463 1464
			vol->sfu_remap = false;
			break;
		case Opt_mapposix:
			vol->remap = true;
			vol->sfu_remap = false; /* disable SFU mapping */
			break;
		case Opt_nomapposix:
			vol->remap = false;
1465 1466
			break;
		case Opt_sfu:
1467
			vol->sfu_emul = 1;
1468 1469
			break;
		case Opt_nosfu:
1470
			vol->sfu_emul = 0;
1471 1472
			break;
		case Opt_nodfs:
S
Steve French 已提交
1473
			vol->nodfs = 1;
1474 1475
			break;
		case Opt_posixpaths:
1476
			vol->posix_paths = 1;
1477 1478
			break;
		case Opt_noposixpaths:
1479
			vol->posix_paths = 0;
1480 1481
			break;
		case Opt_nounix:
1482 1483 1484
			if (vol->linux_ext)
				cifs_dbg(VFS,
					"conflicting unix mount options\n");
1485
			vol->no_linux_ext = 1;
1486
			break;
1487 1488 1489 1490 1491 1492
		case Opt_unix:
			if (vol->no_linux_ext)
				cifs_dbg(VFS,
					"conflicting unix mount options\n");
			vol->linux_ext = 1;
			break;
1493
		case Opt_nocase:
1494
			vol->nocase = 1;
1495 1496
			break;
		case Opt_brl:
1497
			vol->nobrl =  0;
1498 1499
			break;
		case Opt_nobrl:
1500
			vol->nobrl =  1;
1501 1502
			/*
			 * turn off mandatory locking in mode
1503
			 * if remote locking is turned off since the
1504 1505
			 * local vfs will do advisory
			 */
1506 1507
			if (vol->file_mode ==
				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1508
				vol->file_mode = S_IALLUGO;
1509
			break;
S
Steve French 已提交
1510 1511 1512 1513 1514 1515
		case Opt_nohandlecache:
			vol->nohandlecache = 1;
			break;
		case Opt_handlecache:
			vol->nohandlecache = 0;
			break;
1516
		case Opt_forcemandatorylock:
1517
			vol->mand_lock = 1;
1518 1519
			break;
		case Opt_setuids:
L
Linus Torvalds 已提交
1520
			vol->setuids = 1;
1521 1522
			break;
		case Opt_nosetuids:
L
Linus Torvalds 已提交
1523
			vol->setuids = 0;
1524
			break;
1525 1526 1527
		case Opt_setuidfromacl:
			vol->setuidfromacl = 1;
			break;
1528
		case Opt_dynperm:
1529
			vol->dynperm = true;
1530 1531
			break;
		case Opt_nodynperm:
1532
			vol->dynperm = false;
1533 1534
			break;
		case Opt_nohard:
L
Linus Torvalds 已提交
1535
			vol->retry = 0;
1536 1537
			break;
		case Opt_nosoft:
L
Linus Torvalds 已提交
1538
			vol->retry = 1;
1539 1540
			break;
		case Opt_nointr:
L
Linus Torvalds 已提交
1541
			vol->intr = 0;
1542 1543
			break;
		case Opt_intr:
L
Linus Torvalds 已提交
1544
			vol->intr = 1;
1545 1546
			break;
		case Opt_nostrictsync:
1547
			vol->nostrictsync = 1;
1548 1549
			break;
		case Opt_strictsync:
1550
			vol->nostrictsync = 0;
1551 1552
			break;
		case Opt_serverino:
L
Linus Torvalds 已提交
1553
			vol->server_ino = 1;
1554 1555
			break;
		case Opt_noserverino:
L
Linus Torvalds 已提交
1556
			vol->server_ino = 0;
1557 1558
			break;
		case Opt_rwpidforward:
1559
			vol->rwpidforward = 1;
1560 1561
			break;
		case Opt_cifsacl:
1562
			vol->cifs_acl = 1;
1563 1564
			break;
		case Opt_nocifsacl:
1565
			vol->cifs_acl = 0;
1566 1567
			break;
		case Opt_acl:
L
Linus Torvalds 已提交
1568
			vol->no_psx_acl = 0;
1569 1570
			break;
		case Opt_noacl:
L
Linus Torvalds 已提交
1571
			vol->no_psx_acl = 1;
1572 1573
			break;
		case Opt_locallease:
S
Steve French 已提交
1574
			vol->local_lease = 1;
1575 1576
			break;
		case Opt_sign:
1577
			vol->sign = true;
1578 1579
			break;
		case Opt_seal:
1580
			/* we do not do the following in secFlags because seal
1581 1582 1583 1584
			 * is a per tree connection (mount) not a per socket
			 * or per-smb connection option in the protocol
			 * vol->secFlg |= CIFSSEC_MUST_SEAL;
			 */
1585
			vol->seal = 1;
1586 1587
			break;
		case Opt_noac:
1588
			pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1589 1590
			break;
		case Opt_fsc:
1591
#ifndef CONFIG_CIFS_FSCACHE
1592
			cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
1593
			goto cifs_parse_mount_err;
1594
#endif
1595
			vol->fsc = true;
1596 1597
			break;
		case Opt_mfsymlinks:
1598
			vol->mfsymlinks = true;
1599 1600
			break;
		case Opt_multiuser:
J
Jeff Layton 已提交
1601
			vol->multiuser = true;
1602
			break;
1603 1604 1605
		case Opt_sloppy:
			sloppy = true;
			break;
1606 1607 1608
		case Opt_nosharesock:
			vol->nosharesock = true;
			break;
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
		case Opt_nopersistent:
			vol->nopersistent = true;
			if (vol->persistent) {
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_persistent:
			vol->persistent = true;
S
Steve French 已提交
1619
			if ((vol->nopersistent) || (vol->resilient)) {
1620 1621 1622 1623 1624
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
S
Steve French 已提交
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
		case Opt_resilient:
			vol->resilient = true;
			if (vol->persistent) {
				cifs_dbg(VFS,
				  "persistenthandles mount options conflict\n");
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_noresilient:
			vol->resilient = false; /* already the default */
			break;
1636 1637 1638
		case Opt_domainauto:
			vol->domainauto = true;
			break;
L
Long Li 已提交
1639 1640 1641
		case Opt_rdma:
			vol->rdma = true;
			break;
1642 1643 1644

		/* Numeric Values */
		case Opt_backupuid:
1645
			if (get_option_uid(args, &vol->backupuid)) {
1646 1647
				cifs_dbg(VFS, "%s: Invalid backupuid value\n",
					 __func__);
1648 1649 1650
				goto cifs_parse_mount_err;
			}
			vol->backupuid_specified = true;
1651 1652
			break;
		case Opt_backupgid:
1653
			if (get_option_gid(args, &vol->backupgid)) {
1654 1655
				cifs_dbg(VFS, "%s: Invalid backupgid value\n",
					 __func__);
1656 1657 1658
				goto cifs_parse_mount_err;
			}
			vol->backupgid_specified = true;
1659 1660
			break;
		case Opt_uid:
1661
			if (get_option_uid(args, &vol->linux_uid)) {
1662 1663
				cifs_dbg(VFS, "%s: Invalid uid value\n",
					 __func__);
1664 1665 1666 1667 1668
				goto cifs_parse_mount_err;
			}
			uid_specified = true;
			break;
		case Opt_cruid:
1669
			if (get_option_uid(args, &vol->cred_uid)) {
1670 1671
				cifs_dbg(VFS, "%s: Invalid cruid value\n",
					 __func__);
1672 1673 1674 1675
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_gid:
1676
			if (get_option_gid(args, &vol->linux_gid)) {
1677 1678
				cifs_dbg(VFS, "%s: Invalid gid value\n",
					 __func__);
1679 1680 1681 1682 1683 1684
				goto cifs_parse_mount_err;
			}
			gid_specified = true;
			break;
		case Opt_file_mode:
			if (get_option_ul(args, &option)) {
1685 1686
				cifs_dbg(VFS, "%s: Invalid file_mode value\n",
					 __func__);
1687 1688 1689 1690 1691 1692
				goto cifs_parse_mount_err;
			}
			vol->file_mode = option;
			break;
		case Opt_dirmode:
			if (get_option_ul(args, &option)) {
1693 1694
				cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
					 __func__);
1695 1696 1697 1698 1699
				goto cifs_parse_mount_err;
			}
			vol->dir_mode = option;
			break;
		case Opt_port:
1700 1701
			if (get_option_ul(args, &option) ||
			    option > USHRT_MAX) {
1702 1703
				cifs_dbg(VFS, "%s: Invalid port value\n",
					 __func__);
1704 1705
				goto cifs_parse_mount_err;
			}
1706
			port = (unsigned short)option;
1707 1708 1709
			break;
		case Opt_rsize:
			if (get_option_ul(args, &option)) {
1710 1711
				cifs_dbg(VFS, "%s: Invalid rsize value\n",
					 __func__);
1712
				goto cifs_parse_mount_err;
1713 1714 1715 1716 1717
			}
			vol->rsize = option;
			break;
		case Opt_wsize:
			if (get_option_ul(args, &option)) {
1718 1719
				cifs_dbg(VFS, "%s: Invalid wsize value\n",
					 __func__);
1720 1721 1722 1723 1724 1725
				goto cifs_parse_mount_err;
			}
			vol->wsize = option;
			break;
		case Opt_actimeo:
			if (get_option_ul(args, &option)) {
1726 1727
				cifs_dbg(VFS, "%s: Invalid actimeo value\n",
					 __func__);
1728 1729 1730 1731
				goto cifs_parse_mount_err;
			}
			vol->actimeo = HZ * option;
			if (vol->actimeo > CIFS_MAX_ACTIMEO) {
1732
				cifs_dbg(VFS, "attribute cache timeout too large\n");
1733 1734 1735
				goto cifs_parse_mount_err;
			}
			break;
S
Steve French 已提交
1736 1737 1738 1739 1740 1741 1742 1743
		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;
			}
			vol->echo_interval = option;
			break;
1744 1745 1746 1747 1748 1749 1750 1751
		case Opt_snapshot:
			if (get_option_ul(args, &option)) {
				cifs_dbg(VFS, "%s: Invalid snapshot time\n",
					 __func__);
				goto cifs_parse_mount_err;
			}
			vol->snapshot_time = option;
			break;
1752 1753 1754 1755 1756 1757 1758 1759 1760
		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;
			}
			vol->max_credits = option;
			break;
1761 1762 1763

		/* String Arguments */

1764 1765 1766 1767 1768
		case Opt_blank_user:
			/* null user, ie. anonymous authentication */
			vol->nullauth = 1;
			vol->username = NULL;
			break;
1769 1770 1771 1772 1773
		case Opt_user:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1774 1775
			if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
							CIFS_MAX_USERNAME_LEN) {
1776
				pr_warn("CIFS: username too long\n");
1777 1778
				goto cifs_parse_mount_err;
			}
1779 1780

			kfree(vol->username);
1781
			vol->username = kstrdup(string, GFP_KERNEL);
1782
			if (!vol->username)
1783 1784 1785 1786 1787 1788 1789 1790
				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
			 */

1791 1792 1793 1794 1795 1796 1797 1798
			/*
			 * 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 */
1799
				kzfree(vol->password);
1800 1801 1802 1803 1804
				vol->password = NULL;
				break;
			}
			/* Yes it is. Drop down to Opt_pass below.*/
		case Opt_pass:
1805 1806
			/* Obtain the value string */
			value = strchr(data, '=');
1807
			value++;
1808 1809 1810 1811 1812 1813 1814 1815

			/* 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
			 */
1816
			if (tmp_end < end && tmp_end[1] == delim) {
1817 1818
				tmp_end[0] = delim;

1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834
				/* 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;
1835 1836
			}

1837
			kzfree(vol->password);
1838 1839 1840 1841
			/* Now build new password string */
			temp_len = strlen(value);
			vol->password = kzalloc(temp_len+1, GFP_KERNEL);
			if (vol->password == NULL) {
1842
				pr_warn("CIFS: no memory for password\n");
1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854
				goto cifs_parse_mount_err;
			}

			for (i = 0, j = 0; i < temp_len; i++, j++) {
				vol->password[j] = value[i];
				if ((value[i] == delim) &&
				     value[i+1] == delim)
					/* skip the second deliminator */
					i++;
			}
			vol->password[j] = '\0';
			break;
1855
		case Opt_blank_ip:
1856 1857
			/* FIXME: should this be an error instead? */
			got_ip = false;
1858
			break;
1859 1860 1861 1862 1863
		case Opt_ip:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1864 1865
			if (!cifs_convert_address(dstaddr, string,
					strlen(string))) {
1866
				pr_err("CIFS: bad ip= option (%s).\n", string);
1867 1868
				goto cifs_parse_mount_err;
			}
1869
			got_ip = true;
1870 1871 1872 1873 1874 1875
			break;
		case Opt_domain:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1876 1877
			if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
					== CIFS_MAX_DOMAINNAME_LEN) {
1878
				pr_warn("CIFS: domain name too long\n");
1879 1880 1881
				goto cifs_parse_mount_err;
			}

1882
			kfree(vol->domainname);
1883 1884
			vol->domainname = kstrdup(string, GFP_KERNEL);
			if (!vol->domainname) {
1885
				pr_warn("CIFS: no memory for domainname\n");
1886 1887
				goto cifs_parse_mount_err;
			}
1888
			cifs_dbg(FYI, "Domain name set\n");
1889 1890 1891 1892 1893 1894
			break;
		case Opt_srcaddr:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1895
			if (!cifs_convert_address(
1896 1897
					(struct sockaddr *)&vol->srcaddr,
					string, strlen(string))) {
1898 1899
				pr_warn("CIFS: Could not parse srcaddr: %s\n",
					string);
1900 1901 1902 1903 1904 1905 1906 1907
				goto cifs_parse_mount_err;
			}
			break;
		case Opt_iocharset:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1908
			if (strnlen(string, 1024) >= 65) {
1909
				pr_warn("CIFS: iocharset name too long.\n");
1910 1911 1912
				goto cifs_parse_mount_err;
			}

1913
			 if (strncasecmp(string, "default", 7) != 0) {
1914
				kfree(vol->iocharset);
1915 1916 1917
				vol->iocharset = kstrdup(string,
							 GFP_KERNEL);
				if (!vol->iocharset) {
1918
					pr_warn("CIFS: no memory for charset\n");
1919 1920 1921 1922 1923 1924
					goto cifs_parse_mount_err;
				}
			}
			/* if iocharset not set then load_nls_default
			 * is used by caller
			 */
1925
			 cifs_dbg(FYI, "iocharset set to %s\n", string);
1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948
			break;
		case Opt_netbiosname:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

			memset(vol->source_rfc1001_name, 0x20,
				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;
				vol->source_rfc1001_name[i] = string[i];
			}
			/* The string has 16th byte zero still from
			 * set at top of the function
			 */
			if (i == RFC1001_NAME_LEN && string[i] != 0)
1949
				pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974
			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 */
			memset(vol->target_rfc1001_name, 0x20,
				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;
				vol->target_rfc1001_name[i] = string[i];
			}
			/* The string has 16th byte zero still from
			   set at top of the function  */
			if (i == RFC1001_NAME_LEN && string[i] != 0)
1975
				pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
1976 1977
			break;
		case Opt_ver:
1978
			/* version of mount userspace tools, not dialect */
1979 1980 1981 1982
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

1983
			/* If interface changes in mount.cifs bump to new ver */
1984
			if (strncasecmp(string, "1", 1) == 0) {
1985 1986 1987 1988 1989 1990 1991
				if (strlen(string) > 1) {
					pr_warn("Bad mount helper ver=%s. Did "
						"you want SMB1 (CIFS) dialect "
						"and mean to type vers=1.0 "
						"instead?\n", string);
					goto cifs_parse_mount_err;
				}
1992 1993 1994 1995
				/* This is the default */
				break;
			}
			/* For all other value, error */
1996
			pr_warn("CIFS: Invalid mount helper version specified\n");
1997
			goto cifs_parse_mount_err;
1998
		case Opt_vers:
1999
			/* protocol version (dialect) */
2000 2001 2002 2003
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

2004
			if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
2005
				goto cifs_parse_mount_err;
2006
			got_version = true;
2007
			break;
2008 2009 2010 2011 2012 2013 2014 2015
		case Opt_sec:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

			if (cifs_parse_security_flavors(string, vol) != 0)
				goto cifs_parse_mount_err;
			break;
2016 2017 2018 2019 2020 2021 2022 2023
		case Opt_cache:
			string = match_strdup(args);
			if (string == NULL)
				goto out_nomem;

			if (cifs_parse_cache_flavor(string, vol) != 0)
				goto cifs_parse_mount_err;
			break;
2024
		default:
2025 2026 2027 2028 2029 2030
			/*
			 * An option we don't recognize. Save it off for later
			 * if we haven't already found one
			 */
			if (!invalid)
				invalid = data;
2031
			break;
L
Linus Torvalds 已提交
2032
		}
2033 2034 2035
		/* Free up any allocated string */
		kfree(string);
		string = NULL;
L
Linus Torvalds 已提交
2036
	}
J
Jeff Layton 已提交
2037

2038
	if (!sloppy && invalid) {
2039
		pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
2040 2041 2042
		goto cifs_parse_mount_err;
	}

L
Long Li 已提交
2043 2044 2045 2046 2047
	if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
		cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
		goto cifs_parse_mount_err;
	}

2048 2049 2050
#ifndef CONFIG_KEYS
	/* Muliuser mounts require CONFIG_KEYS support */
	if (vol->multiuser) {
2051
		cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
2052
		goto cifs_parse_mount_err;
J
Jeff Layton 已提交
2053
	}
2054
#endif
2055
	if (!vol->UNC) {
2056
		cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
2057 2058
		goto cifs_parse_mount_err;
	}
J
Jeff Layton 已提交
2059

2060 2061
	/* make sure UNC has a share name */
	if (!strchr(vol->UNC + 3, '\\')) {
2062
		cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
2063 2064 2065
		goto cifs_parse_mount_err;
	}

2066
	if (!got_ip) {
2067 2068 2069
		int len;
		const char *slash;

2070
		/* No ip= option specified? Try to get it from UNC */
2071 2072 2073 2074
		/* Use the address part of the UNC. */
		slash = strchr(&vol->UNC[2], '\\');
		len = slash - &vol->UNC[2];
		if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
2075
			pr_err("Unable to determine destination address.\n");
2076 2077 2078 2079 2080 2081
			goto cifs_parse_mount_err;
		}
	}

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

2083 2084 2085
	if (uid_specified)
		vol->override_uid = override_uid;
	else if (override_uid == 1)
2086
		pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
2087 2088 2089 2090

	if (gid_specified)
		vol->override_gid = override_gid;
	else if (override_gid == 1)
2091
		pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
2092

2093 2094
	if (got_version == false)
		pr_warn("No dialect specified on mount. Default has changed to "
2095
			"a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
2096
			"(SMB1). To use the less secure SMB1 dialect to access "
2097 2098
			"old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
			" on mount.\n");
2099

2100
	kfree(mountdata_copy);
L
Linus Torvalds 已提交
2101
	return 0;
2102

2103
out_nomem:
2104
	pr_warn("Could not allocate temporary buffer\n");
2105
cifs_parse_mount_err:
2106
	kfree(string);
2107 2108
	kfree(mountdata_copy);
	return 1;
L
Linus Torvalds 已提交
2109 2110
}

2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127
/** 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.
 */
static bool
srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
{
	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;
2128
		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
2129 2130 2131 2132 2133 2134 2135 2136
		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
	}
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
}

2137 2138 2139 2140 2141 2142 2143 2144
/*
 * 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)
{
2145
	__be16 port, *sport;
2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170

	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;
}
2171

2172
static bool
2173 2174
match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
	      struct sockaddr *srcaddr)
2175 2176
{
	switch (addr->sa_family) {
2177 2178 2179 2180 2181 2182
	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)
2183 2184
			return false;
		break;
2185 2186 2187 2188 2189 2190
	}
	case AF_INET6: {
		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
		struct sockaddr_in6 *srv_addr6 =
					(struct sockaddr_in6 *)&server->dstaddr;

2191
		if (!ipv6_addr_equal(&addr6->sin6_addr,
2192
				     &srv_addr6->sin6_addr))
2193
			return false;
2194
		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
2195 2196 2197
			return false;
		break;
	}
2198 2199 2200 2201
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
2202

2203 2204 2205
	if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
		return false;

2206 2207 2208
	return true;
}

2209 2210 2211
static bool
match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
{
2212 2213 2214 2215 2216
	/*
	 * The select_sectype function should either return the vol->sectype
	 * that was specified, or "Unspecified" if that sectype was not
	 * compatible with the given NEGOTIATE request.
	 */
S
Sachin Prabhu 已提交
2217 2218
	if (server->ops->select_sectype(server, vol->sectype)
	     == Unspecified)
2219 2220
		return false;

2221 2222 2223 2224 2225
	/*
	 * 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.
	 */
2226 2227
	if (vol->sign && !server->sign)
		return false;
2228 2229 2230 2231

	return true;
}

2232
static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
2233
{
2234 2235
	struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;

2236 2237 2238
	if (vol->nosharesock)
		return 0;

2239
	/* BB update this for smb3any and default case */
2240 2241 2242
	if ((server->vals != vol->vals) || (server->ops != vol->ops))
		return 0;

2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255
	if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
		return 0;

	if (!match_address(server, addr,
			   (struct sockaddr *)&vol->srcaddr))
		return 0;

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

	if (!match_security(server, vol))
		return 0;

R
Rabin Vincent 已提交
2256
	if (server->echo_interval != vol->echo_interval * HZ)
S
Steve French 已提交
2257 2258
		return 0;

L
Long Li 已提交
2259 2260 2261
	if (server->rdma != vol->rdma)
		return 0;

2262 2263 2264
	return 1;
}

2265
static struct TCP_Server_Info *
2266
cifs_find_tcp_session(struct smb_vol *vol)
L
Linus Torvalds 已提交
2267
{
2268 2269
	struct TCP_Server_Info *server;

2270
	spin_lock(&cifs_tcp_ses_lock);
2271
	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
2272
		if (!match_server(server, vol))
2273 2274
			continue;

2275
		++server->srv_count;
2276
		spin_unlock(&cifs_tcp_ses_lock);
2277
		cifs_dbg(FYI, "Existing tcp session with server found\n");
2278
		return server;
L
Linus Torvalds 已提交
2279
	}
2280
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
2281 2282
	return NULL;
}
2283

2284 2285
void
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
L
Linus Torvalds 已提交
2286
{
2287 2288
	struct task_struct *task;

2289
	spin_lock(&cifs_tcp_ses_lock);
2290
	if (--server->srv_count > 0) {
2291
		spin_unlock(&cifs_tcp_ses_lock);
2292
		return;
L
Linus Torvalds 已提交
2293
	}
2294

2295 2296
	put_net(cifs_net_ns(server));

2297
	list_del_init(&server->tcp_ses_list);
2298
	spin_unlock(&cifs_tcp_ses_lock);
2299

2300 2301
	cancel_delayed_work_sync(&server->echo);

2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312
	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);

2313 2314 2315
	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
2316

2317
	cifs_crypto_secmech_release(server);
2318 2319
	cifs_fscache_release_client_cookie(server);

2320 2321 2322
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
2323 2324 2325 2326

	task = xchg(&server->tsk, NULL);
	if (task)
		force_sig(SIGKILL, task);
L
Linus Torvalds 已提交
2327 2328
}

2329 2330 2331 2332 2333 2334
static struct TCP_Server_Info *
cifs_get_tcp_session(struct smb_vol *volume_info)
{
	struct TCP_Server_Info *tcp_ses = NULL;
	int rc;

2335
	cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
2336 2337

	/* see if we already have a matching tcp_ses */
2338
	tcp_ses = cifs_find_tcp_session(volume_info);
2339 2340 2341 2342 2343 2344 2345 2346 2347
	if (tcp_ses)
		return tcp_ses;

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

2348 2349
	tcp_ses->ops = volume_info->ops;
	tcp_ses->vals = volume_info->vals;
2350
	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
2351 2352 2353
	tcp_ses->hostname = extract_hostname(volume_info->UNC);
	if (IS_ERR(tcp_ses->hostname)) {
		rc = PTR_ERR(tcp_ses->hostname);
2354
		goto out_err_crypto_release;
2355 2356 2357 2358
	}

	tcp_ses->noblocksnd = volume_info->noblocksnd;
	tcp_ses->noautotune = volume_info->noautotune;
2359
	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
L
Long Li 已提交
2360
	tcp_ses->rdma = volume_info->rdma;
P
Pavel Shilovsky 已提交
2361
	tcp_ses->in_flight = 0;
2362
	tcp_ses->credits = 1;
2363 2364 2365 2366 2367 2368 2369 2370
	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,
		volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
	memcpy(tcp_ses->server_RFC1001_name,
		volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2371
	tcp_ses->session_estab = false;
2372
	tcp_ses->sequence_number = 0;
2373
	tcp_ses->lstrp = jiffies;
2374
	spin_lock_init(&tcp_ses->req_lock);
2375 2376
	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
2377
	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
2378 2379
	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
	mutex_init(&tcp_ses->reconnect_mutex);
2380 2381 2382 2383
	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
	       sizeof(tcp_ses->srcaddr));
	memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
		sizeof(tcp_ses->dstaddr));
2384
	generate_random_uuid(tcp_ses->client_guid);
2385 2386 2387 2388 2389 2390 2391 2392
	/*
	 * 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;

S
Steve French 已提交
2393 2394 2395 2396 2397
	if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
		volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
		tcp_ses->echo_interval = volume_info->echo_interval * HZ;
	else
		tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414
	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(
			tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
		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;
		}
	}
2415
	rc = ip_connect(tcp_ses);
2416
	if (rc < 0) {
2417
		cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
2418
		goto out_err_crypto_release;
2419
	}
2420
smbd_connected:
2421 2422 2423 2424 2425
	/*
	 * since we're in a cifs function already, we know that
	 * this will succeed. No need for try_module_get().
	 */
	__module_get(THIS_MODULE);
2426
	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
2427 2428 2429
				  tcp_ses, "cifsd");
	if (IS_ERR(tcp_ses->tsk)) {
		rc = PTR_ERR(tcp_ses->tsk);
2430
		cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
2431
		module_put(THIS_MODULE);
2432
		goto out_err_crypto_release;
2433
	}
2434
	tcp_ses->tcpStatus = CifsNeedNegotiate;
2435 2436

	/* thread spawned, put it on the list */
2437
	spin_lock(&cifs_tcp_ses_lock);
2438
	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
2439
	spin_unlock(&cifs_tcp_ses_lock);
2440

2441 2442
	cifs_fscache_get_client_cookie(tcp_ses);

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

2446 2447
	return tcp_ses;

2448
out_err_crypto_release:
2449
	cifs_crypto_secmech_release(tcp_ses);
2450

2451 2452
	put_net(cifs_net_ns(tcp_ses));

2453 2454
out_err:
	if (tcp_ses) {
2455 2456
		if (!IS_ERR(tcp_ses->hostname))
			kfree(tcp_ses->hostname);
2457 2458 2459 2460 2461 2462 2463
		if (tcp_ses->ssocket)
			sock_release(tcp_ses->ssocket);
		kfree(tcp_ses);
	}
	return ERR_PTR(rc);
}

2464
static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
2465
{
2466 2467 2468 2469 2470
	if (vol->sectype != Unspecified &&
	    vol->sectype != ses->sectype)
		return 0;

	switch (ses->sectype) {
2471
	case Kerberos:
2472
		if (!uid_eq(vol->cred_uid, ses->cred_uid))
2473 2474 2475
			return 0;
		break;
	default:
J
Jeff Layton 已提交
2476 2477 2478 2479 2480 2481 2482
		/* NULL username means anonymous session */
		if (ses->user_name == NULL) {
			if (!vol->nullauth)
				return 0;
			break;
		}

2483
		/* anything else takes username/password */
J
Jeff Layton 已提交
2484 2485
		if (strncmp(ses->user_name,
			    vol->username ? vol->username : "",
2486
			    CIFS_MAX_USERNAME_LEN))
2487
			return 0;
2488
		if ((vol->username && strlen(vol->username) != 0) &&
2489 2490 2491
		    ses->password != NULL &&
		    strncmp(ses->password,
			    vol->password ? vol->password : "",
2492
			    CIFS_MAX_PASSWORD_LEN))
2493 2494 2495 2496 2497
			return 0;
	}
	return 1;
}

A
Aurelien Aptel 已提交
2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584
/**
 * 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
cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
{
	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;

	/*
	 * If the mount request that resulted in the creation of the
	 * session requires encryption, force IPC to be encrypted too.
	 */
	if (volume_info->seal) {
		if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
			seal = true;
		else {
			cifs_dbg(VFS,
				 "IPC: server doesn't support encryption\n");
			return -EOPNOTSUPP;
		}
	}

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

	snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->serverName);

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

	xid = get_xid();
	tcon->ses = ses;
	tcon->ipc = true;
	tcon->seal = seal;
	rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
	free_xid(xid);

	if (rc) {
		cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
		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;
}

2585
static struct cifs_ses *
2586
cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
L
Linus Torvalds 已提交
2587
{
2588
	struct cifs_ses *ses;
2589

2590
	spin_lock(&cifs_tcp_ses_lock);
2591
	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
2592 2593
		if (ses->status == CifsExiting)
			continue;
2594 2595
		if (!match_session(ses, vol))
			continue;
2596
		++ses->ses_count;
2597
		spin_unlock(&cifs_tcp_ses_lock);
2598 2599
		return ses;
	}
2600
	spin_unlock(&cifs_tcp_ses_lock);
2601 2602
	return NULL;
}
2603

2604
static void
2605
cifs_put_smb_ses(struct cifs_ses *ses)
2606
{
2607
	unsigned int rc, xid;
2608
	struct TCP_Server_Info *server = ses->server;
2609

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

2612
	spin_lock(&cifs_tcp_ses_lock);
2613 2614 2615 2616
	if (ses->status == CifsExiting) {
		spin_unlock(&cifs_tcp_ses_lock);
		return;
	}
2617
	if (--ses->ses_count > 0) {
2618
		spin_unlock(&cifs_tcp_ses_lock);
2619 2620
		return;
	}
2621 2622
	if (ses->status == CifsGood)
		ses->status = CifsExiting;
2623
	spin_unlock(&cifs_tcp_ses_lock);
2624

A
Aurelien Aptel 已提交
2625 2626
	cifs_free_ipc(ses);

2627
	if (ses->status == CifsExiting && server->ops->logoff) {
2628
		xid = get_xid();
2629 2630 2631 2632
		rc = server->ops->logoff(xid, ses);
		if (rc)
			cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
				__func__, rc);
2633
		_free_xid(xid);
2634
	}
2635 2636 2637 2638 2639

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

2640
	sesInfoFree(ses);
2641
	cifs_put_tcp_session(server, 0);
2642
}
2643

2644 2645
#ifdef CONFIG_KEYS

2646 2647
/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
2648 2649 2650 2651 2652 2653

/* Populate username and pw fields from keyring if possible */
static int
cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
{
	int rc = 0;
2654 2655
	const char *delim, *payload;
	char *desc;
2656 2657 2658 2659 2660
	ssize_t len;
	struct key *key;
	struct TCP_Server_Info *server = ses->server;
	struct sockaddr_in *sa;
	struct sockaddr_in6 *sa6;
2661
	const struct user_key_payload *upayload;
2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677

	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:
2678 2679
		cifs_dbg(FYI, "Bad ss_family (%hu)\n",
			 server->dstaddr.ss_family);
2680 2681 2682 2683
		rc = -EINVAL;
		goto out_err;
	}

2684
	cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
2685 2686 2687
	key = request_key(&key_type_logon, desc, "");
	if (IS_ERR(key)) {
		if (!ses->domainName) {
2688
			cifs_dbg(FYI, "domainName is NULL\n");
2689 2690 2691 2692 2693 2694
			rc = PTR_ERR(key);
			goto out_err;
		}

		/* didn't work, try to find a domain key */
		sprintf(desc, "cifs:d:%s", ses->domainName);
2695
		cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
2696 2697 2698 2699 2700 2701 2702 2703
		key = request_key(&key_type_logon, desc, "");
		if (IS_ERR(key)) {
			rc = PTR_ERR(key);
			goto out_err;
		}
	}

	down_read(&key->sem);
2704
	upayload = user_key_payload_locked(key);
2705
	if (IS_ERR_OR_NULL(upayload)) {
2706
		rc = upayload ? PTR_ERR(upayload) : -EINVAL;
2707 2708 2709 2710
		goto out_key_put;
	}

	/* find first : in payload */
2711
	payload = upayload->data;
2712
	delim = strnchr(payload, upayload->datalen, ':');
2713
	cifs_dbg(FYI, "payload=%s\n", payload);
2714
	if (!delim) {
2715 2716
		cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
			 upayload->datalen);
2717 2718 2719 2720 2721
		rc = -EINVAL;
		goto out_key_put;
	}

	len = delim - payload;
2722
	if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
2723 2724
		cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
			 len);
2725 2726 2727 2728 2729 2730
		rc = -EINVAL;
		goto out_key_put;
	}

	vol->username = kstrndup(payload, len, GFP_KERNEL);
	if (!vol->username) {
2731 2732
		cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
			 len);
2733 2734 2735
		rc = -ENOMEM;
		goto out_key_put;
	}
2736
	cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
2737 2738

	len = key->datalen - (len + 1);
2739
	if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
2740
		cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
2741 2742 2743 2744 2745 2746 2747 2748 2749
		rc = -EINVAL;
		kfree(vol->username);
		vol->username = NULL;
		goto out_key_put;
	}

	++delim;
	vol->password = kstrndup(delim, len, GFP_KERNEL);
	if (!vol->password) {
2750 2751
		cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
			 len);
2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762
		rc = -ENOMEM;
		kfree(vol->username);
		vol->username = NULL;
		goto out_key_put;
	}

out_key_put:
	up_read(&key->sem);
	key_put(key);
out_err:
	kfree(desc);
2763
	cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774
	return rc;
}
#else /* ! CONFIG_KEYS */
static inline int
cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
		   struct cifs_ses *ses __attribute__((unused)))
{
	return -ENOSYS;
}
#endif /* CONFIG_KEYS */

2775 2776 2777 2778 2779 2780 2781
/**
 * cifs_get_smb_ses - get a session matching @volume_info data from @server
 *
 * 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.
 */
2782
static struct cifs_ses *
2783 2784
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
{
2785 2786
	int rc = -ENOMEM;
	unsigned int xid;
2787
	struct cifs_ses *ses;
2788 2789
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
2790

2791
	xid = get_xid();
2792

2793
	ses = cifs_find_smb_ses(server, volume_info);
2794
	if (ses) {
2795 2796
		cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
			 ses->status);
2797 2798

		mutex_lock(&ses->session_mutex);
2799 2800 2801 2802 2803
		rc = cifs_negotiate_protocol(xid, ses);
		if (rc) {
			mutex_unlock(&ses->session_mutex);
			/* problem -- put our ses reference */
			cifs_put_smb_ses(ses);
2804
			free_xid(xid);
2805 2806
			return ERR_PTR(rc);
		}
2807
		if (ses->need_reconnect) {
2808
			cifs_dbg(FYI, "Session needs reconnect\n");
2809 2810 2811 2812 2813 2814
			rc = cifs_setup_session(xid, ses,
						volume_info->local_nls);
			if (rc) {
				mutex_unlock(&ses->session_mutex);
				/* problem -- put our reference */
				cifs_put_smb_ses(ses);
2815
				free_xid(xid);
2816 2817 2818 2819
				return ERR_PTR(rc);
			}
		}
		mutex_unlock(&ses->session_mutex);
2820 2821

		/* existing SMB ses has a server reference already */
2822
		cifs_put_tcp_session(server, 0);
2823
		free_xid(xid);
2824 2825 2826
		return ses;
	}

2827
	cifs_dbg(FYI, "Existing smb sess not found\n");
2828 2829 2830 2831 2832 2833
	ses = sesInfoAlloc();
	if (ses == NULL)
		goto get_ses_fail;

	/* new SMB session uses our server ref */
	ses->server = server;
2834 2835
	if (server->dstaddr.ss_family == AF_INET6)
		sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
2836
	else
2837
		sprintf(ses->serverName, "%pI4", &addr->sin_addr);
2838

2839 2840 2841 2842 2843
	if (volume_info->username) {
		ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
		if (!ses->user_name)
			goto get_ses_fail;
	}
2844 2845 2846 2847 2848 2849 2850 2851

	/* volume_info->password freed at unmount */
	if (volume_info->password) {
		ses->password = kstrdup(volume_info->password, GFP_KERNEL);
		if (!ses->password)
			goto get_ses_fail;
	}
	if (volume_info->domainname) {
2852 2853 2854
		ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
		if (!ses->domainName)
			goto get_ses_fail;
2855
	}
2856 2857
	if (volume_info->domainauto)
		ses->domainAuto = volume_info->domainauto;
2858
	ses->cred_uid = volume_info->cred_uid;
2859
	ses->linux_uid = volume_info->linux_uid;
2860

2861 2862
	ses->sectype = volume_info->sectype;
	ses->sign = volume_info->sign;
2863 2864

	mutex_lock(&ses->session_mutex);
2865 2866 2867
	rc = cifs_negotiate_protocol(xid, ses);
	if (!rc)
		rc = cifs_setup_session(xid, ses, volume_info->local_nls);
2868
	mutex_unlock(&ses->session_mutex);
2869
	if (rc)
2870 2871 2872
		goto get_ses_fail;

	/* success, put it on the list */
2873
	spin_lock(&cifs_tcp_ses_lock);
2874
	list_add(&ses->smb_ses_list, &server->smb_ses_list);
2875
	spin_unlock(&cifs_tcp_ses_lock);
2876

2877
	free_xid(xid);
A
Aurelien Aptel 已提交
2878 2879 2880

	cifs_setup_ipc(ses, volume_info);

2881 2882 2883 2884
	return ses;

get_ses_fail:
	sesInfoFree(ses);
2885
	free_xid(xid);
2886 2887 2888
	return ERR_PTR(rc);
}

2889
static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
2890 2891 2892
{
	if (tcon->tidStatus == CifsExiting)
		return 0;
2893
	if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
2894
		return 0;
2895 2896 2897 2898
	if (tcon->seal != volume_info->seal)
		return 0;
	if (tcon->snapshot_time != volume_info->snapshot_time)
		return 0;
2899 2900 2901
	return 1;
}

2902
static struct cifs_tcon *
2903
cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
2904 2905
{
	struct list_head *tmp;
2906
	struct cifs_tcon *tcon;
2907

2908
	spin_lock(&cifs_tcp_ses_lock);
2909
	list_for_each(tmp, &ses->tcon_list) {
2910
		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
2911
		if (!match_tcon(tcon, volume_info))
2912 2913
			continue;
		++tcon->tc_count;
2914
		spin_unlock(&cifs_tcp_ses_lock);
2915
		return tcon;
L
Linus Torvalds 已提交
2916
	}
2917
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
2918 2919 2920
	return NULL;
}

2921
void
2922
cifs_put_tcon(struct cifs_tcon *tcon)
2923
{
2924
	unsigned int xid;
A
Aurelien Aptel 已提交
2925
	struct cifs_ses *ses;
2926

A
Aurelien Aptel 已提交
2927 2928 2929 2930 2931 2932 2933 2934
	/*
	 * 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;
2935
	cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
2936
	spin_lock(&cifs_tcp_ses_lock);
2937
	if (--tcon->tc_count > 0) {
2938
		spin_unlock(&cifs_tcp_ses_lock);
2939 2940 2941 2942
		return;
	}

	list_del_init(&tcon->tcon_list);
2943
	spin_unlock(&cifs_tcp_ses_lock);
2944

2945
	xid = get_xid();
2946 2947
	if (ses->server->ops->tree_disconnect)
		ses->server->ops->tree_disconnect(xid, tcon);
2948
	_free_xid(xid);
2949

2950
	cifs_fscache_release_super_cookie(tcon);
2951
	tconInfoFree(tcon);
2952 2953 2954
	cifs_put_smb_ses(ses);
}

2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974
/**
 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
 *
 * - 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.
 */
2975 2976
static struct cifs_tcon *
cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
2977 2978
{
	int rc, xid;
2979
	struct cifs_tcon *tcon;
2980

2981
	tcon = cifs_find_tcon(ses, volume_info);
2982
	if (tcon) {
2983 2984 2985 2986
		/*
		 * tcon has refcount already incremented but we need to
		 * decrement extra ses reference gotten by caller (case b)
		 */
2987
		cifs_dbg(FYI, "Found match on UNC path\n");
2988 2989 2990 2991
		cifs_put_smb_ses(ses);
		return tcon;
	}

2992 2993 2994 2995 2996
	if (!ses->server->ops->tree_connect) {
		rc = -ENOSYS;
		goto out_fail;
	}

2997 2998 2999 3000 3001 3002
	tcon = tconInfoAlloc();
	if (tcon == NULL) {
		rc = -ENOMEM;
		goto out_fail;
	}

3003 3004 3005 3006 3007 3008 3009 3010 3011 3012
	if (volume_info->snapshot_time) {
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "Use SMB2 or later for snapshot mount option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
			tcon->snapshot_time = volume_info->snapshot_time;
	}

3013 3014 3015 3016 3017 3018 3019 3020 3021
	tcon->ses = ses;
	if (volume_info->password) {
		tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
		if (!tcon->password) {
			rc = -ENOMEM;
			goto out_fail;
		}
	}

3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037
	if (volume_info->seal) {
		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;
		}
	}

3038 3039
	if (volume_info->linux_ext) {
		if (ses->server->posix_ext_supported) {
3040
			tcon->posix_extensions = true;
3041 3042
			printk_once(KERN_WARNING
				"SMB3.11 POSIX Extensions are experimental\n");
3043 3044 3045 3046
		} else {
			cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
3047
		}
3048 3049
	}

3050 3051 3052 3053
	/*
	 * BB Do we need to wrap session_mutex around this TCon call and Unix
	 * SetFS as we do on SessSetup and reconnect?
	 */
3054
	xid = get_xid();
3055 3056
	rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
					    volume_info->local_nls);
3057
	free_xid(xid);
3058
	cifs_dbg(FYI, "Tcon rc = %d\n", rc);
3059 3060 3061 3062 3063
	if (rc)
		goto out_fail;

	if (volume_info->nodfs) {
		tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
3064
		cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
3065
	}
3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087
	tcon->use_persistent = false;
	/* check if SMB2 or later, CIFS does not support persistent handles */
	if (volume_info->persistent) {
		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)
	     && (volume_info->nopersistent == false)) {
		cifs_dbg(FYI, "enabling persistent handles\n");
		tcon->use_persistent = true;
S
Steve French 已提交
3088 3089 3090 3091 3092 3093 3094 3095
	} else if (volume_info->resilient) {
		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;
3096 3097
	}

3098 3099 3100 3101 3102
	/*
	 * 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.
	 */
3103 3104
	tcon->retry = volume_info->retry;
	tcon->nocase = volume_info->nocase;
S
Steve French 已提交
3105
	tcon->nohandlecache = volume_info->nohandlecache;
3106
	tcon->local_lease = volume_info->local_lease;
3107
	INIT_LIST_HEAD(&tcon->pending_opens);
3108

3109
	spin_lock(&cifs_tcp_ses_lock);
3110
	list_add(&tcon->tcon_list, &ses->tcon_list);
3111
	spin_unlock(&cifs_tcp_ses_lock);
3112

3113 3114
	cifs_fscache_get_super_cookie(tcon);

3115 3116 3117 3118 3119 3120 3121
	return tcon;

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

3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138
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;
}
3139

3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153
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;

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

	if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
	    (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
		return 0;

	/*
3154 3155
	 * 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.
3156 3157 3158 3159
	 */
	if (new->wsize && new->wsize < old->wsize)
		return 0;

3160 3161 3162
	if (new->rsize && new->rsize < old->rsize)
		return 0;

3163
	if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178
		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;
}

3179 3180 3181 3182 3183
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;
S
Sachin Prabhu 已提交
3184 3185
	bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
	bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3186

S
Sachin Prabhu 已提交
3187
	if (old_set && new_set && !strcmp(new->prepath, old->prepath))
3188
		return 1;
S
Sachin Prabhu 已提交
3189 3190 3191
	else if (!old_set && !new_set)
		return 1;

3192 3193 3194
	return 0;
}

3195 3196 3197 3198 3199 3200 3201
int
cifs_match_super(struct super_block *sb, void *data)
{
	struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
	struct smb_vol *volume_info;
	struct cifs_sb_info *cifs_sb;
	struct TCP_Server_Info *tcp_srv;
3202 3203
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219
	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;

	volume_info = mnt_data->vol;

3220
	if (!match_server(tcp_srv, volume_info) ||
3221
	    !match_session(ses, volume_info) ||
3222
	    !match_tcon(tcon, volume_info) ||
3223
	    !match_prepath(sb, mnt_data)) {
3224 3225 3226 3227 3228 3229 3230
		rc = 0;
		goto out;
	}

	rc = compare_mount_options(sb, mnt_data);
out:
	spin_unlock(&cifs_tcp_ses_lock);
3231
	cifs_put_tlink(tlink);
3232 3233 3234
	return rc;
}

L
Linus Torvalds 已提交
3235
int
3236
get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
3237 3238
	     const struct nls_table *nls_codepage, unsigned int *num_referrals,
	     struct dfs_info3_param **referrals, int remap)
L
Linus Torvalds 已提交
3239 3240 3241
{
	int rc = 0;

A
Aurelien Aptel 已提交
3242
	if (!ses->server->ops->get_dfs_refer)
3243 3244 3245 3246
		return -ENOSYS;

	*num_referrals = 0;
	*referrals = NULL;
L
Linus Torvalds 已提交
3247

A
Aurelien Aptel 已提交
3248 3249 3250
	rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
					     referrals, num_referrals,
					     nls_codepage, remap);
L
Linus Torvalds 已提交
3251 3252 3253
	return rc;
}

3254 3255 3256 3257 3258 3259 3260 3261
#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;
3262
	BUG_ON(!sock_allow_reclassification(sk));
3263 3264 3265 3266 3267 3268 3269 3270
	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;
3271
	BUG_ON(!sock_allow_reclassification(sk));
3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286
	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 已提交
3287
/* See RFC1001 section 14 on representation of Netbios names */
3288
static void rfc1002mangle(char *target, char *source, unsigned int length)
L
Linus Torvalds 已提交
3289
{
3290
	unsigned int i, j;
L
Linus Torvalds 已提交
3291

3292
	for (i = 0, j = 0; i < (length); i++) {
L
Linus Torvalds 已提交
3293 3294 3295
		/* mask a nibble at a time and encode */
		target[j] = 'A' + (0x0F & (source[i] >> 4));
		target[j+1] = 'A' + (0x0F & source[i]);
3296
		j += 2;
L
Linus Torvalds 已提交
3297 3298 3299 3300
	}

}

3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316
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)
3317 3318
				cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
					 &saddr6->sin6_addr, rc);
3319
			else
3320 3321
				cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
					 &saddr4->sin_addr.s_addr, rc);
3322 3323 3324 3325
		}
	}
	return rc;
}
L
Linus Torvalds 已提交
3326 3327

static int
3328
ip_rfc1001_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
3329 3330
{
	int rc = 0;
3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342
	/*
	 * 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;

3343
		if (server->server_RFC1001_name[0] != 0)
3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359
			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.
		 */
3360
		if (server->workstation_RFC1001_name[0] != 0)
3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375
			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 */
3376
		smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402
		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;
3403
	__be16 sport;
3404
	int slen, sfamily;
3405
	struct socket *socket = server->ssocket;
3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418
	struct sockaddr *saddr;

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

	if (server->dstaddr.ss_family == AF_INET6) {
		sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
		slen = sizeof(struct sockaddr_in6);
		sfamily = AF_INET6;
	} else {
		sport = ((struct sockaddr_in *) saddr)->sin_port;
		slen = sizeof(struct sockaddr_in);
		sfamily = AF_INET;
	}
L
Linus Torvalds 已提交
3419

3420
	if (socket == NULL) {
3421 3422
		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
				   IPPROTO_TCP, &socket, 1);
L
Linus Torvalds 已提交
3423
		if (rc < 0) {
3424
			cifs_dbg(VFS, "Error %d creating socket\n", rc);
3425
			server->ssocket = NULL;
L
Linus Torvalds 已提交
3426 3427
			return rc;
		}
3428 3429

		/* BB other socket options to set KEEPALIVE, NODELAY? */
3430
		cifs_dbg(FYI, "Socket created\n");
3431 3432
		server->ssocket = socket;
		socket->sk->sk_allocation = GFP_NOFS;
3433 3434 3435 3436
		if (sfamily == AF_INET6)
			cifs_reclassify_socket6(socket);
		else
			cifs_reclassify_socket4(socket);
L
Linus Torvalds 已提交
3437 3438
	}

3439 3440 3441 3442
	rc = bind_socket(server);
	if (rc < 0)
		return rc;

3443 3444
	/*
	 * Eventually check for other socket options to change from
3445 3446
	 * the default. sock_setsockopt not used because it expects
	 * user space buffer
3447 3448
	 */
	socket->sk->sk_rcvtimeo = 7 * HZ;
3449
	socket->sk->sk_sndtimeo = 5 * HZ;
3450

3451
	/* make the bufsizes depend on wsize/rsize and max requests */
3452 3453 3454 3455 3456
	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;
3457
	}
L
Linus Torvalds 已提交
3458

3459
	if (server->tcp_nodelay) {
3460
		int val = 1;
3461 3462 3463
		rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
				(char *)&val, sizeof(val));
		if (rc)
3464 3465
			cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
				 rc);
3466 3467
	}

3468
	cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
3469
		 socket->sk->sk_sndbuf,
3470
		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3471

3472 3473
	rc = socket->ops->connect(socket, saddr, slen, 0);
	if (rc < 0) {
3474
		cifs_dbg(FYI, "Error %d connecting to server\n", rc);
3475 3476 3477 3478 3479
		sock_release(socket);
		server->ssocket = NULL;
		return rc;
	}

3480 3481
	if (sport == htons(RFC1001_PORT))
		rc = ip_rfc1001_connect(server);
3482

L
Linus Torvalds 已提交
3483 3484 3485 3486
	return rc;
}

static int
3487
ip_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
3488
{
3489
	__be16 *sport;
3490 3491
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
L
Linus Torvalds 已提交
3492

3493 3494 3495 3496
	if (server->dstaddr.ss_family == AF_INET6)
		sport = &addr6->sin6_port;
	else
		sport = &addr->sin_port;
L
Linus Torvalds 已提交
3497

3498 3499
	if (*sport == 0) {
		int rc;
L
Linus Torvalds 已提交
3500

3501 3502
		/* try with 445 port at first */
		*sport = htons(CIFS_PORT);
3503

3504
		rc = generic_ip_connect(server);
L
Linus Torvalds 已提交
3505
		if (rc >= 0)
3506
			return rc;
3507

3508 3509
		/* if it failed, try with 139 port */
		*sport = htons(RFC1001_PORT);
3510 3511
	}

3512
	return generic_ip_connect(server);
L
Linus Torvalds 已提交
3513 3514
}

3515
void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
3516
			  struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527
{
	/* 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);
3528

3529 3530 3531
	if (vol_info && vol_info->no_linux_ext) {
		tcon->fsUnixInfo.Capability = 0;
		tcon->unix_ext = 0; /* Unix Extensions disabled */
3532
		cifs_dbg(FYI, "Linux protocol extensions disabled\n");
3533 3534 3535 3536 3537
		return;
	} else if (vol_info)
		tcon->unix_ext = 1; /* Unix Extensions supported */

	if (tcon->unix_ext == 0) {
3538
		cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
3539 3540
		return;
	}
3541

S
Steve French 已提交
3542
	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
3543
		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
3544
		cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
3545 3546
		/* check for reconnect case in which we do not
		   want to change the mount behavior if we can avoid it */
S
Steve French 已提交
3547
		if (vol_info == NULL) {
3548
			/* turn off POSIX ACL and PATHNAMES if not set
3549 3550 3551
			   originally at mount time */
			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
3552 3553
			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
3554
					cifs_dbg(VFS, "POSIXPATH support change\n");
3555
				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
3556
			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3557 3558
				cifs_dbg(VFS, "possible reconnect error\n");
				cifs_dbg(VFS, "server disabled POSIX path support\n");
3559
			}
3560
		}
3561

3562
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3563
			cifs_dbg(VFS, "per-share encryption not supported yet\n");
3564

3565
		cap &= CIFS_UNIX_CAP_MASK;
3566
		if (vol_info && vol_info->no_psx_acl)
3567
			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
3568
		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
3569
			cifs_dbg(FYI, "negotiated posix acl support\n");
3570 3571 3572
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
					CIFS_MOUNT_POSIXACL;
3573 3574
		}

3575
		if (vol_info && vol_info->posix_paths == 0)
3576
			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
3577
		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3578
			cifs_dbg(FYI, "negotiate posix pathnames\n");
3579 3580
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
3581 3582
					CIFS_MOUNT_POSIX_PATHS;
		}
3583

3584
		cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
3585
#ifdef CONFIG_CIFS_DEBUG2
3586
		if (cap & CIFS_UNIX_FCNTL_CAP)
3587
			cifs_dbg(FYI, "FCNTL cap\n");
3588
		if (cap & CIFS_UNIX_EXTATTR_CAP)
3589
			cifs_dbg(FYI, "EXTATTR cap\n");
3590
		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
3591
			cifs_dbg(FYI, "POSIX path cap\n");
3592
		if (cap & CIFS_UNIX_XATTR_CAP)
3593
			cifs_dbg(FYI, "XATTR cap\n");
3594
		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
3595
			cifs_dbg(FYI, "POSIX ACL cap\n");
3596
		if (cap & CIFS_UNIX_LARGE_READ_CAP)
3597
			cifs_dbg(FYI, "very large read cap\n");
3598
		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
3599
			cifs_dbg(FYI, "very large write cap\n");
3600
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
3601
			cifs_dbg(FYI, "transport encryption cap\n");
3602
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
3603
			cifs_dbg(FYI, "mandatory transport encryption cap\n");
3604 3605
#endif /* CIFS_DEBUG2 */
		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
3606
			if (vol_info == NULL) {
3607
				cifs_dbg(FYI, "resetting capabilities failed\n");
3608
			} else
3609
				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");
3610

3611 3612 3613 3614
		}
	}
}

3615
int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3616
			struct cifs_sb_info *cifs_sb)
3617
{
3618 3619
	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);

3620 3621 3622
	spin_lock_init(&cifs_sb->tlink_tree_lock);
	cifs_sb->tlink_tree = RB_ROOT;

3623
	/*
3624 3625
	 * Temporarily set r/wsize for matching superblock. If we end up using
	 * new sb then client will later negotiate it downward if needed.
3626
	 */
3627
	cifs_sb->rsize = pvolume_info->rsize;
3628 3629
	cifs_sb->wsize = pvolume_info->wsize;

S
Steve French 已提交
3630 3631 3632 3633
	cifs_sb->mnt_uid = pvolume_info->linux_uid;
	cifs_sb->mnt_gid = pvolume_info->linux_gid;
	cifs_sb->mnt_file_mode = pvolume_info->file_mode;
	cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
3634 3635
	cifs_dbg(FYI, "file mode: 0x%hx  dir mode: 0x%hx\n",
		 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
S
Steve French 已提交
3636

3637
	cifs_sb->actimeo = pvolume_info->actimeo;
3638
	cifs_sb->local_nls = pvolume_info->local_nls;
3639

S
Steve French 已提交
3640 3641 3642 3643
	if (pvolume_info->noperm)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
	if (pvolume_info->setuids)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
3644 3645
	if (pvolume_info->setuidfromacl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
S
Steve French 已提交
3646 3647 3648
	if (pvolume_info->server_ino)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
	if (pvolume_info->remap)
3649 3650
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
	if (pvolume_info->sfu_remap)
S
Steve French 已提交
3651 3652 3653 3654 3655 3656 3657
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
	if (pvolume_info->no_xattr)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
	if (pvolume_info->sfu_emul)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
	if (pvolume_info->nobrl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
S
Steve French 已提交
3658 3659
	if (pvolume_info->nohandlecache)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
3660
	if (pvolume_info->nostrictsync)
S
Steve French 已提交
3661
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
3662 3663
	if (pvolume_info->mand_lock)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
3664 3665
	if (pvolume_info->rwpidforward)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
S
Steve French 已提交
3666 3667
	if (pvolume_info->cifs_acl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
3668
	if (pvolume_info->backupuid_specified) {
3669
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
3670 3671 3672
		cifs_sb->mnt_backupuid = pvolume_info->backupuid;
	}
	if (pvolume_info->backupgid_specified) {
3673
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
3674 3675
		cifs_sb->mnt_backupgid = pvolume_info->backupgid;
	}
S
Steve French 已提交
3676 3677 3678 3679 3680 3681
	if (pvolume_info->override_uid)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
	if (pvolume_info->override_gid)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
	if (pvolume_info->dynperm)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
3682 3683
	if (pvolume_info->fsc)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
J
Jeff Layton 已提交
3684 3685 3686
	if (pvolume_info->multiuser)
		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
					    CIFS_MOUNT_NO_PERM);
3687 3688
	if (pvolume_info->strict_io)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
S
Steve French 已提交
3689
	if (pvolume_info->direct_io) {
3690
		cifs_dbg(FYI, "mounting share using direct i/o\n");
S
Steve French 已提交
3691 3692
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
	}
3693 3694
	if (pvolume_info->mfsymlinks) {
		if (pvolume_info->sfu_emul) {
3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706
			/*
			 * 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");
3707
		}
3708
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3709
	}
S
Steve French 已提交
3710 3711

	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
3712
		cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
3713 3714 3715 3716 3717 3718 3719 3720

	if (pvolume_info->prepath) {
		cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
		if (cifs_sb->prepath == NULL)
			return -ENOMEM;
	}

	return 0;
3721 3722
}

J
Jeff Layton 已提交
3723 3724
static void
cleanup_volume_info_contents(struct smb_vol *volume_info)
I
Igor Mammedov 已提交
3725
{
3726
	kfree(volume_info->username);
I
Igor Mammedov 已提交
3727
	kzfree(volume_info->password);
3728
	kfree(volume_info->UNC);
3729 3730
	kfree(volume_info->domainname);
	kfree(volume_info->iocharset);
I
Igor Mammedov 已提交
3731
	kfree(volume_info->prepath);
J
Jeff Layton 已提交
3732 3733 3734 3735 3736 3737 3738 3739
}

void
cifs_cleanup_volume_info(struct smb_vol *volume_info)
{
	if (!volume_info)
		return;
	cleanup_volume_info_contents(volume_info);
I
Igor Mammedov 已提交
3740 3741 3742
	kfree(volume_info);
}

J
Jeff Layton 已提交
3743

S
Steve French 已提交
3744
#ifdef CONFIG_CIFS_DFS_UPCALL
3745 3746 3747 3748
/*
 * cifs_build_path_to_root returns full path to root when we do not have an
 * exiting connection (tcon)
 */
I
Igor Mammedov 已提交
3749
static char *
3750
build_unc_path_to_root(const struct smb_vol *vol,
I
Igor Mammedov 已提交
3751 3752
		const struct cifs_sb_info *cifs_sb)
{
3753
	char *full_path, *pos;
3754
	unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
3755
	unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
I
Igor Mammedov 已提交
3756

3757
	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
I
Igor Mammedov 已提交
3758 3759 3760
	if (full_path == NULL)
		return ERR_PTR(-ENOMEM);

3761 3762 3763 3764
	strncpy(full_path, vol->UNC, unc_len);
	pos = full_path + unc_len;

	if (pplen) {
3765 3766
		*pos = CIFS_DIR_SEP(cifs_sb);
		strncpy(pos + 1, vol->prepath, pplen);
3767 3768 3769 3770
		pos += pplen;
	}

	*pos = '\0'; /* add trailing null */
3771
	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
3772
	cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
I
Igor Mammedov 已提交
3773 3774
	return full_path;
}
3775 3776 3777 3778

/*
 * Perform a dfs referral query for a share and (optionally) prefix
 *
3779 3780 3781
 * 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.
3782 3783 3784 3785 3786
 *
 * Returns the rc from get_dfs_path to the caller, which can be used to
 * determine whether there were referrals.
 */
static int
3787
expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
3788
		    struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
3789
		    int check_prefix)
3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802
{
	int rc;
	unsigned int num_referrals = 0;
	struct dfs_info3_param *referrals = NULL;
	char *full_path = NULL, *ref_path = NULL, *mdata = NULL;

	full_path = build_unc_path_to_root(volume_info, cifs_sb);
	if (IS_ERR(full_path))
		return PTR_ERR(full_path);

	/* For DFS paths, skip the first '\' of the UNC */
	ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;

3803
	rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
3804
			  &num_referrals, &referrals, cifs_remap(cifs_sb));
3805 3806 3807 3808 3809 3810 3811 3812 3813

	if (!rc && num_referrals > 0) {
		char *fake_devname = NULL;

		mdata = cifs_compose_mount_options(cifs_sb->mountdata,
						   full_path + 1, referrals,
						   &fake_devname);

		free_dfs_info_array(referrals, num_referrals);
3814

3815 3816 3817
		if (IS_ERR(mdata)) {
			rc = PTR_ERR(mdata);
			mdata = NULL;
J
Jeff Layton 已提交
3818 3819 3820
		} else {
			cleanup_volume_info_contents(volume_info);
			rc = cifs_setup_volume_info(volume_info, mdata,
3821
							fake_devname, false);
3822
		}
J
Jeff Layton 已提交
3823 3824
		kfree(fake_devname);
		kfree(cifs_sb->mountdata);
3825
		cifs_sb->mountdata = mdata;
3826 3827 3828 3829
	}
	kfree(full_path);
	return rc;
}
S
Steve French 已提交
3830
#endif
I
Igor Mammedov 已提交
3831

3832 3833
static int
cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3834
			const char *devname, bool is_smb3)
L
Linus Torvalds 已提交
3835
{
3836
	int rc = 0;
L
Linus Torvalds 已提交
3837

3838
	if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
3839
		return -EINVAL;
L
Linus Torvalds 已提交
3840

3841
	if (volume_info->nullauth) {
3842
		cifs_dbg(FYI, "Anonymous login\n");
J
Jeff Layton 已提交
3843 3844
		kfree(volume_info->username);
		volume_info->username = NULL;
3845
	} else if (volume_info->username) {
L
Linus Torvalds 已提交
3846
		/* BB fixme parse for domain name here */
3847
		cifs_dbg(FYI, "Username: %s\n", volume_info->username);
L
Linus Torvalds 已提交
3848
	} else {
3849
		cifs_dbg(VFS, "No username specified\n");
3850 3851
	/* In userspace mount helper we can get user name from alternate
	   locations such as env variables and files on disk */
3852
		return -EINVAL;
L
Linus Torvalds 已提交
3853 3854 3855
	}

	/* this is needed for ASCII cp to Unicode converts */
3856
	if (volume_info->iocharset == NULL) {
3857 3858
		/* load_nls_default cannot return null */
		volume_info->local_nls = load_nls_default();
L
Linus Torvalds 已提交
3859
	} else {
3860 3861
		volume_info->local_nls = load_nls(volume_info->iocharset);
		if (volume_info->local_nls == NULL) {
3862
			cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
3863
				 volume_info->iocharset);
3864
			return -ELIBACC;
L
Linus Torvalds 已提交
3865 3866
		}
	}
3867 3868 3869 3870

	return rc;
}

3871
struct smb_vol *
3872
cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
3873 3874 3875 3876
{
	int rc;
	struct smb_vol *volume_info;

3877
	volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
3878 3879 3880
	if (!volume_info)
		return ERR_PTR(-ENOMEM);

3881
	rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
3882 3883 3884 3885 3886 3887 3888 3889
	if (rc) {
		cifs_cleanup_volume_info(volume_info);
		volume_info = ERR_PTR(rc);
	}

	return volume_info;
}

3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927
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,
					char *full_path)
{
	int rc;
	char *s;
	char sep, tmp;

	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++;

		/*
		 * 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;
}

3928
int
3929
cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
3930
{
3931
	int rc;
3932
	unsigned int xid;
3933
	struct cifs_ses *ses;
3934
	struct cifs_tcon *tcon;
3935
	struct TCP_Server_Info *server;
3936 3937 3938 3939
	char   *full_path;
	struct tcon_link *tlink;
#ifdef CONFIG_CIFS_DFS_UPCALL
	int referral_walks_count = 0;
3940
#endif
3941

3942
#ifdef CONFIG_CIFS_DFS_UPCALL
3943 3944 3945 3946 3947
try_mount_again:
	/* cleanup activities if we're chasing a referral */
	if (referral_walks_count) {
		if (tcon)
			cifs_put_tcon(tcon);
3948 3949
		else if (ses)
			cifs_put_smb_ses(ses);
3950

3951 3952
		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;

3953
		free_xid(xid);
3954 3955
	}
#endif
3956
	rc = 0;
3957
	tcon = NULL;
3958 3959
	ses = NULL;
	server = NULL;
3960 3961 3962
	full_path = NULL;
	tlink = NULL;

3963
	xid = get_xid();
L
Linus Torvalds 已提交
3964

3965
	/* get a reference to a tcp session */
3966 3967 3968
	server = cifs_get_tcp_session(volume_info);
	if (IS_ERR(server)) {
		rc = PTR_ERR(server);
3969
		goto out;
L
Linus Torvalds 已提交
3970
	}
3971 3972 3973 3974 3975
	if ((volume_info->max_credits < 20) ||
	     (volume_info->max_credits > 60000))
		server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
	else
		server->max_credits = volume_info->max_credits;
3976
	/* get a reference to a SMB session */
3977 3978 3979 3980
	ses = cifs_get_smb_ses(server, volume_info);
	if (IS_ERR(ses)) {
		rc = PTR_ERR(ses);
		ses = NULL;
3981
		goto mount_fail_check;
L
Linus Torvalds 已提交
3982
	}
3983

3984 3985 3986 3987 3988 3989
	if ((volume_info->persistent == true) && ((ses->server->capabilities &
		SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
		cifs_dbg(VFS, "persistent handles not supported by server\n");
		rc = -EOPNOTSUPP;
		goto mount_fail_check;
	}
S
Steve French 已提交
3990

3991
	/* search for existing tcon to this server share */
3992
	tcon = cifs_get_tcon(ses, volume_info);
3993 3994 3995
	if (IS_ERR(tcon)) {
		rc = PTR_ERR(tcon);
		tcon = NULL;
3996 3997 3998
		if (rc == -EACCES)
			goto mount_fail_check;

I
Igor Mammedov 已提交
3999
		goto remote_path_check;
4000
	}
I
Igor Mammedov 已提交
4001

4002 4003 4004 4005
	/* 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;

S
Steve French 已提交
4006
	/* tell server which Unix caps we support */
4007
	if (cap_unix(tcon->ses)) {
S
Steve French 已提交
4008 4009
		/* reset of caps checks mount to see if unix extensions
		   disabled for just this mount */
4010
		reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
4011 4012 4013 4014 4015 4016 4017
		if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
		    (le64_to_cpu(tcon->fsUnixInfo.Capability) &
		     CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
			rc = -EACCES;
			goto mount_fail_check;
		}
	} else
S
Steve French 已提交
4018
		tcon->unix_ext = 0; /* server does not support them */
4019

4020
	/* do not care if a following call succeed - informational */
A
Aurelien Aptel 已提交
4021
	if (!tcon->pipe && server->ops->qfs_tcon)
4022
		server->ops->qfs_tcon(xid, tcon);
4023

4024 4025
	cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
	cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
4026

I
Igor Mammedov 已提交
4027
remote_path_check:
4028 4029 4030 4031 4032 4033 4034 4035 4036
#ifdef CONFIG_CIFS_DFS_UPCALL
	/*
	 * Perform an unconditional check for whether there are DFS
	 * referrals for this path without prefix, 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.
	 * Chase the referral if found, otherwise continue normally.
	 */
	if (referral_walks_count == 0) {
4037 4038
		int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
						false);
4039 4040 4041 4042 4043 4044 4045
		if (!refrc) {
			referral_walks_count++;
			goto try_mount_again;
		}
	}
#endif

4046
	/* check if a whole path is not remote */
4047
	if (!rc && tcon) {
4048 4049 4050 4051
		if (!server->ops->is_path_accessible) {
			rc = -ENOSYS;
			goto mount_fail_check;
		}
4052 4053 4054
		/*
		 * cifs_build_path_to_root works only when we have a valid tcon
		 */
4055 4056
		full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
					tcon->Flags & SMB_SHARE_IS_IN_DFS);
4057 4058 4059 4060
		if (full_path == NULL) {
			rc = -ENOMEM;
			goto mount_fail_check;
		}
4061 4062
		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
						     full_path);
4063
		if (rc != 0 && rc != -EREMOTE) {
4064 4065 4066
			kfree(full_path);
			goto mount_fail_check;
		}
4067

4068 4069
		if (rc != -EREMOTE) {
			rc = cifs_are_all_path_components_accessible(server,
4070 4071
							     xid, tcon, cifs_sb,
							     full_path);
4072 4073 4074 4075 4076 4077
			if (rc != 0) {
				cifs_dbg(VFS, "cannot query dirs between root and final path, "
					 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
				cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
				rc = 0;
			}
4078
		}
4079 4080 4081
		kfree(full_path);
	}

I
Igor Mammedov 已提交
4082 4083
	/* get referral if needed */
	if (rc == -EREMOTE) {
4084
#ifdef CONFIG_CIFS_DFS_UPCALL
4085 4086 4087 4088 4089 4090 4091 4092 4093 4094
		if (referral_walks_count > MAX_NESTED_LINKS) {
			/*
			 * BB: when we implement proper loop detection,
			 *     we will remove this check. But now we need it
			 *     to prevent an indefinite loop if 'DFS tree' is
			 *     misconfigured (i.e. has loops).
			 */
			rc = -ELOOP;
			goto mount_fail_check;
		}
I
Igor Mammedov 已提交
4095

4096
		rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
4097

4098
		if (!rc) {
4099
			referral_walks_count++;
I
Igor Mammedov 已提交
4100 4101
			goto try_mount_again;
		}
4102
		goto mount_fail_check;
4103 4104 4105
#else /* No DFS support, return error on mount */
		rc = -EOPNOTSUPP;
#endif
I
Igor Mammedov 已提交
4106 4107
	}

4108 4109 4110 4111 4112 4113 4114 4115 4116 4117
	if (rc)
		goto mount_fail_check;

	/* now, hang the tcon off of the superblock */
	tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
	if (tlink == NULL) {
		rc = -ENOMEM;
		goto mount_fail_check;
	}

4118
	tlink->tl_uid = ses->linux_uid;
4119 4120 4121 4122 4123
	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);

J
Jeff Layton 已提交
4124
	cifs_sb->master_tlink = tlink;
4125
	spin_lock(&cifs_sb->tlink_tree_lock);
J
Jeff Layton 已提交
4126
	tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4127
	spin_unlock(&cifs_sb->tlink_tree_lock);
4128

J
Jeff Layton 已提交
4129
	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4130 4131
				TLINK_IDLE_EXPIRE);

I
Igor Mammedov 已提交
4132 4133 4134 4135
mount_fail_check:
	/* on error free sesinfo and tcon struct if needed */
	if (rc) {
		/* If find_unc succeeded then rc == 0 so we can not end */
L
Lucas De Marchi 已提交
4136
		/* up accidentally freeing someone elses tcon struct */
I
Igor Mammedov 已提交
4137 4138
		if (tcon)
			cifs_put_tcon(tcon);
4139 4140
		else if (ses)
			cifs_put_smb_ses(ses);
I
Igor Mammedov 已提交
4141
		else
4142
			cifs_put_tcp_session(server, 0);
I
Igor Mammedov 已提交
4143 4144
	}

4145
out:
4146
	free_xid(xid);
L
Linus Torvalds 已提交
4147 4148 4149
	return rc;
}

4150
/*
A
Aurelien Aptel 已提交
4151
 * Issue a TREE_CONNECT request.
4152
 */
L
Linus Torvalds 已提交
4153
int
4154
CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
4155
	 const char *tree, struct cifs_tcon *tcon,
L
Linus Torvalds 已提交
4156 4157 4158 4159 4160 4161 4162 4163
	 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;
4164 4165
	int length;
	__u16 bytes_left, count;
L
Linus Torvalds 已提交
4166 4167 4168 4169 4170

	if (ses == NULL)
		return -EIO;

	smb_buffer = cifs_buf_get();
S
Steve French 已提交
4171
	if (smb_buffer == NULL)
L
Linus Torvalds 已提交
4172
		return -ENOMEM;
S
Steve French 已提交
4173

L
Linus Torvalds 已提交
4174 4175 4176 4177
	smb_buffer_response = smb_buffer;

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

4179
	smb_buffer->Mid = get_next_mid(ses->server);
L
Linus Torvalds 已提交
4180 4181 4182 4183 4184 4185 4186
	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 已提交
4187
	if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
4188
		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
4189
		*bcc_ptr = 0; /* password is null byte */
4190
		bcc_ptr++;              /* skip password */
4191
		/* already aligned so no need to do it below */
4192
	} else {
4193
		pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
4194 4195 4196
		/* 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
4197
		   weaker LANMAN (which we do not send by default) is accepted
4198 4199
		   by Samba (not sure whether other servers allow
		   NTLMv2 password here) */
4200
#ifdef CONFIG_CIFS_WEAK_PW_HASH
4201
		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
4202
		    (ses->sectype == LANMAN))
4203
			calc_lanman_hash(tcon->password, ses->server->cryptkey,
4204
					 ses->server->sec_mode &
4205 4206
					    SECMODE_PW_ENCRYPT ? true : false,
					 bcc_ptr);
4207 4208
		else
#endif /* CIFS_WEAK_PW_HASH */
4209
		rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
4210
					bcc_ptr, nls_codepage);
4211 4212 4213 4214 4215 4216
		if (rc) {
			cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
				 __func__, rc);
			cifs_buf_release(smb_buffer);
			return rc;
		}
4217

4218
		bcc_ptr += CIFS_AUTH_RESP_SIZE;
S
Steve French 已提交
4219
		if (ses->capabilities & CAP_UNICODE) {
4220 4221 4222 4223
			/* must align unicode strings */
			*bcc_ptr = 0; /* null byte password */
			bcc_ptr++;
		}
4224
	}
L
Linus Torvalds 已提交
4225

4226
	if (ses->server->sign)
L
Linus Torvalds 已提交
4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237
		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 =
4238
		    cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
4239
			6 /* max utf8 char length in bytes */ *
4240 4241
			(/* server len*/ + 256 /* share len */), nls_codepage);
		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
L
Linus Torvalds 已提交
4242 4243 4244 4245 4246 4247 4248 4249 4250
		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];
4251 4252
	pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
					pSMB->hdr.smb_buf_length) + count);
L
Linus Torvalds 已提交
4253 4254
	pSMB->ByteCount = cpu_to_le16(count);

4255
	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
4256
			 0);
L
Linus Torvalds 已提交
4257 4258

	/* above now done in SendReceive */
A
Aurelien Aptel 已提交
4259
	if (rc == 0) {
4260 4261
		bool is_unicode;

L
Linus Torvalds 已提交
4262
		tcon->tidStatus = CifsGood;
S
Steve French 已提交
4263
		tcon->need_reconnect = false;
L
Linus Torvalds 已提交
4264 4265
		tcon->tid = smb_buffer_response->Tid;
		bcc_ptr = pByteArea(smb_buffer_response);
4266
		bytes_left = get_bcc(smb_buffer_response);
4267
		length = strnlen(bcc_ptr, bytes_left - 2);
4268 4269 4270 4271 4272
		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
			is_unicode = true;
		else
			is_unicode = false;

4273

4274
		/* skip service field (NB: this field is always ASCII) */
4275 4276 4277
		if (length == 3) {
			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
			    (bcc_ptr[2] == 'C')) {
4278
				cifs_dbg(FYI, "IPC connection\n");
A
Aurelien Aptel 已提交
4279 4280
				tcon->ipc = true;
				tcon->pipe = true;
4281 4282 4283 4284
			}
		} else if (length == 2) {
			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
				/* the most common case */
4285
				cifs_dbg(FYI, "disk share connection\n");
4286 4287
			}
		}
4288
		bcc_ptr += length + 1;
4289
		bytes_left -= (length + 1);
4290
		strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
4291 4292

		/* mostly informational -- no need to fail on error here */
4293
		kfree(tcon->nativeFileSystem);
4294
		tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
4295
						      bytes_left, is_unicode,
4296 4297
						      nls_codepage);

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

S
Steve French 已提交
4300
		if ((smb_buffer_response->WordCount == 3) ||
S
Steve French 已提交
4301 4302
			 (smb_buffer_response->WordCount == 7))
			/* field is in same location */
4303 4304 4305
			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
		else
			tcon->Flags = 0;
4306
		cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
L
Linus Torvalds 已提交
4307 4308
	}

4309
	cifs_buf_release(smb_buffer);
L
Linus Torvalds 已提交
4310 4311 4312
	return rc;
}

4313 4314 4315 4316 4317 4318 4319
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 已提交
4320 4321
void
cifs_umount(struct cifs_sb_info *cifs_sb)
L
Linus Torvalds 已提交
4322
{
J
Jeff Layton 已提交
4323 4324 4325
	struct rb_root *root = &cifs_sb->tlink_tree;
	struct rb_node *node;
	struct tcon_link *tlink;
4326

4327 4328
	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);

J
Jeff Layton 已提交
4329 4330 4331 4332 4333 4334
	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 已提交
4335

J
Jeff Layton 已提交
4336 4337 4338 4339 4340
		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);
4341

4342
	kfree(cifs_sb->mountdata);
4343
	kfree(cifs_sb->prepath);
4344
	call_rcu(&cifs_sb->rcu, delayed_free);
4345
}
L
Linus Torvalds 已提交
4346

4347 4348
int
cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
L
Linus Torvalds 已提交
4349 4350
{
	int rc = 0;
4351
	struct TCP_Server_Info *server = ses->server;
L
Linus Torvalds 已提交
4352

4353 4354 4355
	if (!server->ops->need_neg || !server->ops->negotiate)
		return -ENOSYS;

4356
	/* only send once per connect */
4357
	if (!server->ops->need_neg(server))
4358 4359
		return 0;

4360
	set_credits(server, 1);
4361 4362

	rc = server->ops->negotiate(xid, ses);
4363 4364
	if (rc == 0) {
		spin_lock(&GlobalMid_Lock);
4365
		if (server->tcpStatus == CifsNeedNegotiate)
4366 4367 4368 4369 4370 4371 4372 4373 4374
			server->tcpStatus = CifsGood;
		else
			rc = -EHOSTDOWN;
		spin_unlock(&GlobalMid_Lock);
	}

	return rc;
}

4375 4376 4377
int
cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
		   struct nls_table *nls_info)
4378
{
4379
	int rc = -ENOSYS;
4380
	struct TCP_Server_Info *server = ses->server;
4381

4382
	ses->capabilities = server->capabilities;
4383
	if (linuxExtEnabled == 0)
4384
		ses->capabilities &= (~server->vals->cap_unix);
4385

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

4389
	if (ses->auth_key.response) {
4390
		cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
4391 4392 4393 4394 4395 4396
			 ses->auth_key.response);
		kfree(ses->auth_key.response);
		ses->auth_key.response = NULL;
		ses->auth_key.len = 0;
	}

4397 4398 4399
	if (server->ops->sess_setup)
		rc = server->ops->sess_setup(xid, ses, nls_info);

4400
	if (rc)
4401
		cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
4402

L
Linus Torvalds 已提交
4403 4404 4405
	return rc;
}

4406 4407 4408
static int
cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
{
4409 4410 4411 4412
	vol->sectype = ses->sectype;

	/* krb5 is special, since we don't need username or pw */
	if (vol->sectype == Kerberos)
4413 4414 4415 4416 4417
		return 0;

	return cifs_set_cifscreds(vol, ses);
}

4418
static struct cifs_tcon *
4419
cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
4420
{
4421
	int rc;
4422 4423 4424
	struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
	struct cifs_ses *ses;
	struct cifs_tcon *tcon = NULL;
4425 4426 4427
	struct smb_vol *vol_info;

	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
4428 4429
	if (vol_info == NULL)
		return ERR_PTR(-ENOMEM);
4430 4431 4432 4433 4434 4435 4436

	vol_info->local_nls = cifs_sb->local_nls;
	vol_info->linux_uid = fsuid;
	vol_info->cred_uid = fsuid;
	vol_info->UNC = master_tcon->treeName;
	vol_info->retry = master_tcon->retry;
	vol_info->nocase = master_tcon->nocase;
S
Steve French 已提交
4437
	vol_info->nohandlecache = master_tcon->nohandlecache;
4438 4439
	vol_info->local_lease = master_tcon->local_lease;
	vol_info->no_linux_ext = !master_tcon->unix_ext;
4440 4441
	vol_info->sectype = master_tcon->ses->sectype;
	vol_info->sign = master_tcon->ses->sign;
4442

4443 4444 4445 4446 4447
	rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
	if (rc) {
		tcon = ERR_PTR(rc);
		goto out;
	}
4448 4449

	/* get a reference for the same TCP session */
4450
	spin_lock(&cifs_tcp_ses_lock);
4451
	++master_tcon->ses->server->srv_count;
4452
	spin_unlock(&cifs_tcp_ses_lock);
4453 4454 4455

	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
	if (IS_ERR(ses)) {
4456
		tcon = (struct cifs_tcon *)ses;
4457
		cifs_put_tcp_session(master_tcon->ses->server, 0);
4458 4459 4460 4461 4462 4463 4464 4465 4466
		goto out;
	}

	tcon = cifs_get_tcon(ses, vol_info);
	if (IS_ERR(tcon)) {
		cifs_put_smb_ses(ses);
		goto out;
	}

4467 4468 4469
	/* 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;
4470

4471
	if (cap_unix(ses))
4472
		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
4473

4474
out:
4475
	kfree(vol_info->username);
4476
	kzfree(vol_info->password);
4477 4478 4479 4480 4481
	kfree(vol_info);

	return tcon;
}

4482
struct cifs_tcon *
4483 4484 4485 4486 4487
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
{
	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
}

J
Jeff Layton 已提交
4488 4489
/* find and return a tlink with given uid */
static struct tcon_link *
4490
tlink_rb_search(struct rb_root *root, kuid_t uid)
J
Jeff Layton 已提交
4491 4492 4493 4494 4495 4496 4497
{
	struct rb_node *node = root->rb_node;
	struct tcon_link *tlink;

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

4498
		if (uid_gt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
4499
			node = node->rb_left;
4500
		else if (uid_lt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518
			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;

4519
		if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
J
Jeff Layton 已提交
4520 4521 4522 4523 4524 4525 4526 4527 4528
			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);
}

4529 4530 4531 4532 4533 4534 4535
/*
 * 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.
 *
4536
 * First, search the rbtree for an existing tcon for this fsuid. If one
4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548
 * 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;
4549
	kuid_t fsuid = current_fsuid();
4550 4551 4552 4553 4554 4555
	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 已提交
4556
	tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
4557 4558 4559 4560 4561 4562 4563 4564
	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 已提交
4565
		newtlink->tl_uid = fsuid;
4566 4567 4568 4569 4570 4571 4572
		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 已提交
4573
		tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
4574 4575 4576 4577 4578 4579 4580
		if (tlink) {
			cifs_get_tlink(tlink);
			spin_unlock(&cifs_sb->tlink_tree_lock);
			kfree(newtlink);
			goto wait_for_construction;
		}
		tlink = newtlink;
J
Jeff Layton 已提交
4581 4582
		tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
		spin_unlock(&cifs_sb->tlink_tree_lock);
4583 4584 4585 4586 4587 4588
	} else {
wait_for_construction:
		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
				  TASK_INTERRUPTIBLE);
		if (ret) {
			cifs_put_tlink(tlink);
4589
			return ERR_PTR(-ERESTARTSYS);
4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616
		}

		/* 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;
}
4617 4618 4619 4620 4621 4622 4623 4624 4625 4626

/*
 * 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 已提交
4627
	struct rb_root *root = &cifs_sb->tlink_tree;
4628
	struct rb_node *node;
J
Jeff Layton 已提交
4629 4630
	struct rb_node *tmp;
	struct tcon_link *tlink;
4631

J
Jeff Layton 已提交
4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649
	/*
	 * 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;
4650

J
Jeff Layton 已提交
4651 4652 4653 4654 4655 4656 4657 4658 4659
		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);
4660

J
Jeff Layton 已提交
4661
	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4662 4663
				TLINK_IDLE_EXPIRE);
}