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

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

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

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

76 77
static int ip_connect(struct TCP_Server_Info *server);
static int generic_ip_connect(struct TCP_Server_Info *server);
J
Jeff Layton 已提交
78
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
79
static void cifs_prune_tlinks(struct work_struct *work);
80

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
/*
 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
 * get their ip addresses changed at some point.
 *
 * This should be called with server->srv_mutex held.
 */
#ifdef CONFIG_CIFS_DFS_UPCALL
static int reconn_set_ipaddr(struct TCP_Server_Info *server)
{
	int rc;
	int len;
	char *unc, *ipaddr = NULL;

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

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

	unc = kmalloc(len, GFP_KERNEL);
	if (!unc) {
		cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
		return -ENOMEM;
	}
104
	scnprintf(unc, len, "\\\\%s", server->hostname);
105 106 107 108 109 110 111 112 113 114

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

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

115
	spin_lock(&cifs_tcp_ses_lock);
116 117
	rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
				  strlen(ipaddr));
118
	spin_unlock(&cifs_tcp_ses_lock);
119 120 121 122 123 124 125 126 127 128 129
	kfree(ipaddr);

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

130 131
#ifdef CONFIG_CIFS_DFS_UPCALL
/* These functions must be called with server->srv_mutex held */
132 133 134 135
static void reconn_set_next_dfs_target(struct TCP_Server_Info *server,
				       struct cifs_sb_info *cifs_sb,
				       struct dfs_cache_tgt_list *tgt_list,
				       struct dfs_cache_tgt_iterator **tgt_it)
136 137 138
{
	const char *name;

139
	if (!cifs_sb || !cifs_sb->origin_fullpath)
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
		return;

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

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

	name = dfs_cache_get_tgt_name(*tgt_it);

	kfree(server->hostname);

	server->hostname = extract_hostname(name);
D
Dan Carpenter 已提交
157 158 159 160
	if (IS_ERR(server->hostname)) {
		cifs_dbg(FYI,
			 "%s: failed to extract hostname from target: %ld\n",
			 __func__, PTR_ERR(server->hostname));
161 162 163 164
	}
}

static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
165
					   struct dfs_cache_tgt_list *tl)
166 167 168 169 170 171
{
	if (!cifs_sb->origin_fullpath)
		return -EOPNOTSUPP;
	return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
}
#endif
L
Linus Torvalds 已提交
172

173 174 175 176 177 178 179 180
/*
 * 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 已提交
181
int
L
Linus Torvalds 已提交
182 183 184
cifs_reconnect(struct TCP_Server_Info *server)
{
	int rc = 0;
185
	struct list_head *tmp, *tmp2;
186 187
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
S
Steve French 已提交
188
	struct mid_q_entry *mid_entry;
189
	struct list_head retry_list;
190
#ifdef CONFIG_CIFS_DFS_UPCALL
191
	struct super_block *sb = NULL;
192 193
	struct cifs_sb_info *cifs_sb = NULL;
	struct dfs_cache_tgt_list tgt_list = {0};
194 195
	struct dfs_cache_tgt_iterator *tgt_it = NULL;
#endif
196

L
Linus Torvalds 已提交
197
	spin_lock(&GlobalMid_Lock);
198 199
	server->nr_targets = 1;
#ifdef CONFIG_CIFS_DFS_UPCALL
200
	spin_unlock(&GlobalMid_Lock);
201
	sb = cifs_get_tcp_super(server);
202 203
	if (IS_ERR(sb)) {
		rc = PTR_ERR(sb);
204 205
		cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
			 __func__, rc);
206
		sb = NULL;
207
	} else {
208
		cifs_sb = CIFS_SB(sb);
209
		rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list);
210 211 212 213 214 215
		if (rc) {
			cifs_sb = NULL;
			if (rc != -EOPNOTSUPP) {
				cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
						__func__);
			}
216 217 218 219 220 221
		} else {
			server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
		}
	}
	cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
		 server->nr_targets);
222
	spin_lock(&GlobalMid_Lock);
223
#endif
224
	if (server->tcpStatus == CifsExiting) {
S
Steve French 已提交
225
		/* the demux thread will exit normally
L
Linus Torvalds 已提交
226 227
		next time through the loop */
		spin_unlock(&GlobalMid_Lock);
228 229
#ifdef CONFIG_CIFS_DFS_UPCALL
		dfs_cache_free_tgts(&tgt_list);
230
		cifs_put_tcp_super(sb);
231
#endif
232
		wake_up(&server->response_q);
L
Linus Torvalds 已提交
233 234 235 236 237
		return rc;
	} else
		server->tcpStatus = CifsNeedReconnect;
	spin_unlock(&GlobalMid_Lock);
	server->maxBuf = 0;
238
	server->max_read = 0;
L
Linus Torvalds 已提交
239

240
	cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
S
Steve French 已提交
241
	trace_smb3_reconnect(server->CurrentMid, server->hostname);
L
Linus Torvalds 已提交
242 243 244

	/* before reconnecting the tcp session, mark the smb session (uid)
		and the tid bad so they are not used until reconnected */
245 246
	cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
		 __func__);
247
	spin_lock(&cifs_tcp_ses_lock);
248
	list_for_each(tmp, &server->smb_ses_list) {
249
		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
250
		ses->need_reconnect = true;
251
		list_for_each(tmp2, &ses->tcon_list) {
252
			tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
S
Steve French 已提交
253
			tcon->need_reconnect = true;
L
Linus Torvalds 已提交
254
		}
A
Aurelien Aptel 已提交
255 256
		if (ses->tcon_ipc)
			ses->tcon_ipc->need_reconnect = true;
L
Linus Torvalds 已提交
257
	}
258
	spin_unlock(&cifs_tcp_ses_lock);
259

L
Linus Torvalds 已提交
260
	/* do not want to be sending data on a socket we are freeing */
261
	cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
J
Jeff Layton 已提交
262
	mutex_lock(&server->srv_mutex);
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
	if (server->ssocket) {
		cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
			 server->ssocket->state, server->ssocket->flags);
		kernel_sock_shutdown(server->ssocket, SHUT_WR);
		cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
			 server->ssocket->state, server->ssocket->flags);
		sock_release(server->ssocket);
		server->ssocket = NULL;
	}
	server->sequence_number = 0;
	server->session_estab = false;
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
	server->lstrp = jiffies;
L
Linus Torvalds 已提交
278

279
	/* mark submitted MIDs for retry and issue callback */
280
	INIT_LIST_HEAD(&retry_list);
281
	cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
L
Linus Torvalds 已提交
282
	spin_lock(&GlobalMid_Lock);
283 284
	list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
285
		kref_get(&mid_entry->refcount);
286 287
		if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
			mid_entry->mid_state = MID_RETRY_NEEDED;
288
		list_move(&mid_entry->qhead, &retry_list);
289
		mid_entry->mid_flags |= MID_DELETED;
290 291
	}
	spin_unlock(&GlobalMid_Lock);
292
	mutex_unlock(&server->srv_mutex);
293

294
	cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
295 296
	list_for_each_safe(tmp, tmp2, &retry_list) {
		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
297 298
		list_del_init(&mid_entry->qhead);
		mid_entry->callback(mid_entry);
299
		cifs_mid_q_entry_release(mid_entry);
L
Linus Torvalds 已提交
300 301
	}

302 303
	if (cifs_rdma_enabled(server)) {
		mutex_lock(&server->srv_mutex);
304
		smbd_destroy(server);
305 306
		mutex_unlock(&server->srv_mutex);
	}
307

308
	do {
309
		try_to_freeze();
310

311
		mutex_lock(&server->srv_mutex);
312
#ifdef CONFIG_CIFS_DFS_UPCALL
313 314 315 316 317
		/*
		 * Set up next DFS target server (if any) for reconnect. If DFS
		 * feature is disabled, then we will retry last server we
		 * connected to before.
		 */
318
		reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it);
319 320 321 322 323 324 325
#endif
		rc = reconn_set_ipaddr(server);
		if (rc) {
			cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
				 __func__, rc);
		}

326 327 328 329
		if (cifs_rdma_enabled(server))
			rc = smbd_reconnect(server);
		else
			rc = generic_ip_connect(server);
S
Steve French 已提交
330
		if (rc) {
331
			cifs_dbg(FYI, "reconnect error %d\n", rc);
332
			mutex_unlock(&server->srv_mutex);
333
			msleep(3000);
L
Linus Torvalds 已提交
334 335
		} else {
			atomic_inc(&tcpSesReconnectCount);
336
			set_credits(server, 1);
L
Linus Torvalds 已提交
337
			spin_lock(&GlobalMid_Lock);
338
			if (server->tcpStatus != CifsExiting)
339
				server->tcpStatus = CifsNeedNegotiate;
S
Steve French 已提交
340
			spin_unlock(&GlobalMid_Lock);
341
			mutex_unlock(&server->srv_mutex);
L
Linus Torvalds 已提交
342
		}
343
	} while (server->tcpStatus == CifsNeedReconnect);
344

345 346 347 348 349
#ifdef CONFIG_CIFS_DFS_UPCALL
	if (tgt_it) {
		rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
						    tgt_it);
		if (rc) {
350
			cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
351 352 353 354
				 __func__, rc);
		}
		rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
		if (rc) {
355
			cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
356 357
				 __func__, rc);
		}
358
		dfs_cache_free_tgts(&tgt_list);
359

360
	}
361

362
	cifs_put_tcp_super(sb);
363
#endif
364 365 366
	if (server->tcpStatus == CifsNeedNegotiate)
		mod_delayed_work(cifsiod_wq, &server->echo, 0);

367
	wake_up(&server->response_q);
L
Linus Torvalds 已提交
368 369 370
	return rc;
}

371 372 373 374 375 376
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);
377 378 379 380 381 382 383 384 385 386
	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;
387

388
	/*
389 390
	 * We cannot send an echo if it is disabled.
	 * Also, no need to ping if we got a response recently.
391
	 */
392 393

	if (server->tcpStatus == CifsNeedReconnect ||
394 395
	    server->tcpStatus == CifsExiting ||
	    server->tcpStatus == CifsNew ||
396
	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
S
Steve French 已提交
397
	    time_before(jiffies, server->lstrp + echo_interval - HZ))
398 399
		goto requeue_echo;

400
	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
401
	if (rc)
402 403
		cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
			 server->hostname);
404 405

requeue_echo:
406
	queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
407 408
}

409
static bool
410
allocate_buffers(struct TCP_Server_Info *server)
411
{
412 413 414
	if (!server->bigbuf) {
		server->bigbuf = (char *)cifs_buf_get();
		if (!server->bigbuf) {
415
			cifs_server_dbg(VFS, "No memory for large SMB response\n");
416 417 418 419
			msleep(3000);
			/* retry will check if exiting */
			return false;
		}
420
	} else if (server->large_buf) {
421
		/* we are reusing a dirty large buf, clear its start */
422
		memset(server->bigbuf, 0, HEADER_SIZE(server));
423 424
	}

425 426 427
	if (!server->smallbuf) {
		server->smallbuf = (char *)cifs_small_buf_get();
		if (!server->smallbuf) {
428
			cifs_server_dbg(VFS, "No memory for SMB response\n");
429 430 431 432 433 434 435
			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 */
436
		memset(server->smallbuf, 0, HEADER_SIZE(server));
437 438 439 440 441
	}

	return true;
}

442 443 444
static bool
server_unresponsive(struct TCP_Server_Info *server)
{
445
	/*
446
	 * We need to wait 3 echo intervals to make sure we handle such
447 448
	 * situations right:
	 * 1s  client sends a normal SMB request
449
	 * 2s  client gets a response
450 451 452 453 454 455
	 * 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.
	 */
456 457
	if ((server->tcpStatus == CifsGood ||
	    server->tcpStatus == CifsNeedNegotiate) &&
458
	    time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
459 460
		cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
			 (3 * server->echo_interval) / HZ);
461 462 463 464 465 466 467
		cifs_reconnect(server);
		return true;
	}

	return false;
}

468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
static inline bool
zero_credits(struct TCP_Server_Info *server)
{
	int val;

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

483 484
static int
cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
485
{
J
Jeff Layton 已提交
486 487
	int length = 0;
	int total_read;
488

489 490
	smb_msg->msg_control = NULL;
	smb_msg->msg_controllen = 0;
491

492
	for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
493 494
		try_to_freeze();

495 496 497 498 499 500
		/* reconnect if no credits and no requests in flight */
		if (zero_credits(server)) {
			cifs_reconnect(server);
			return -ECONNABORTED;
		}

501 502
		if (server_unresponsive(server))
			return -ECONNABORTED;
503 504 505 506
		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);
507

508 509
		if (server->tcpStatus == CifsExiting)
			return -ESHUTDOWN;
510

511
		if (server->tcpStatus == CifsNeedReconnect) {
512
			cifs_reconnect(server);
513 514 515 516 517 518
			return -ECONNABORTED;
		}

		if (length == -ERESTARTSYS ||
		    length == -EAGAIN ||
		    length == -EINTR) {
519 520 521 522 523 524 525
			/*
			 * 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 已提交
526
			continue;
527 528 529
		}

		if (length <= 0) {
530
			cifs_dbg(FYI, "Received no data or error: %d\n", length);
531
			cifs_reconnect(server);
532
			return -ECONNABORTED;
533 534
		}
	}
J
Jeff Layton 已提交
535
	return total_read;
536 537
}

J
Jeff Layton 已提交
538 539 540
int
cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
		      unsigned int to_read)
541
{
542 543
	struct msghdr smb_msg;
	struct kvec iov = {.iov_base = buf, .iov_len = to_read};
544
	iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
545

546 547
	return cifs_readv_from_socket(server, &smb_msg);
}
548

549 550
int
cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
L
Long Li 已提交
551
	unsigned int page_offset, unsigned int to_read)
552 553
{
	struct msghdr smb_msg;
L
Long Li 已提交
554 555
	struct bio_vec bv = {
		.bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
556
	iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
557
	return cifs_readv_from_socket(server, &smb_msg);
558 559
}

560
static bool
J
Jeff Layton 已提交
561
is_smb_response(struct TCP_Server_Info *server, unsigned char type)
562 563 564 565 566 567
{
	/*
	 * 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 已提交
568 569 570 571 572
	switch (type) {
	case RFC1002_SESSION_MESSAGE:
		/* Regular SMB response */
		return true;
	case RFC1002_SESSION_KEEP_ALIVE:
573
		cifs_dbg(FYI, "RFC 1002 session keep alive\n");
J
Jeff Layton 已提交
574 575
		break;
	case RFC1002_POSITIVE_SESSION_RESPONSE:
576
		cifs_dbg(FYI, "RFC 1002 positive session response\n");
J
Jeff Layton 已提交
577 578
		break;
	case RFC1002_NEGATIVE_SESSION_RESPONSE:
579 580 581 582
		/*
		 * We get this from Windows 98 instead of an error on
		 * SMB negprot response.
		 */
583
		cifs_dbg(FYI, "RFC 1002 negative session response\n");
584 585 586 587 588 589 590 591
		/* 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 已提交
592
		cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
593
		cifs_reconnect(server);
J
Jeff Layton 已提交
594 595
		break;
	default:
596
		cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
597 598 599
		cifs_reconnect(server);
	}

J
Jeff Layton 已提交
600
	return false;
601 602
}

J
Jeff Layton 已提交
603 604
void
dequeue_mid(struct mid_q_entry *mid, bool malformed)
605
{
606
#ifdef CONFIG_CIFS_STATS2
607
	mid->when_received = jiffies;
608
#endif
609 610
	spin_lock(&GlobalMid_Lock);
	if (!malformed)
611
		mid->mid_state = MID_RESPONSE_RECEIVED;
612
	else
613
		mid->mid_state = MID_RESPONSE_MALFORMED;
614 615 616 617 618
	/*
	 * Trying to handle/dequeue a mid after the send_recv()
	 * function has finished processing it is a bug.
	 */
	if (mid->mid_flags & MID_DELETED)
J
Joe Perches 已提交
619
		pr_warn_once("trying to dequeue a deleted mid\n");
620
	else {
621
		list_del_init(&mid->qhead);
622 623
		mid->mid_flags |= MID_DELETED;
	}
624
	spin_unlock(&GlobalMid_Lock);
625
}
626

627 628 629 630 631 632 633 634 635 636 637 638 639 640
static unsigned int
smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;

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

	return le16_to_cpu(shdr->CreditRequest);
}

641 642
static void
handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
643
	   char *buf, int malformed)
644
{
645 646
	if (server->ops->check_trans2 &&
	    server->ops->check_trans2(mid, server, buf, malformed))
647
		return;
648
	mid->credits_received = smb2_get_credits_from_hdr(buf, server);
649
	mid->resp_buf = buf;
650
	mid->large_buf = server->large_buf;
651 652 653 654 655 656 657 658
	/* 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;
	}
659
	dequeue_mid(mid, malformed);
660 661
}

662 663 664 665 666 667 668 669 670
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);

671 672
	cancel_delayed_work_sync(&server->echo);

673 674 675 676 677
	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
	wake_up_all(&server->response_q);

678
	/* check if we have blocked requests that need to free */
P
Pavel Shilovsky 已提交
679
	spin_lock(&server->req_lock);
680 681
	if (server->credits <= 0)
		server->credits = 1;
P
Pavel Shilovsky 已提交
682
	spin_unlock(&server->req_lock);
683 684 685 686 687 688 689 690 691 692
	/*
	 * 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);
693 694
	if (cifs_rdma_enabled(server))
		smbd_destroy(server);
695 696 697 698 699 700 701 702 703 704 705 706 707 708
	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);
709
			cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
710
			kref_get(&mid_entry->refcount);
711
			mid_entry->mid_state = MID_SHUTDOWN;
712
			list_move(&mid_entry->qhead, &dispose_list);
713
			mid_entry->mid_flags |= MID_DELETED;
714 715 716 717 718 719
		}
		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);
720
			cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
721 722
			list_del_init(&mid_entry->qhead);
			mid_entry->callback(mid_entry);
723
			cifs_mid_q_entry_release(mid_entry);
724 725 726 727 728 729 730 731 732 733 734 735 736 737
		}
		/* 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.
		 */
738
		cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
739 740 741 742 743 744 745 746 747 748 749 750
		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)
751
		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
752 753
}

754 755 756 757 758
static int
standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
	int length;
	char *buf = server->smallbuf;
759
	unsigned int pdu_length = server->pdu_size;
760 761

	/* make sure this will fit in a large buffer */
762 763
	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
		server->vals->header_preamble_size) {
764
		cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
765
		cifs_reconnect(server);
766
		return -ECONNABORTED;
767 768 769 770 771
	}

	/* switch to large buffer if too big for a small one */
	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
		server->large_buf = true;
772
		memcpy(server->bigbuf, buf, server->total_read);
773 774 775 776
		buf = server->bigbuf;
	}

	/* now read the rest */
777
	length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
778 779 780
				       pdu_length - HEADER_SIZE(server) + 1
				       + server->vals->header_preamble_size);

781 782 783 784
	if (length < 0)
		return length;
	server->total_read += length;

785
	dump_smb(buf, server->total_read);
786

787 788 789 790 791 792 793 794 795
	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;

796 797 798 799 800 801 802 803 804
	/*
	 * 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.
	 */
805
	length = server->ops->check_message(buf, server->total_read, server);
806 807 808 809
	if (length != 0)
		cifs_dump_mem("Bad SMB: ", buf,
			min_t(unsigned int, server->total_read, 48));

810 811 812 813 814 815
	if (server->ops->is_session_expired &&
	    server->ops->is_session_expired(buf)) {
		cifs_reconnect(server);
		return -1;
	}

P
Pavel Shilovsky 已提交
816
	if (server->ops->is_status_pending &&
817
	    server->ops->is_status_pending(buf, server))
P
Pavel Shilovsky 已提交
818 819
		return -1;

820 821
	if (!mid)
		return length;
822

823
	handle_mid(mid, server, buf, length);
824
	return 0;
825 826
}

827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
static void
smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{
	struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;

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

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


L
Linus Torvalds 已提交
847
static int
848
cifs_demultiplex_thread(void *p)
L
Linus Torvalds 已提交
849
{
850
	int i, num_mids, length;
851
	struct TCP_Server_Info *server = p;
852
	unsigned int pdu_length;
853
	unsigned int next_offset;
854
	char *buf = NULL;
855
	struct task_struct *task_to_wake = NULL;
856 857
	struct mid_q_entry *mids[MAX_COMPOUND];
	char *bufs[MAX_COMPOUND];
858
	unsigned int noreclaim_flag, num_io_timeout = 0;
L
Linus Torvalds 已提交
859

860
	noreclaim_flag = memalloc_noreclaim_save();
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
	allow_kernel_signal(SIGKILL);
869
	while (server->tcpStatus != CifsExiting) {
870 871
		if (try_to_freeze())
			continue;
872

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

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

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

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

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

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

901
		/* make sure we have enough to get to the MID */
902
		if (server->pdu_size < HEADER_SIZE(server) - 1 -
903
		    server->vals->header_preamble_size) {
904
			cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
905
				 server->pdu_size);
906 907
			cifs_reconnect(server);
			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 926 927 928
		memset(mids, 0, sizeof(mids));
		memset(bufs, 0, sizeof(bufs));
		num_mids = 0;

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,
933 934 935
								mids,
								bufs,
								&num_mids);
936
		} else {
937 938
			mids[0] = server->ops->find_mid(server, buf);
			bufs[0] = buf;
939
			num_mids = 1;
940

941 942
			if (!mids[0] || !mids[0]->receive)
				length = standard_receive3(server, mids[0]);
943
			else
944
				length = mids[0]->receive(server, mids[0]);
945
		}
946

947
		if (length < 0) {
948 949 950
			for (i = 0; i < num_mids; i++)
				if (mids[i])
					cifs_mid_q_entry_release(mids[i]);
J
Jeff Layton 已提交
951
			continue;
952
		}
L
Linus Torvalds 已提交
953

954 955 956 957 958 959 960 961 962 963
		if (server->ops->is_status_io_timeout &&
		    server->ops->is_status_io_timeout(buf)) {
			num_io_timeout++;
			if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
				cifs_reconnect(server);
				num_io_timeout = 0;
				continue;
			}
		}

964
		server->lstrp = jiffies;
S
Sachin Prabhu 已提交
965

966 967 968
		for (i = 0; i < num_mids; i++) {
			if (mids[i] != NULL) {
				mids[i]->resp_buf_size = server->pdu_size;
969

970 971 972 973 974 975 976
				if (!mids[i]->multiRsp || mids[i]->multiEnd)
					mids[i]->callback(mids[i]);

				cifs_mid_q_entry_release(mids[i]);
			} else if (server->ops->is_oplock_break &&
				   server->ops->is_oplock_break(bufs[i],
								server)) {
977
				smb2_add_credits_from_hdr(bufs[i], server);
978 979
				cifs_dbg(FYI, "Received oplock break\n");
			} else {
J
Joe Perches 已提交
980 981
				cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
						atomic_read(&midCount));
982 983
				cifs_dump_mem("Received Data is: ", bufs[i],
					      HEADER_SIZE(server));
984
				smb2_add_credits_from_hdr(bufs[i], server);
985
#ifdef CONFIG_CIFS_DEBUG2
986 987 988 989
				if (server->ops->dump_detail)
					server->ops->dump_detail(bufs[i],
								 server);
				cifs_dump_mids(server);
990
#endif /* CIFS_DEBUG2 */
991
			}
992
		}
993

994 995 996 997 998 999 1000 1001
		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;
1002 1003 1004
		}
	} /* end while !EXITING */

1005
	/* buffer usually freed in free_mid - need to free it here on exit */
1006 1007 1008
	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 已提交
1009

1010
	task_to_wake = xchg(&server->tsk, NULL);
1011
	clean_demultiplex_info(server);
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022

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

1023
	memalloc_noreclaim_restore(noreclaim_flag);
1024
	module_put_and_exit(0);
L
Linus Torvalds 已提交
1025 1026
}

1027 1028 1029
/**
 * 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
1030
 */
1031 1032
bool
cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
{
	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;
1044
		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
1045 1046 1047 1048 1049 1050 1051 1052
		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
	}
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
}

1053 1054 1055 1056 1057 1058 1059 1060
/*
 * 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)
{
1061
	__be16 port, *sport;
1062

1063 1064 1065 1066
	/* SMBDirect manages its own ports, don't match it here */
	if (server->rdma)
		return true;

1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
	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;
}
1091

1092
static bool
1093 1094
match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
	      struct sockaddr *srcaddr)
1095 1096
{
	switch (addr->sa_family) {
1097 1098 1099 1100 1101 1102
	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)
1103 1104
			return false;
		break;
1105 1106 1107 1108 1109 1110
	}
	case AF_INET6: {
		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
		struct sockaddr_in6 *srv_addr6 =
					(struct sockaddr_in6 *)&server->dstaddr;

1111
		if (!ipv6_addr_equal(&addr6->sin6_addr,
1112
				     &srv_addr6->sin6_addr))
1113
			return false;
1114
		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
1115 1116 1117
			return false;
		break;
	}
1118 1119 1120 1121
	default:
		WARN_ON(1);
		return false; /* don't expect to be here */
	}
1122

1123
	if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
1124 1125
		return false;

1126 1127 1128
	return true;
}

1129
static bool
1130
match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
1131
{
1132
	/*
1133
	 * The select_sectype function should either return the ctx->sectype
1134 1135 1136
	 * that was specified, or "Unspecified" if that sectype was not
	 * compatible with the given NEGOTIATE request.
	 */
1137
	if (server->ops->select_sectype(server, ctx->sectype)
S
Sachin Prabhu 已提交
1138
	     == Unspecified)
1139 1140
		return false;

1141 1142 1143 1144 1145
	/*
	 * 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.
	 */
1146
	if (ctx->sign && !server->sign)
1147
		return false;
1148 1149 1150 1151

	return true;
}

1152
static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
1153
{
1154
	struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
1155

1156
	if (ctx->nosharesock)
1157 1158
		return 0;

1159
	/* If multidialect negotiation see if existing sessions match one */
1160
	if (strcmp(ctx->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
1161 1162
		if (server->vals->protocol_id < SMB30_PROT_ID)
			return 0;
1163
	} else if (strcmp(ctx->vals->version_string,
1164 1165 1166
		   SMBDEFAULT_VERSION_STRING) == 0) {
		if (server->vals->protocol_id < SMB21_PROT_ID)
			return 0;
1167
	} else if ((server->vals != ctx->vals) || (server->ops != ctx->ops))
1168 1169
		return 0;

1170 1171 1172 1173
	if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
		return 0;

	if (!match_address(server, addr,
1174
			   (struct sockaddr *)&ctx->srcaddr))
1175 1176 1177 1178 1179
		return 0;

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

1180
	if (!match_security(server, ctx))
1181 1182
		return 0;

1183
	if (server->echo_interval != ctx->echo_interval * HZ)
S
Steve French 已提交
1184 1185
		return 0;

1186
	if (server->rdma != ctx->rdma)
L
Long Li 已提交
1187 1188
		return 0;

1189
	if (server->ignore_signature != ctx->ignore_signature)
1190 1191
		return 0;

1192
	if (server->min_offload != ctx->min_offload)
1193 1194
		return 0;

1195 1196 1197
	return 1;
}

P
Paulo Alcantara 已提交
1198
struct TCP_Server_Info *
1199
cifs_find_tcp_session(struct smb3_fs_context *ctx)
L
Linus Torvalds 已提交
1200
{
1201 1202
	struct TCP_Server_Info *server;

1203
	spin_lock(&cifs_tcp_ses_lock);
1204
	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
1205 1206 1207 1208
		/*
		 * Skip ses channels since they're only handled in lower layers
		 * (e.g. cifs_send_recv).
		 */
1209
		if (server->is_channel || !match_server(server, ctx))
1210 1211
			continue;

1212
		++server->srv_count;
1213
		spin_unlock(&cifs_tcp_ses_lock);
1214
		cifs_dbg(FYI, "Existing tcp session with server found\n");
1215
		return server;
L
Linus Torvalds 已提交
1216
	}
1217
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
1218 1219
	return NULL;
}
1220

1221 1222
void
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
L
Linus Torvalds 已提交
1223
{
1224 1225
	struct task_struct *task;

1226
	spin_lock(&cifs_tcp_ses_lock);
1227
	if (--server->srv_count > 0) {
1228
		spin_unlock(&cifs_tcp_ses_lock);
1229
		return;
L
Linus Torvalds 已提交
1230
	}
1231

1232 1233
	put_net(cifs_net_ns(server));

1234
	list_del_init(&server->tcp_ses_list);
1235
	spin_unlock(&cifs_tcp_ses_lock);
1236

1237 1238
	cancel_delayed_work_sync(&server->echo);

1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249
	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);

1250 1251 1252
	spin_lock(&GlobalMid_Lock);
	server->tcpStatus = CifsExiting;
	spin_unlock(&GlobalMid_Lock);
1253

1254
	cifs_crypto_secmech_release(server);
1255 1256
	cifs_fscache_release_client_cookie(server);

1257 1258 1259
	kfree(server->session_key.response);
	server->session_key.response = NULL;
	server->session_key.len = 0;
1260 1261 1262

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

1266
struct TCP_Server_Info *
1267
cifs_get_tcp_session(struct smb3_fs_context *ctx)
1268 1269 1270 1271
{
	struct TCP_Server_Info *tcp_ses = NULL;
	int rc;

1272
	cifs_dbg(FYI, "UNC: %s\n", ctx->UNC);
1273 1274

	/* see if we already have a matching tcp_ses */
1275
	tcp_ses = cifs_find_tcp_session(ctx);
1276 1277 1278 1279 1280 1281 1282 1283 1284
	if (tcp_ses)
		return tcp_ses;

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

1285 1286
	tcp_ses->ops = ctx->ops;
	tcp_ses->vals = ctx->vals;
1287
	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
1288
	tcp_ses->hostname = extract_hostname(ctx->UNC);
1289 1290
	if (IS_ERR(tcp_ses->hostname)) {
		rc = PTR_ERR(tcp_ses->hostname);
1291
		goto out_err_crypto_release;
1292 1293
	}

1294 1295 1296 1297 1298
	tcp_ses->noblockcnt = ctx->rootfs;
	tcp_ses->noblocksnd = ctx->noblocksnd || ctx->rootfs;
	tcp_ses->noautotune = ctx->noautotune;
	tcp_ses->tcp_nodelay = ctx->sockopt_tcp_nodelay;
	tcp_ses->rdma = ctx->rdma;
P
Pavel Shilovsky 已提交
1299
	tcp_ses->in_flight = 0;
1300
	tcp_ses->max_in_flight = 0;
1301
	tcp_ses->credits = 1;
1302 1303 1304 1305 1306
	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,
1307
		ctx->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1308
	memcpy(tcp_ses->server_RFC1001_name,
1309
		ctx->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
1310
	tcp_ses->session_estab = false;
1311
	tcp_ses->sequence_number = 0;
1312
	tcp_ses->reconnect_instance = 1;
1313
	tcp_ses->lstrp = jiffies;
1314
	tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);
1315
	spin_lock_init(&tcp_ses->req_lock);
1316 1317
	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
1318
	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
1319 1320
	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
	mutex_init(&tcp_ses->reconnect_mutex);
1321
	memcpy(&tcp_ses->srcaddr, &ctx->srcaddr,
1322
	       sizeof(tcp_ses->srcaddr));
1323
	memcpy(&tcp_ses->dstaddr, &ctx->dstaddr,
1324
		sizeof(tcp_ses->dstaddr));
1325 1326
	if (ctx->use_client_guid)
		memcpy(tcp_ses->client_guid, ctx->client_guid,
1327 1328 1329
		       SMB2_CLIENT_GUID_SIZE);
	else
		generate_random_uuid(tcp_ses->client_guid);
1330 1331 1332 1333 1334 1335 1336 1337
	/*
	 * 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;

1338 1339 1340
	if (ctx->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
		ctx->echo_interval <= SMB_ECHO_INTERVAL_MAX)
		tcp_ses->echo_interval = ctx->echo_interval * HZ;
S
Steve French 已提交
1341 1342
	else
		tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
1343 1344 1345 1346 1347 1348 1349
	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(
1350
			tcp_ses, (struct sockaddr *)&ctx->dstaddr);
1351 1352 1353 1354 1355 1356 1357 1358 1359
		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;
		}
	}
1360
	rc = ip_connect(tcp_ses);
1361
	if (rc < 0) {
1362
		cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
1363
		goto out_err_crypto_release;
1364
	}
1365
smbd_connected:
1366 1367 1368 1369 1370
	/*
	 * since we're in a cifs function already, we know that
	 * this will succeed. No need for try_module_get().
	 */
	__module_get(THIS_MODULE);
1371
	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
1372 1373 1374
				  tcp_ses, "cifsd");
	if (IS_ERR(tcp_ses->tsk)) {
		rc = PTR_ERR(tcp_ses->tsk);
1375
		cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
1376
		module_put(THIS_MODULE);
1377
		goto out_err_crypto_release;
1378
	}
1379
	tcp_ses->min_offload = ctx->min_offload;
1380
	tcp_ses->tcpStatus = CifsNeedNegotiate;
1381

1382
	tcp_ses->nr_targets = 1;
1383
	tcp_ses->ignore_signature = ctx->ignore_signature;
1384
	/* thread spawned, put it on the list */
1385
	spin_lock(&cifs_tcp_ses_lock);
1386
	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
1387
	spin_unlock(&cifs_tcp_ses_lock);
1388

1389 1390
	cifs_fscache_get_client_cookie(tcp_ses);

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

1394 1395
	return tcp_ses;

1396
out_err_crypto_release:
1397
	cifs_crypto_secmech_release(tcp_ses);
1398

1399 1400
	put_net(cifs_net_ns(tcp_ses));

1401 1402
out_err:
	if (tcp_ses) {
1403 1404
		if (!IS_ERR(tcp_ses->hostname))
			kfree(tcp_ses->hostname);
1405 1406 1407 1408 1409 1410 1411
		if (tcp_ses->ssocket)
			sock_release(tcp_ses->ssocket);
		kfree(tcp_ses);
	}
	return ERR_PTR(rc);
}

1412
static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
1413
{
1414 1415
	if (ctx->sectype != Unspecified &&
	    ctx->sectype != ses->sectype)
1416 1417
		return 0;

1418 1419 1420 1421
	/*
	 * If an existing session is limited to less channels than
	 * requested, it should not be reused
	 */
1422
	if (ses->chan_max < ctx->max_channels)
1423 1424
		return 0;

1425
	switch (ses->sectype) {
1426
	case Kerberos:
1427
		if (!uid_eq(ctx->cred_uid, ses->cred_uid))
1428 1429 1430
			return 0;
		break;
	default:
J
Jeff Layton 已提交
1431 1432
		/* NULL username means anonymous session */
		if (ses->user_name == NULL) {
1433
			if (!ctx->nullauth)
J
Jeff Layton 已提交
1434 1435 1436 1437
				return 0;
			break;
		}

1438
		/* anything else takes username/password */
J
Jeff Layton 已提交
1439
		if (strncmp(ses->user_name,
1440
			    ctx->username ? ctx->username : "",
1441
			    CIFS_MAX_USERNAME_LEN))
1442
			return 0;
1443
		if ((ctx->username && strlen(ctx->username) != 0) &&
1444 1445
		    ses->password != NULL &&
		    strncmp(ses->password,
1446
			    ctx->password ? ctx->password : "",
1447
			    CIFS_MAX_PASSWORD_LEN))
1448 1449 1450 1451 1452
			return 0;
	}
	return 1;
}

A
Aurelien Aptel 已提交
1453 1454 1455 1456 1457 1458 1459
/**
 * 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
1460
cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
A
Aurelien Aptel 已提交
1461 1462 1463 1464 1465 1466
{
	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;
1467
	struct TCP_Server_Info *server = ses->server;
A
Aurelien Aptel 已提交
1468 1469 1470 1471 1472

	/*
	 * If the mount request that resulted in the creation of the
	 * session requires encryption, force IPC to be encrypted too.
	 */
1473
	if (ctx->seal) {
1474
		if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
A
Aurelien Aptel 已提交
1475 1476
			seal = true;
		else {
1477
			cifs_server_dbg(VFS,
A
Aurelien Aptel 已提交
1478 1479 1480 1481 1482 1483 1484 1485 1486
				 "IPC: server doesn't support encryption\n");
			return -EOPNOTSUPP;
		}
	}

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

1487
	scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
A
Aurelien Aptel 已提交
1488 1489 1490 1491 1492 1493 1494 1495

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

	xid = get_xid();
	tcon->ses = ses;
	tcon->ipc = true;
	tcon->seal = seal;
1496
	rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
A
Aurelien Aptel 已提交
1497 1498 1499
	free_xid(xid);

	if (rc) {
1500
		cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
A
Aurelien Aptel 已提交
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
		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;
}

1541
static struct cifs_ses *
1542
cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
L
Linus Torvalds 已提交
1543
{
1544
	struct cifs_ses *ses;
1545

1546
	spin_lock(&cifs_tcp_ses_lock);
1547
	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
1548 1549
		if (ses->status == CifsExiting)
			continue;
1550
		if (!match_session(ses, ctx))
1551
			continue;
1552
		++ses->ses_count;
1553
		spin_unlock(&cifs_tcp_ses_lock);
1554 1555
		return ses;
	}
1556
	spin_unlock(&cifs_tcp_ses_lock);
1557 1558
	return NULL;
}
1559

1560
void cifs_put_smb_ses(struct cifs_ses *ses)
1561
{
1562
	unsigned int rc, xid;
1563
	struct TCP_Server_Info *server = ses->server;
1564

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

1567
	spin_lock(&cifs_tcp_ses_lock);
1568 1569 1570 1571
	if (ses->status == CifsExiting) {
		spin_unlock(&cifs_tcp_ses_lock);
		return;
	}
1572
	if (--ses->ses_count > 0) {
1573
		spin_unlock(&cifs_tcp_ses_lock);
1574 1575
		return;
	}
1576 1577
	if (ses->status == CifsGood)
		ses->status = CifsExiting;
1578
	spin_unlock(&cifs_tcp_ses_lock);
1579

A
Aurelien Aptel 已提交
1580 1581
	cifs_free_ipc(ses);

1582
	if (ses->status == CifsExiting && server->ops->logoff) {
1583
		xid = get_xid();
1584 1585
		rc = server->ops->logoff(xid, ses);
		if (rc)
1586
			cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
1587
				__func__, rc);
1588
		_free_xid(xid);
1589
	}
1590 1591 1592 1593 1594

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

1595 1596 1597 1598 1599 1600 1601 1602
	/* close any extra channels */
	if (ses->chan_count > 1) {
		int i;

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

1603
	sesInfoFree(ses);
1604
	cifs_put_tcp_session(server, 0);
1605
}
1606

1607 1608
#ifdef CONFIG_KEYS

1609 1610
/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
1611 1612 1613

/* Populate username and pw fields from keyring if possible */
static int
1614
cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
1615 1616
{
	int rc = 0;
1617
	int is_domain = 0;
1618 1619
	const char *delim, *payload;
	char *desc;
1620 1621 1622 1623 1624
	ssize_t len;
	struct key *key;
	struct TCP_Server_Info *server = ses->server;
	struct sockaddr_in *sa;
	struct sockaddr_in6 *sa6;
1625
	const struct user_key_payload *upayload;
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641

	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:
1642 1643
		cifs_dbg(FYI, "Bad ss_family (%hu)\n",
			 server->dstaddr.ss_family);
1644 1645 1646 1647
		rc = -EINVAL;
		goto out_err;
	}

1648
	cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
1649
	key = request_key(&key_type_logon, desc, "");
1650 1651
	if (IS_ERR(key)) {
		if (!ses->domainName) {
1652
			cifs_dbg(FYI, "domainName is NULL\n");
1653 1654 1655 1656 1657 1658
			rc = PTR_ERR(key);
			goto out_err;
		}

		/* didn't work, try to find a domain key */
		sprintf(desc, "cifs:d:%s", ses->domainName);
1659
		cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
1660
		key = request_key(&key_type_logon, desc, "");
1661 1662 1663 1664
		if (IS_ERR(key)) {
			rc = PTR_ERR(key);
			goto out_err;
		}
1665
		is_domain = 1;
1666 1667 1668
	}

	down_read(&key->sem);
1669
	upayload = user_key_payload_locked(key);
1670
	if (IS_ERR_OR_NULL(upayload)) {
1671
		rc = upayload ? PTR_ERR(upayload) : -EINVAL;
1672 1673 1674 1675
		goto out_key_put;
	}

	/* find first : in payload */
1676
	payload = upayload->data;
1677
	delim = strnchr(payload, upayload->datalen, ':');
1678
	cifs_dbg(FYI, "payload=%s\n", payload);
1679
	if (!delim) {
1680 1681
		cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
			 upayload->datalen);
1682 1683 1684 1685 1686
		rc = -EINVAL;
		goto out_key_put;
	}

	len = delim - payload;
1687
	if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
1688 1689
		cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
			 len);
1690 1691 1692 1693
		rc = -EINVAL;
		goto out_key_put;
	}

1694 1695
	ctx->username = kstrndup(payload, len, GFP_KERNEL);
	if (!ctx->username) {
1696 1697
		cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
			 len);
1698 1699 1700
		rc = -ENOMEM;
		goto out_key_put;
	}
1701
	cifs_dbg(FYI, "%s: username=%s\n", __func__, ctx->username);
1702 1703

	len = key->datalen - (len + 1);
1704
	if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
1705
		cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
1706
		rc = -EINVAL;
1707 1708
		kfree(ctx->username);
		ctx->username = NULL;
1709 1710 1711 1712
		goto out_key_put;
	}

	++delim;
1713 1714
	ctx->password = kstrndup(delim, len, GFP_KERNEL);
	if (!ctx->password) {
1715 1716
		cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
			 len);
1717
		rc = -ENOMEM;
1718 1719
		kfree(ctx->username);
		ctx->username = NULL;
1720 1721 1722
		goto out_key_put;
	}

1723 1724 1725 1726 1727
	/*
	 * If we have a domain key then we must set the domainName in the
	 * for the request.
	 */
	if (is_domain && ses->domainName) {
1728
		ctx->domainname = kstrndup(ses->domainName,
1729 1730
					   strlen(ses->domainName),
					   GFP_KERNEL);
1731
		if (!ctx->domainname) {
J
Joe Perches 已提交
1732 1733
			cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
				 len);
1734
			rc = -ENOMEM;
1735 1736 1737 1738
			kfree(ctx->username);
			ctx->username = NULL;
			kfree_sensitive(ctx->password);
			ctx->password = NULL;
1739 1740 1741 1742
			goto out_key_put;
		}
	}

1743 1744 1745 1746 1747
out_key_put:
	up_read(&key->sem);
	key_put(key);
out_err:
	kfree(desc);
1748
	cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
1749 1750 1751 1752
	return rc;
}
#else /* ! CONFIG_KEYS */
static inline int
1753
cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)),
1754 1755 1756 1757 1758 1759
		   struct cifs_ses *ses __attribute__((unused)))
{
	return -ENOSYS;
}
#endif /* CONFIG_KEYS */

1760
/**
1761
 * cifs_get_smb_ses - get a session matching @ctx data from @server
1762 1763 1764 1765 1766
 *
 * 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.
 */
1767
struct cifs_ses *
1768
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
1769
{
1770 1771
	int rc = -ENOMEM;
	unsigned int xid;
1772
	struct cifs_ses *ses;
1773 1774
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
1775

1776
	xid = get_xid();
1777

1778
	ses = cifs_find_smb_ses(server, ctx);
1779
	if (ses) {
1780 1781
		cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
			 ses->status);
1782 1783

		mutex_lock(&ses->session_mutex);
1784 1785 1786 1787 1788
		rc = cifs_negotiate_protocol(xid, ses);
		if (rc) {
			mutex_unlock(&ses->session_mutex);
			/* problem -- put our ses reference */
			cifs_put_smb_ses(ses);
1789
			free_xid(xid);
1790 1791
			return ERR_PTR(rc);
		}
1792
		if (ses->need_reconnect) {
1793
			cifs_dbg(FYI, "Session needs reconnect\n");
1794
			rc = cifs_setup_session(xid, ses,
1795
						ctx->local_nls);
1796 1797 1798 1799
			if (rc) {
				mutex_unlock(&ses->session_mutex);
				/* problem -- put our reference */
				cifs_put_smb_ses(ses);
1800
				free_xid(xid);
1801 1802 1803 1804
				return ERR_PTR(rc);
			}
		}
		mutex_unlock(&ses->session_mutex);
1805 1806

		/* existing SMB ses has a server reference already */
1807
		cifs_put_tcp_session(server, 0);
1808
		free_xid(xid);
1809 1810 1811
		return ses;
	}

1812
	cifs_dbg(FYI, "Existing smb sess not found\n");
1813 1814 1815 1816 1817 1818
	ses = sesInfoAlloc();
	if (ses == NULL)
		goto get_ses_fail;

	/* new SMB session uses our server ref */
	ses->server = server;
1819 1820
	if (server->dstaddr.ss_family == AF_INET6)
		sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
1821
	else
1822
		sprintf(ses->serverName, "%pI4", &addr->sin_addr);
1823

1824 1825
	if (ctx->username) {
		ses->user_name = kstrdup(ctx->username, GFP_KERNEL);
1826 1827 1828
		if (!ses->user_name)
			goto get_ses_fail;
	}
1829

1830 1831 1832
	/* ctx->password freed at unmount */
	if (ctx->password) {
		ses->password = kstrdup(ctx->password, GFP_KERNEL);
1833 1834 1835
		if (!ses->password)
			goto get_ses_fail;
	}
1836 1837
	if (ctx->domainname) {
		ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL);
1838 1839
		if (!ses->domainName)
			goto get_ses_fail;
1840
	}
1841 1842 1843 1844
	if (ctx->domainauto)
		ses->domainAuto = ctx->domainauto;
	ses->cred_uid = ctx->cred_uid;
	ses->linux_uid = ctx->linux_uid;
1845

1846 1847
	ses->sectype = ctx->sectype;
	ses->sign = ctx->sign;
1848
	mutex_lock(&ses->session_mutex);
1849 1850 1851 1852

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

1855 1856
	rc = cifs_negotiate_protocol(xid, ses);
	if (!rc)
1857
		rc = cifs_setup_session(xid, ses, ctx->local_nls);
1858 1859 1860 1861 1862

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

1863
	mutex_unlock(&ses->session_mutex);
1864
	if (rc)
1865 1866
		goto get_ses_fail;

1867
	/* success, put it on the list and add it as first channel */
1868
	spin_lock(&cifs_tcp_ses_lock);
1869
	list_add(&ses->smb_ses_list, &server->smb_ses_list);
1870
	spin_unlock(&cifs_tcp_ses_lock);
1871

1872
	free_xid(xid);
A
Aurelien Aptel 已提交
1873

1874
	cifs_setup_ipc(ses, ctx);
A
Aurelien Aptel 已提交
1875

1876 1877 1878 1879
	return ses;

get_ses_fail:
	sesInfoFree(ses);
1880
	free_xid(xid);
1881 1882 1883
	return ERR_PTR(rc);
}

1884
static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
1885 1886 1887
{
	if (tcon->tidStatus == CifsExiting)
		return 0;
1888
	if (strncmp(tcon->treeName, ctx->UNC, MAX_TREE_SIZE))
1889
		return 0;
1890
	if (tcon->seal != ctx->seal)
1891
		return 0;
1892
	if (tcon->snapshot_time != ctx->snapshot_time)
1893
		return 0;
1894
	if (tcon->handle_timeout != ctx->handle_timeout)
1895
		return 0;
1896
	if (tcon->no_lease != ctx->no_lease)
1897
		return 0;
1898
	if (tcon->nodelete != ctx->nodelete)
S
Steve French 已提交
1899
		return 0;
1900 1901 1902
	return 1;
}

1903
static struct cifs_tcon *
1904
cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
1905 1906
{
	struct list_head *tmp;
1907
	struct cifs_tcon *tcon;
1908

1909
	spin_lock(&cifs_tcp_ses_lock);
1910
	list_for_each(tmp, &ses->tcon_list) {
1911
		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
1912 1913 1914 1915
#ifdef CONFIG_CIFS_DFS_UPCALL
		if (tcon->dfs_path)
			continue;
#endif
1916
		if (!match_tcon(tcon, ctx))
1917 1918
			continue;
		++tcon->tc_count;
1919
		spin_unlock(&cifs_tcp_ses_lock);
1920
		return tcon;
L
Linus Torvalds 已提交
1921
	}
1922
	spin_unlock(&cifs_tcp_ses_lock);
L
Linus Torvalds 已提交
1923 1924 1925
	return NULL;
}

1926
void
1927
cifs_put_tcon(struct cifs_tcon *tcon)
1928
{
1929
	unsigned int xid;
A
Aurelien Aptel 已提交
1930
	struct cifs_ses *ses;
1931

A
Aurelien Aptel 已提交
1932 1933 1934 1935 1936 1937 1938 1939
	/*
	 * 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;
1940
	cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
1941
	spin_lock(&cifs_tcp_ses_lock);
1942
	if (--tcon->tc_count > 0) {
1943
		spin_unlock(&cifs_tcp_ses_lock);
1944 1945 1946
		return;
	}

1947 1948
	/* TODO witness unregister */

1949
	list_del_init(&tcon->tcon_list);
1950
	spin_unlock(&cifs_tcp_ses_lock);
1951

1952
	xid = get_xid();
1953 1954
	if (ses->server->ops->tree_disconnect)
		ses->server->ops->tree_disconnect(xid, tcon);
1955
	_free_xid(xid);
1956

1957
	cifs_fscache_release_super_cookie(tcon);
1958
	tconInfoFree(tcon);
1959 1960 1961
	cifs_put_smb_ses(ses);
}

1962
/**
1963
 * cifs_get_tcon - get a tcon matching @ctx data from @ses
1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981
 *
 * - 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.
 */
1982
static struct cifs_tcon *
1983
cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
1984 1985
{
	int rc, xid;
1986
	struct cifs_tcon *tcon;
1987

1988
	tcon = cifs_find_tcon(ses, ctx);
1989
	if (tcon) {
1990 1991 1992 1993
		/*
		 * tcon has refcount already incremented but we need to
		 * decrement extra ses reference gotten by caller (case b)
		 */
1994
		cifs_dbg(FYI, "Found match on UNC path\n");
1995 1996 1997 1998
		cifs_put_smb_ses(ses);
		return tcon;
	}

1999 2000 2001 2002 2003
	if (!ses->server->ops->tree_connect) {
		rc = -ENOSYS;
		goto out_fail;
	}

2004 2005 2006 2007 2008 2009
	tcon = tconInfoAlloc();
	if (tcon == NULL) {
		rc = -ENOMEM;
		goto out_fail;
	}

2010
	if (ctx->snapshot_time) {
2011 2012 2013 2014 2015 2016
		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
2017
			tcon->snapshot_time = ctx->snapshot_time;
2018 2019
	}

2020
	if (ctx->handle_timeout) {
2021 2022 2023 2024 2025 2026
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
			     "Use SMB2.1 or later for handle timeout option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
2027
			tcon->handle_timeout = ctx->handle_timeout;
2028 2029
	}

2030
	tcon->ses = ses;
2031 2032
	if (ctx->password) {
		tcon->password = kstrdup(ctx->password, GFP_KERNEL);
2033 2034 2035 2036 2037 2038
		if (!tcon->password) {
			rc = -ENOMEM;
			goto out_fail;
		}
	}

2039
	if (ctx->seal) {
2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054
		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;
		}
	}

2055
	if (ctx->linux_ext) {
2056
		if (ses->server->posix_ext_supported) {
2057
			tcon->posix_extensions = true;
J
Joe Perches 已提交
2058
			pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
2059
		} else {
J
Joe Perches 已提交
2060
			cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
2061 2062
			rc = -EOPNOTSUPP;
			goto out_fail;
2063
		}
2064 2065
	}

2066 2067 2068 2069
	/*
	 * BB Do we need to wrap session_mutex around this TCon call and Unix
	 * SetFS as we do on SessSetup and reconnect?
	 */
2070
	xid = get_xid();
2071 2072
	rc = ses->server->ops->tree_connect(xid, ses, ctx->UNC, tcon,
					    ctx->local_nls);
2073
	free_xid(xid);
2074
	cifs_dbg(FYI, "Tcon rc = %d\n", rc);
2075 2076 2077
	if (rc)
		goto out_fail;

2078 2079
	tcon->use_persistent = false;
	/* check if SMB2 or later, CIFS does not support persistent handles */
2080
	if (ctx->persistent) {
2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096
		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)
2097
	     && (ctx->nopersistent == false)) {
2098 2099
		cifs_dbg(FYI, "enabling persistent handles\n");
		tcon->use_persistent = true;
2100
	} else if (ctx->resilient) {
S
Steve French 已提交
2101 2102 2103 2104 2105 2106 2107
		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;
2108
	}
2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128
#ifdef CONFIG_CIFS_SWN_UPCALL
	tcon->use_witness = false;
	if (ctx->witness) {
		if (ses->server->vals->protocol_id >= SMB30_PROT_ID) {
			if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER) {
				/* TODO witness register */
				tcon->use_witness = true;
			} else {
				/* TODO: try to extend for non-cluster uses (eg multichannel) */
				cifs_dbg(VFS, "witness requested on mount but no CLUSTER capability on share\n");
				rc = -EOPNOTSUPP;
				goto out_fail;
			}
		} else {
			cifs_dbg(VFS, "SMB3 or later required for witness option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		}
	}
#endif
2129

2130 2131
	/* If the user really knows what they are doing they can override */
	if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
2132
		if (ctx->cache_ro)
2133
			cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
2134
		else if (ctx->cache_rw)
2135 2136 2137
			cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
	}

2138
	if (ctx->no_lease) {
2139 2140 2141 2142 2143 2144
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
				"SMB2 or later required for nolease option\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else
2145
			tcon->no_lease = ctx->no_lease;
2146 2147
	}

2148 2149 2150 2151 2152
	/*
	 * 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.
	 */
2153 2154
	tcon->retry = ctx->retry;
	tcon->nocase = ctx->nocase;
2155
	if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
2156
		tcon->nohandlecache = ctx->nohandlecache;
2157 2158
	else
		tcon->nohandlecache = 1;
2159 2160
	tcon->nodelete = ctx->nodelete;
	tcon->local_lease = ctx->local_lease;
2161
	INIT_LIST_HEAD(&tcon->pending_opens);
2162

2163
	spin_lock(&cifs_tcp_ses_lock);
2164
	list_add(&tcon->tcon_list, &ses->tcon_list);
2165
	spin_unlock(&cifs_tcp_ses_lock);
2166

2167 2168
	cifs_fscache_get_super_cookie(tcon);

2169 2170 2171 2172 2173 2174 2175
	return tcon;

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

2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192
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;
}
2193

2194 2195 2196 2197 2198
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;
2199 2200
	unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
	unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
2201 2202 2203 2204

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

2205 2206 2207 2208
	if (old->mnt_cifs_serverino_autodisabled)
		newflags &= ~CIFS_MOUNT_SERVER_INUM;

	if (oldflags != newflags)
2209 2210 2211
		return 0;

	/*
2212 2213
	 * 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.
2214 2215 2216 2217
	 */
	if (new->wsize && new->wsize < old->wsize)
		return 0;

2218 2219 2220
	if (new->rsize && new->rsize < old->rsize)
		return 0;

2221
	if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
		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;
}

2237 2238 2239 2240 2241
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;
2242 2243 2244 2245
	bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
		old->prepath;
	bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
		new->prepath;
2246

S
Sachin Prabhu 已提交
2247
	if (old_set && new_set && !strcmp(new->prepath, old->prepath))
2248
		return 1;
S
Sachin Prabhu 已提交
2249 2250 2251
	else if (!old_set && !new_set)
		return 1;

2252 2253 2254
	return 0;
}

2255 2256 2257 2258
int
cifs_match_super(struct super_block *sb, void *data)
{
	struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
2259
	struct smb3_fs_context *ctx;
2260 2261
	struct cifs_sb_info *cifs_sb;
	struct TCP_Server_Info *tcp_srv;
2262 2263
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277
	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;

2278
	ctx = mnt_data->ctx;
2279

2280 2281 2282
	if (!match_server(tcp_srv, ctx) ||
	    !match_session(ses, ctx) ||
	    !match_tcon(tcon, ctx) ||
2283
	    !match_prepath(sb, mnt_data)) {
2284 2285 2286 2287 2288 2289 2290
		rc = 0;
		goto out;
	}

	rc = compare_mount_options(sb, mnt_data);
out:
	spin_unlock(&cifs_tcp_ses_lock);
2291
	cifs_put_tlink(tlink);
2292 2293 2294
	return rc;
}

2295 2296 2297 2298 2299 2300 2301 2302
#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;
2303
	BUG_ON(!sock_allow_reclassification(sk));
2304 2305 2306 2307 2308 2309 2310 2311
	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;
2312
	BUG_ON(!sock_allow_reclassification(sk));
2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327
	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 已提交
2328
/* See RFC1001 section 14 on representation of Netbios names */
2329
static void rfc1002mangle(char *target, char *source, unsigned int length)
L
Linus Torvalds 已提交
2330
{
2331
	unsigned int i, j;
L
Linus Torvalds 已提交
2332

2333
	for (i = 0, j = 0; i < (length); i++) {
L
Linus Torvalds 已提交
2334 2335 2336
		/* mask a nibble at a time and encode */
		target[j] = 'A' + (0x0F & (source[i] >> 4));
		target[j+1] = 'A' + (0x0F & source[i]);
2337
		j += 2;
L
Linus Torvalds 已提交
2338 2339 2340 2341
	}

}

2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357
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)
2358
				cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
2359
					 &saddr6->sin6_addr, rc);
2360
			else
2361
				cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
2362
					 &saddr4->sin_addr.s_addr, rc);
2363 2364 2365 2366
		}
	}
	return rc;
}
L
Linus Torvalds 已提交
2367 2368

static int
2369
ip_rfc1001_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
2370 2371
{
	int rc = 0;
2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383
	/*
	 * 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;

2384
		if (server->server_RFC1001_name[0] != 0)
2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400
			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.
		 */
2401
		if (server->workstation_RFC1001_name[0] != 0)
2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
			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 */
2417
		smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443
		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;
2444
	__be16 sport;
2445
	int slen, sfamily;
2446
	struct socket *socket = server->ssocket;
2447 2448 2449 2450 2451
	struct sockaddr *saddr;

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

	if (server->dstaddr.ss_family == AF_INET6) {
2452 2453 2454
		struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr;

		sport = ipv6->sin6_port;
2455 2456
		slen = sizeof(struct sockaddr_in6);
		sfamily = AF_INET6;
2457 2458
		cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr,
				ntohs(sport));
2459
	} else {
2460 2461 2462
		struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr;

		sport = ipv4->sin_port;
2463 2464
		slen = sizeof(struct sockaddr_in);
		sfamily = AF_INET;
2465 2466
		cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr,
				ntohs(sport));
2467
	}
L
Linus Torvalds 已提交
2468

2469
	if (socket == NULL) {
2470 2471
		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
				   IPPROTO_TCP, &socket, 1);
L
Linus Torvalds 已提交
2472
		if (rc < 0) {
2473
			cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
2474
			server->ssocket = NULL;
L
Linus Torvalds 已提交
2475 2476
			return rc;
		}
2477 2478

		/* BB other socket options to set KEEPALIVE, NODELAY? */
2479
		cifs_dbg(FYI, "Socket created\n");
2480 2481
		server->ssocket = socket;
		socket->sk->sk_allocation = GFP_NOFS;
2482 2483 2484 2485
		if (sfamily == AF_INET6)
			cifs_reclassify_socket6(socket);
		else
			cifs_reclassify_socket4(socket);
L
Linus Torvalds 已提交
2486 2487
	}

2488 2489 2490 2491
	rc = bind_socket(server);
	if (rc < 0)
		return rc;

2492 2493
	/*
	 * Eventually check for other socket options to change from
2494 2495
	 * the default. sock_setsockopt not used because it expects
	 * user space buffer
2496 2497
	 */
	socket->sk->sk_rcvtimeo = 7 * HZ;
2498
	socket->sk->sk_sndtimeo = 5 * HZ;
2499

2500
	/* make the bufsizes depend on wsize/rsize and max requests */
2501 2502 2503 2504 2505
	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;
2506
	}
L
Linus Torvalds 已提交
2507

2508 2509
	if (server->tcp_nodelay)
		tcp_sock_set_nodelay(socket->sk);
2510

2511
	cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
2512
		 socket->sk->sk_sndbuf,
2513
		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
2514

2515 2516
	rc = socket->ops->connect(socket, saddr, slen,
				  server->noblockcnt ? O_NONBLOCK : 0);
2517 2518 2519 2520 2521 2522
	/*
	 * When mounting SMB root file systems, we do not want to block in
	 * connect. Otherwise bail out and then let cifs_reconnect() perform
	 * reconnect failover - if possible.
	 */
	if (server->noblockcnt && rc == -EINPROGRESS)
2523
		rc = 0;
2524
	if (rc < 0) {
2525
		cifs_dbg(FYI, "Error %d connecting to server\n", rc);
2526 2527 2528 2529 2530
		sock_release(socket);
		server->ssocket = NULL;
		return rc;
	}

2531 2532
	if (sport == htons(RFC1001_PORT))
		rc = ip_rfc1001_connect(server);
2533

L
Linus Torvalds 已提交
2534 2535 2536 2537
	return rc;
}

static int
2538
ip_connect(struct TCP_Server_Info *server)
L
Linus Torvalds 已提交
2539
{
2540
	__be16 *sport;
2541 2542
	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
L
Linus Torvalds 已提交
2543

2544 2545 2546 2547
	if (server->dstaddr.ss_family == AF_INET6)
		sport = &addr6->sin6_port;
	else
		sport = &addr->sin_port;
L
Linus Torvalds 已提交
2548

2549 2550
	if (*sport == 0) {
		int rc;
L
Linus Torvalds 已提交
2551

2552 2553
		/* try with 445 port at first */
		*sport = htons(CIFS_PORT);
2554

2555
		rc = generic_ip_connect(server);
L
Linus Torvalds 已提交
2556
		if (rc >= 0)
2557
			return rc;
2558

2559 2560
		/* if it failed, try with 139 port */
		*sport = htons(RFC1001_PORT);
2561 2562
	}

2563
	return generic_ip_connect(server);
L
Linus Torvalds 已提交
2564 2565
}

2566
void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
2567
			  struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
2568
{
2569 2570
	/*
	 * If we are reconnecting then should we check to see if
2571 2572 2573 2574 2575 2576 2577
	 * 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
2578 2579
	 * and once without posixacls or posix paths?
	 */
2580
	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
2581

2582
	if (ctx && ctx->no_linux_ext) {
2583 2584
		tcon->fsUnixInfo.Capability = 0;
		tcon->unix_ext = 0; /* Unix Extensions disabled */
2585
		cifs_dbg(FYI, "Linux protocol extensions disabled\n");
2586
		return;
2587
	} else if (ctx)
2588 2589 2590
		tcon->unix_ext = 1; /* Unix Extensions supported */

	if (tcon->unix_ext == 0) {
2591
		cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
2592 2593
		return;
	}
2594

S
Steve French 已提交
2595
	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
2596
		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
2597
		cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
2598 2599 2600 2601
		/*
		 * check for reconnect case in which we do not
		 * want to change the mount behavior if we can avoid it
		 */
2602
		if (ctx == NULL) {
2603 2604 2605 2606
			/*
			 * turn off POSIX ACL and PATHNAMES if not set
			 * originally at mount time
			 */
2607 2608
			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
2609 2610
			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
2611
					cifs_dbg(VFS, "POSIXPATH support change\n");
2612
				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
2613
			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
2614 2615
				cifs_dbg(VFS, "possible reconnect error\n");
				cifs_dbg(VFS, "server disabled POSIX path support\n");
2616
			}
2617
		}
2618

2619
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
2620
			cifs_dbg(VFS, "per-share encryption not supported yet\n");
2621

2622
		cap &= CIFS_UNIX_CAP_MASK;
2623
		if (ctx && ctx->no_psx_acl)
2624
			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
2625
		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
2626
			cifs_dbg(FYI, "negotiated posix acl support\n");
2627 2628 2629
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
					CIFS_MOUNT_POSIXACL;
2630 2631
		}

2632
		if (ctx && ctx->posix_paths == 0)
2633
			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
2634
		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2635
			cifs_dbg(FYI, "negotiate posix pathnames\n");
2636 2637
			if (cifs_sb)
				cifs_sb->mnt_cifs_flags |=
2638 2639
					CIFS_MOUNT_POSIX_PATHS;
		}
2640

2641
		cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
2642
#ifdef CONFIG_CIFS_DEBUG2
2643
		if (cap & CIFS_UNIX_FCNTL_CAP)
2644
			cifs_dbg(FYI, "FCNTL cap\n");
2645
		if (cap & CIFS_UNIX_EXTATTR_CAP)
2646
			cifs_dbg(FYI, "EXTATTR cap\n");
2647
		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
2648
			cifs_dbg(FYI, "POSIX path cap\n");
2649
		if (cap & CIFS_UNIX_XATTR_CAP)
2650
			cifs_dbg(FYI, "XATTR cap\n");
2651
		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
2652
			cifs_dbg(FYI, "POSIX ACL cap\n");
2653
		if (cap & CIFS_UNIX_LARGE_READ_CAP)
2654
			cifs_dbg(FYI, "very large read cap\n");
2655
		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
2656
			cifs_dbg(FYI, "very large write cap\n");
2657
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
2658
			cifs_dbg(FYI, "transport encryption cap\n");
2659
		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
2660
			cifs_dbg(FYI, "mandatory transport encryption cap\n");
2661 2662
#endif /* CIFS_DEBUG2 */
		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
2663
			if (ctx == NULL)
2664
				cifs_dbg(FYI, "resetting capabilities failed\n");
2665
			else
2666
				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");
2667

2668 2669 2670 2671
		}
	}
}

2672
int cifs_setup_cifs_sb(struct smb3_fs_context *ctx,
2673
			struct cifs_sb_info *cifs_sb)
2674
{
2675 2676
	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);

2677 2678 2679
	spin_lock_init(&cifs_sb->tlink_tree_lock);
	cifs_sb->tlink_tree = RB_ROOT;

2680
	cifs_sb->bsize = ctx->bsize;
2681
	/*
2682 2683
	 * Temporarily set r/wsize for matching superblock. If we end up using
	 * new sb then client will later negotiate it downward if needed.
2684
	 */
2685 2686
	cifs_sb->rsize = ctx->rsize;
	cifs_sb->wsize = ctx->wsize;
2687

2688 2689 2690 2691
	cifs_sb->mnt_uid = ctx->linux_uid;
	cifs_sb->mnt_gid = ctx->linux_gid;
	cifs_sb->mnt_file_mode = ctx->file_mode;
	cifs_sb->mnt_dir_mode = ctx->dir_mode;
2692
	cifs_dbg(FYI, "file mode: %04ho  dir mode: %04ho\n",
2693
		 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
S
Steve French 已提交
2694

2695 2696
	cifs_sb->actimeo = ctx->actimeo;
	cifs_sb->local_nls = ctx->local_nls;
2697

2698
	if (ctx->nodfs)
2699
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
2700
	if (ctx->noperm)
S
Steve French 已提交
2701
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2702
	if (ctx->setuids)
S
Steve French 已提交
2703
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2704
	if (ctx->setuidfromacl)
2705
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
2706
	if (ctx->server_ino)
S
Steve French 已提交
2707
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2708
	if (ctx->remap)
2709
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
2710
	if (ctx->sfu_remap)
S
Steve French 已提交
2711
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2712
	if (ctx->no_xattr)
S
Steve French 已提交
2713
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2714
	if (ctx->sfu_emul)
S
Steve French 已提交
2715
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2716
	if (ctx->nobrl)
S
Steve French 已提交
2717
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2718
	if (ctx->nohandlecache)
S
Steve French 已提交
2719
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
2720
	if (ctx->nostrictsync)
S
Steve French 已提交
2721
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
2722
	if (ctx->mand_lock)
2723
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
2724
	if (ctx->rwpidforward)
2725
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
2726
	if (ctx->mode_ace)
2727
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
2728
	if (ctx->cifs_acl)
S
Steve French 已提交
2729
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2730
	if (ctx->backupuid_specified) {
2731
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
2732
		cifs_sb->mnt_backupuid = ctx->backupuid;
2733
	}
2734
	if (ctx->backupgid_specified) {
2735
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
2736
		cifs_sb->mnt_backupgid = ctx->backupgid;
2737
	}
2738
	if (ctx->override_uid)
S
Steve French 已提交
2739
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2740
	if (ctx->override_gid)
S
Steve French 已提交
2741
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2742
	if (ctx->dynperm)
S
Steve French 已提交
2743
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2744
	if (ctx->fsc)
2745
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
2746
	if (ctx->multiuser)
J
Jeff Layton 已提交
2747 2748
		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
					    CIFS_MOUNT_NO_PERM);
2749
	if (ctx->strict_io)
2750
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
2751
	if (ctx->direct_io) {
2752
		cifs_dbg(FYI, "mounting share using direct i/o\n");
S
Steve French 已提交
2753 2754
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
	}
2755
	if (ctx->cache_ro) {
2756 2757
		cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
2758
	} else if (ctx->cache_rw) {
2759 2760 2761
		cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
					    CIFS_MOUNT_RW_CACHE);
2762
	}
2763 2764
	if (ctx->mfsymlinks) {
		if (ctx->sfu_emul) {
2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776
			/*
			 * 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");
2777
		}
2778
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
2779
	}
S
Steve French 已提交
2780

2781
	if ((ctx->cifs_acl) && (ctx->dynperm))
2782
		cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
2783

2784 2785
	if (ctx->prepath) {
		cifs_sb->prepath = kstrdup(ctx->prepath, GFP_KERNEL);
2786 2787 2788 2789 2790
		if (cifs_sb->prepath == NULL)
			return -ENOMEM;
	}

	return 0;
2791 2792
}

P
Paulo Alcantara 已提交
2793
void
2794
cifs_cleanup_volume_info_contents(struct smb3_fs_context *ctx)
I
Igor Mammedov 已提交
2795
{
2796 2797 2798
	if (ctx == NULL)
		return;

R
Ronnie Sahlberg 已提交
2799 2800 2801 2802 2803
	/*
	 * Make sure this stays in sync with smb3_fs_context_dup()
	 */
	kfree(ctx->mount_options);
	ctx->mount_options = NULL;
2804
	kfree(ctx->username);
R
Ronnie Sahlberg 已提交
2805
	ctx->username = NULL;
2806
	kfree_sensitive(ctx->password);
R
Ronnie Sahlberg 已提交
2807
	ctx->password = NULL;
2808
	kfree(ctx->UNC);
R
Ronnie Sahlberg 已提交
2809
	ctx->UNC = NULL;
2810
	kfree(ctx->domainname);
R
Ronnie Sahlberg 已提交
2811 2812 2813
	ctx->domainname = NULL;
	kfree(ctx->nodename);
	ctx->nodename = NULL;
2814
	kfree(ctx->iocharset);
R
Ronnie Sahlberg 已提交
2815
	ctx->iocharset = NULL;
2816
	kfree(ctx->prepath);
R
Ronnie Sahlberg 已提交
2817
	ctx->prepath = NULL;
2818 2819 2820

	unload_nls(ctx->local_nls);
	ctx->local_nls = NULL;
J
Jeff Layton 已提交
2821 2822 2823
}

void
2824
cifs_cleanup_volume_info(struct smb3_fs_context *ctx)
J
Jeff Layton 已提交
2825
{
2826
	if (!ctx)
J
Jeff Layton 已提交
2827
		return;
2828 2829
	cifs_cleanup_volume_info_contents(ctx);
	kfree(ctx);
I
Igor Mammedov 已提交
2830 2831
}

P
Paulo Alcantara 已提交
2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850
/* Release all succeed connections */
static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
				   unsigned int xid,
				   struct TCP_Server_Info *server,
				   struct cifs_ses *ses, struct cifs_tcon *tcon)
{
	int rc = 0;

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

/* Get connections for tcp, ses and tcon */
2851
static int mount_get_conns(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb,
P
Paulo Alcantara 已提交
2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867
			   unsigned int *xid,
			   struct TCP_Server_Info **nserver,
			   struct cifs_ses **nses, struct cifs_tcon **ntcon)
{
	int rc = 0;
	struct TCP_Server_Info *server;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;

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

	*xid = get_xid();

	/* get a reference to a tcp session */
2868
	server = cifs_get_tcp_session(ctx);
P
Paulo Alcantara 已提交
2869 2870 2871 2872 2873 2874 2875
	if (IS_ERR(server)) {
		rc = PTR_ERR(server);
		return rc;
	}

	*nserver = server;

2876
	if ((ctx->max_credits < 20) || (ctx->max_credits > 60000))
P
Paulo Alcantara 已提交
2877 2878
		server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
	else
2879
		server->max_credits = ctx->max_credits;
P
Paulo Alcantara 已提交
2880 2881

	/* get a reference to a SMB session */
2882
	ses = cifs_get_smb_ses(server, ctx);
P
Paulo Alcantara 已提交
2883 2884 2885 2886 2887 2888 2889
	if (IS_ERR(ses)) {
		rc = PTR_ERR(ses);
		return rc;
	}

	*nses = ses;

2890
	if ((ctx->persistent == true) && (!(ses->server->capabilities &
P
Paulo Alcantara 已提交
2891
					    SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
2892
		cifs_server_dbg(VFS, "persistent handles not supported by server\n");
P
Paulo Alcantara 已提交
2893 2894 2895 2896
		return -EOPNOTSUPP;
	}

	/* search for existing tcon to this server share */
2897
	tcon = cifs_get_tcon(ses, ctx);
P
Paulo Alcantara 已提交
2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914
	if (IS_ERR(tcon)) {
		rc = PTR_ERR(tcon);
		return rc;
	}

	*ntcon = tcon;

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

	/* tell server which Unix caps we support */
	if (cap_unix(tcon->ses)) {
		/*
		 * reset of caps checks mount to see if unix extensions disabled
		 * for just this mount.
		 */
2915
		reset_cifs_unix_caps(*xid, tcon, cifs_sb, ctx);
P
Paulo Alcantara 已提交
2916 2917 2918 2919 2920 2921 2922 2923
		if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
		    (le64_to_cpu(tcon->fsUnixInfo.Capability) &
		     CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
			return -EACCES;
	} else
		tcon->unix_ext = 0; /* server does not support them */

	/* do not care if a following call succeed - informational */
2924
	if (!tcon->pipe && server->ops->qfs_tcon) {
2925
		server->ops->qfs_tcon(*xid, tcon, cifs_sb);
2926 2927
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
			if (tcon->fsDevInfo.DeviceCharacteristics &
2928
			    cpu_to_le32(FILE_READ_ONLY_DEVICE))
2929
				cifs_dbg(VFS, "mounted to read only share\n");
2930 2931
			else if ((cifs_sb->mnt_cifs_flags &
				  CIFS_MOUNT_RW_CACHE) == 0)
2932
				cifs_dbg(VFS, "read only mount of RW share\n");
2933
			/* no need to log a RW mount of a typical RW share */
2934 2935
		}
	}
P
Paulo Alcantara 已提交
2936

2937 2938
	cifs_sb->wsize = server->ops->negotiate_wsize(tcon, ctx);
	cifs_sb->rsize = server->ops->negotiate_rsize(tcon, ctx);
P
Paulo Alcantara 已提交
2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967

	return 0;
}

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

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

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

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

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

S
Steve French 已提交
2969
#ifdef CONFIG_CIFS_DFS_UPCALL
2970 2971 2972 2973
/*
 * cifs_build_path_to_root returns full path to root when we do not have an
 * exiting connection (tcon)
 */
I
Igor Mammedov 已提交
2974
static char *
2975
build_unc_path_to_root(const struct smb3_fs_context *ctx,
2976
		       const struct cifs_sb_info *cifs_sb, bool useppath)
I
Igor Mammedov 已提交
2977
{
2978
	char *full_path, *pos;
2979 2980 2981
	unsigned int pplen = useppath && ctx->prepath ?
		strlen(ctx->prepath) + 1 : 0;
	unsigned int unc_len = strnlen(ctx->UNC, MAX_TREE_SIZE + 1);
I
Igor Mammedov 已提交
2982

2983 2984 2985
	if (unc_len > MAX_TREE_SIZE)
		return ERR_PTR(-EINVAL);

2986
	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
I
Igor Mammedov 已提交
2987 2988 2989
	if (full_path == NULL)
		return ERR_PTR(-ENOMEM);

2990
	memcpy(full_path, ctx->UNC, unc_len);
2991 2992 2993
	pos = full_path + unc_len;

	if (pplen) {
2994
		*pos = CIFS_DIR_SEP(cifs_sb);
2995
		memcpy(pos + 1, ctx->prepath, pplen);
2996 2997 2998 2999
		pos += pplen;
	}

	*pos = '\0'; /* add trailing null */
3000
	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
3001
	cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
I
Igor Mammedov 已提交
3002 3003
	return full_path;
}
3004

3005 3006 3007
/**
 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
 *
3008
 * If a referral is found, cifs_sb->ctx->mount_options will be (re-)allocated
3009 3010
 * to a string containing updated options for the submount.  Otherwise it
 * will be left untouched.
3011 3012 3013 3014 3015
 *
 * Returns the rc from get_dfs_path to the caller, which can be used to
 * determine whether there were referrals.
 */
static int
3016
expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
3017
		    struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb,
3018
		    char *ref_path)
3019 3020
{
	int rc;
3021
	struct dfs_info3_param referral = {0};
3022
	char *full_path = NULL, *mdata = NULL;
3023

3024 3025 3026
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
		return -EREMOTE;

3027
	full_path = build_unc_path_to_root(ctx, cifs_sb, true);
3028 3029 3030
	if (IS_ERR(full_path))
		return PTR_ERR(full_path);

3031 3032 3033
	rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
			    ref_path, &referral, NULL);
	if (!rc) {
3034
		mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
3035
						   full_path + 1, &referral);
3036
		free_dfs_info_param(&referral);
3037

3038 3039 3040
		if (IS_ERR(mdata)) {
			rc = PTR_ERR(mdata);
			mdata = NULL;
J
Jeff Layton 已提交
3041
		} else {
3042
			cifs_cleanup_volume_info_contents(ctx);
R
Ronnie Sahlberg 已提交
3043
			rc = cifs_setup_volume_info(ctx);
3044
		}
3045 3046
		kfree(cifs_sb->ctx->mount_options);
		cifs_sb->ctx->mount_options = mdata;
3047 3048 3049 3050
	}
	kfree(full_path);
	return rc;
}
3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063

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

static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
3064
			   struct smb3_fs_context *fake_ctx, struct smb3_fs_context *ctx)
3065 3066 3067 3068 3069 3070 3071 3072
{
	const char *tgt = dfs_cache_get_tgt_name(tgt_it);
	int len = strlen(tgt) + 2;
	char *new_unc;

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

3075 3076
	kfree(ctx->UNC);
	ctx->UNC = new_unc;
3077

3078 3079 3080 3081
	if (fake_ctx->prepath) {
		kfree(ctx->prepath);
		ctx->prepath = fake_ctx->prepath;
		fake_ctx->prepath = NULL;
3082
	}
3083
	memcpy(&ctx->dstaddr, &fake_ctx->dstaddr, sizeof(ctx->dstaddr));
3084 3085 3086 3087

	return 0;
}

3088
static int setup_dfs_tgt_conn(const char *path, const char *full_path,
3089
			      const struct dfs_cache_tgt_iterator *tgt_it,
3090 3091 3092
			      struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx,
			      unsigned int *xid, struct TCP_Server_Info **server,
			      struct cifs_ses **ses, struct cifs_tcon **tcon)
3093 3094 3095
{
	int rc;
	struct dfs_info3_param ref = {0};
3096
	char *mdata = NULL;
3097
	struct smb3_fs_context fake_ctx = {NULL};
3098 3099 3100 3101 3102 3103 3104

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

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

3105 3106
	mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
					   full_path + 1, &ref);
3107 3108 3109 3110 3111
	free_dfs_info_param(&ref);

	if (IS_ERR(mdata)) {
		rc = PTR_ERR(mdata);
		mdata = NULL;
R
Ronnie Sahlberg 已提交
3112 3113 3114
	} else
		rc = cifs_setup_volume_info(&fake_ctx);

3115 3116 3117 3118
	kfree(mdata);

	if (!rc) {
		/*
3119
		 * We use a 'fake_ctx' here because we need pass it down to the
3120 3121 3122 3123
		 * mount_{get,put} functions to test connection against new DFS
		 * targets.
		 */
		mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
3124
		rc = mount_get_conns(&fake_ctx, cifs_sb, xid, server, ses,
3125
				     tcon);
3126
		if (!rc || (*server && *ses)) {
3127 3128
			/*
			 * We were able to connect to new target server.
3129
			 * Update current context with new target server.
3130
			 */
3131
			rc = update_vol_info(tgt_it, &fake_ctx, ctx);
3132 3133
		}
	}
R
Ronnie Sahlberg 已提交
3134
	cifs_cleanup_volume_info_contents(&fake_ctx);
3135 3136 3137
	return rc;
}

3138
static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb,
3139 3140 3141
			   struct smb3_fs_context *ctx, struct cifs_ses *root_ses,
			   unsigned int *xid, struct TCP_Server_Info **server,
			   struct cifs_ses **ses, struct cifs_tcon **tcon)
3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159
{
	int rc;
	struct dfs_cache_tgt_list tgt_list;
	struct dfs_cache_tgt_iterator *tgt_it = NULL;

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

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

	for (;;) {
		/* Get next DFS target server - if any */
		rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
		if (rc)
			break;
		/* Connect to next DFS target */
3160
		rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, ctx, xid, server, ses,
3161 3162
					tcon);
		if (!rc || (*server && *ses))
3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177
			break;
	}
	if (!rc) {
		/*
		 * Update DFS target hint in DFS referral cache with the target
		 * server we successfully reconnected to.
		 */
		rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
					      cifs_sb->local_nls,
					      cifs_remap(cifs_sb), path,
					      tgt_it);
	}
	dfs_cache_free_tgts(&tgt_list);
	return rc;
}
S
Steve French 已提交
3178
#endif
I
Igor Mammedov 已提交
3179

R
Ronnie Sahlberg 已提交
3180 3181 3182
/* TODO: all callers to this are broken. We are not parsing mount_options here
 * we should pass a clone of the original context?
 */
3183
int
R
Ronnie Sahlberg 已提交
3184
cifs_setup_volume_info(struct smb3_fs_context *ctx)
L
Linus Torvalds 已提交
3185
{
3186
	int rc = 0;
L
Linus Torvalds 已提交
3187

3188
	if (ctx->nullauth) {
3189
		cifs_dbg(FYI, "Anonymous login\n");
3190 3191 3192
		kfree(ctx->username);
		ctx->username = NULL;
	} else if (ctx->username) {
L
Linus Torvalds 已提交
3193
		/* BB fixme parse for domain name here */
3194
		cifs_dbg(FYI, "Username: %s\n", ctx->username);
L
Linus Torvalds 已提交
3195
	} else {
3196
		cifs_dbg(VFS, "No username specified\n");
3197 3198
	/* In userspace mount helper we can get user name from alternate
	   locations such as env variables and files on disk */
3199
		return -EINVAL;
L
Linus Torvalds 已提交
3200 3201 3202
	}

	/* this is needed for ASCII cp to Unicode converts */
3203
	if (ctx->iocharset == NULL) {
3204
		/* load_nls_default cannot return null */
3205
		ctx->local_nls = load_nls_default();
L
Linus Torvalds 已提交
3206
	} else {
3207 3208
		ctx->local_nls = load_nls(ctx->iocharset);
		if (ctx->local_nls == NULL) {
3209
			cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
3210
				 ctx->iocharset);
3211
			return -ELIBACC;
L
Linus Torvalds 已提交
3212 3213
		}
	}
3214 3215 3216 3217

	return rc;
}

3218 3219 3220 3221 3222
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,
3223 3224
					char *full_path,
					int added_treename)
3225 3226 3227 3228
{
	int rc;
	char *s;
	char sep, tmp;
3229
	int skip = added_treename ? 1 : 0;
3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243

	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++;
3244 3245 3246 3247 3248 3249 3250 3251
		/*
		 * if the treename is added, we then have to skip the first
		 * part within the separators
		 */
		if (skip) {
			skip = 0;
			continue;
		}
3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264
		/*
		 * temporarily null-terminate the path at the end of
		 * the current component
		 */
		tmp = *s;
		*s = 0;
		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
						     full_path);
		*s = tmp;
	}
	return rc;
}

P
Paulo Alcantara 已提交
3265 3266 3267 3268
/*
 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
 * otherwise 0.
 */
3269
static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx,
P
Paulo Alcantara 已提交
3270 3271 3272
			  const unsigned int xid,
			  struct TCP_Server_Info *server,
			  struct cifs_tcon *tcon)
3273
{
3274
	int rc;
P
Paulo Alcantara 已提交
3275
	char *full_path;
3276

P
Paulo Alcantara 已提交
3277 3278
	if (!server->ops->is_path_accessible)
		return -EOPNOTSUPP;
3279

P
Paulo Alcantara 已提交
3280 3281 3282
	/*
	 * cifs_build_path_to_root works only when we have a valid tcon
	 */
3283
	full_path = cifs_build_path_to_root(ctx, cifs_sb, tcon,
P
Paulo Alcantara 已提交
3284 3285 3286
					    tcon->Flags & SMB_SHARE_IS_IN_DFS);
	if (full_path == NULL)
		return -ENOMEM;
3287

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

P
Paulo Alcantara 已提交
3290 3291 3292 3293 3294
	rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
					     full_path);
	if (rc != 0 && rc != -EREMOTE) {
		kfree(full_path);
		return rc;
3295
	}
S
Steve French 已提交
3296

P
Paulo Alcantara 已提交
3297 3298
	if (rc != -EREMOTE) {
		rc = cifs_are_all_path_components_accessible(server, xid, tcon,
3299
			cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
P
Paulo Alcantara 已提交
3300
		if (rc != 0) {
J
Joe Perches 已提交
3301
			cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
P
Paulo Alcantara 已提交
3302 3303 3304
			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
			rc = 0;
		}
3305
	}
I
Igor Mammedov 已提交
3306

P
Paulo Alcantara 已提交
3307 3308 3309
	kfree(full_path);
	return rc;
}
3310

P
Paulo Alcantara 已提交
3311
#ifdef CONFIG_CIFS_DFS_UPCALL
3312 3313
static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
			 struct cifs_ses **root_ses)
3314
{
3315 3316 3317
	if (ses) {
		spin_lock(&cifs_tcp_ses_lock);
		ses->ses_count++;
3318 3319
		if (ses->tcon_ipc)
			ses->tcon_ipc->remap = cifs_remap(cifs_sb);
3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331
		spin_unlock(&cifs_tcp_ses_lock);
	}
	*root_ses = ses;
}

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

/* Check if a path component is remote and then update @dfs_path accordingly */
3332
static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx,
3333 3334 3335 3336 3337 3338 3339 3340 3341 3342
			     const unsigned int xid, struct TCP_Server_Info *server,
			     struct cifs_tcon *tcon, char **dfs_path)
{
	char *path, *s;
	char sep = CIFS_DIR_SEP(cifs_sb), tmp;
	char *npath;
	int rc = 0;
	int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS;
	int skip = added_treename;

3343
	path = cifs_build_path_to_root(ctx, cifs_sb, tcon, added_treename);
3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373
	if (!path)
		return -ENOMEM;

	/*
	 * Walk through the path components in @path and check if they're accessible. In case any of
	 * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path
	 * (NOT including the remaining components).
	 */
	s = path;
	do {
		/* skip separators */
		while (*s && *s == sep)
			s++;
		if (!*s)
			break;
		/* next separator */
		while (*s && *s != sep)
			s++;
		/*
		 * if the treename is added, we then have to skip the first
		 * part within the separators
		 */
		if (skip) {
			skip = 0;
			continue;
		}
		tmp = *s;
		*s = 0;
		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path);
		if (rc && rc == -EREMOTE) {
3374
			struct smb3_fs_context v = {NULL};
3375 3376
			/* if @path contains a tree name, skip it in the prefix path */
			if (added_treename) {
3377
				rc = smb3_parse_devname(path, &v);
3378 3379 3380 3381 3382 3383
				if (rc)
					break;
				rc = -EREMOTE;
				npath = build_unc_path_to_root(&v, cifs_sb, true);
				cifs_cleanup_volume_info_contents(&v);
			} else {
3384
				v.UNC = ctx->UNC;
3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399
				v.prepath = path + 1;
				npath = build_unc_path_to_root(&v, cifs_sb, true);
			}
			if (IS_ERR(npath)) {
				rc = PTR_ERR(npath);
				break;
			}
			kfree(*dfs_path);
			*dfs_path = npath;
		}
		*s = tmp;
	} while (rc == 0);

	kfree(path);
	return rc;
3400 3401
}

3402
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
P
Paulo Alcantara 已提交
3403 3404 3405
{
	int rc = 0;
	unsigned int xid;
3406 3407
	struct TCP_Server_Info *server = NULL;
	struct cifs_ses *ses = NULL, *root_ses = NULL;
P
Paulo Alcantara 已提交
3408
	struct cifs_tcon *tcon = NULL;
3409 3410 3411 3412
	int count = 0;
	char *ref_path = NULL, *full_path = NULL;
	char *oldmnt = NULL;
	char *mntdata = NULL;
3413

3414
	rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon);
3415
	/*
3416 3417
	 * Unconditionally try to get an DFS referral (even cached) to determine whether it is an
	 * DFS mount.
3418
	 *
3419 3420
	 * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem
	 * to respond with PATH_NOT_COVERED to requests that include the prefix.
3421
	 */
3422
	if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), ctx->UNC + 1, NULL,
3423 3424 3425 3426 3427
			   NULL)) {
		/* No DFS referral was returned.  Looks like a regular share. */
		if (rc)
			goto error;
		/* Check if it is fully accessible and then mount it */
3428
		rc = is_path_remote(cifs_sb, ctx, xid, server, tcon);
3429 3430 3431 3432
		if (!rc)
			goto out;
		if (rc != -EREMOTE)
			goto error;
3433
	}
3434
	/* Save mount options */
3435 3436
	mntdata = kstrndup(cifs_sb->ctx->mount_options,
			   strlen(cifs_sb->ctx->mount_options), GFP_KERNEL);
3437
	if (!mntdata) {
3438 3439 3440
		rc = -ENOMEM;
		goto error;
	}
3441
	/* Get path of DFS root */
3442
	ref_path = build_unc_path_to_root(ctx, cifs_sb, false);
3443 3444 3445
	if (IS_ERR(ref_path)) {
		rc = PTR_ERR(ref_path);
		ref_path = NULL;
3446 3447
		goto error;
	}
I
Igor Mammedov 已提交
3448

3449 3450 3451
	set_root_ses(cifs_sb, ses, &root_ses);
	do {
		/* Save full path of last DFS path we used to resolve final target server */
3452
		kfree(full_path);
3453
		full_path = build_unc_path_to_root(ctx, cifs_sb, !!count);
3454 3455
		if (IS_ERR(full_path)) {
			rc = PTR_ERR(full_path);
3456
			full_path = NULL;
3457 3458
			break;
		}
3459
		/* Chase referral */
3460
		oldmnt = cifs_sb->ctx->mount_options;
3461
		rc = expand_dfs_referral(xid, root_ses, ctx, cifs_sb, ref_path + 1);
P
Paulo Alcantara 已提交
3462 3463
		if (rc)
			break;
3464
		/* Connect to new DFS target only if we were redirected */
3465
		if (oldmnt != cifs_sb->ctx->mount_options) {
P
Paulo Alcantara 已提交
3466
			mount_put_conns(cifs_sb, xid, server, ses, tcon);
3467
			rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon);
P
Paulo Alcantara 已提交
3468
		}
3469 3470
		if (rc && !server && !ses) {
			/* Failed to connect. Try to connect to other targets in the referral. */
3471
			rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, ctx, root_ses, &xid,
3472
					     &server, &ses, &tcon);
I
Igor Mammedov 已提交
3473
		}
3474 3475 3476 3477 3478
		if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses)
			break;
		if (!tcon)
			continue;
		/* Make sure that requests go through new root servers */
3479
		if (is_tcon_dfs(tcon)) {
3480 3481 3482 3483
			put_root_ses(root_ses);
			set_root_ses(cifs_sb, ses, &root_ses);
		}
		/* Check for remaining path components and then continue chasing them (-EREMOTE) */
3484
		rc = check_dfs_prepath(cifs_sb, ctx, xid, server, tcon, &ref_path);
3485 3486 3487 3488
		/* Prevent recursion on broken link referrals */
		if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS)
			rc = -ELOOP;
	} while (rc == -EREMOTE);
I
Igor Mammedov 已提交
3489

3490
	if (rc)
P
Paulo Alcantara 已提交
3491
		goto error;
3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504
	put_root_ses(root_ses);
	root_ses = NULL;
	kfree(ref_path);
	ref_path = NULL;
	/*
	 * Store DFS full path in both superblock and tree connect structures.
	 *
	 * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so
	 * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS
	 * links, the prefix path is included in both and may be changed during reconnect.  See
	 * cifs_tree_connect().
	 */
	cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL);
3505 3506 3507 3508
	if (!cifs_sb->origin_fullpath) {
		rc = -ENOMEM;
		goto error;
	}
3509 3510 3511 3512
	spin_lock(&cifs_tcp_ses_lock);
	tcon->dfs_path = full_path;
	full_path = NULL;
	tcon->remap = cifs_remap(cifs_sb);
3513 3514
	spin_unlock(&cifs_tcp_ses_lock);

3515 3516
	/* Add original context for DFS cache to be used when refreshing referrals */
	rc = dfs_cache_add_vol(mntdata, ctx, cifs_sb->origin_fullpath);
3517
	if (rc)
3518
		goto error;
3519 3520 3521 3522 3523 3524
	/*
	 * After reconnecting to a different server, unique ids won't
	 * match anymore, so we disable serverino. This prevents
	 * dentry revalidation to think the dentry are stale (ESTALE).
	 */
	cifs_autodisable_serverino(cifs_sb);
3525 3526 3527 3528 3529 3530
	/*
	 * Force the use of prefix path to support failover on DFS paths that
	 * resolve to targets that have different prefix paths.
	 */
	cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
	kfree(cifs_sb->prepath);
3531 3532
	cifs_sb->prepath = ctx->prepath;
	ctx->prepath = NULL;
3533

P
Paulo Alcantara 已提交
3534 3535
out:
	free_xid(xid);
3536
	cifs_try_adding_channels(ses);
P
Paulo Alcantara 已提交
3537
	return mount_setup_tlink(cifs_sb, ses, tcon);
3538

P
Paulo Alcantara 已提交
3539
error:
3540
	kfree(ref_path);
3541
	kfree(full_path);
3542 3543 3544
	kfree(mntdata);
	kfree(cifs_sb->origin_fullpath);
	put_root_ses(root_ses);
P
Paulo Alcantara 已提交
3545 3546 3547 3548
	mount_put_conns(cifs_sb, xid, server, ses, tcon);
	return rc;
}
#else
3549
int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
P
Paulo Alcantara 已提交
3550 3551 3552 3553 3554 3555
{
	int rc = 0;
	unsigned int xid;
	struct cifs_ses *ses;
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
3556

3557
	rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon);
P
Paulo Alcantara 已提交
3558 3559
	if (rc)
		goto error;
3560

P
Paulo Alcantara 已提交
3561
	if (tcon) {
3562
		rc = is_path_remote(cifs_sb, ctx, xid, server, tcon);
P
Paulo Alcantara 已提交
3563 3564 3565 3566
		if (rc == -EREMOTE)
			rc = -EOPNOTSUPP;
		if (rc)
			goto error;
I
Igor Mammedov 已提交
3567 3568
	}

3569
	free_xid(xid);
P
Paulo Alcantara 已提交
3570 3571 3572 3573 3574

	return mount_setup_tlink(cifs_sb, ses, tcon);

error:
	mount_put_conns(cifs_sb, xid, server, ses, tcon);
L
Linus Torvalds 已提交
3575 3576
	return rc;
}
P
Paulo Alcantara 已提交
3577
#endif
L
Linus Torvalds 已提交
3578

3579
/*
A
Aurelien Aptel 已提交
3580
 * Issue a TREE_CONNECT request.
3581
 */
L
Linus Torvalds 已提交
3582
int
3583
CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
3584
	 const char *tree, struct cifs_tcon *tcon,
L
Linus Torvalds 已提交
3585 3586 3587 3588 3589 3590 3591 3592
	 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;
3593 3594
	int length;
	__u16 bytes_left, count;
L
Linus Torvalds 已提交
3595 3596 3597 3598 3599

	if (ses == NULL)
		return -EIO;

	smb_buffer = cifs_buf_get();
S
Steve French 已提交
3600
	if (smb_buffer == NULL)
L
Linus Torvalds 已提交
3601
		return -ENOMEM;
S
Steve French 已提交
3602

L
Linus Torvalds 已提交
3603 3604 3605 3606
	smb_buffer_response = smb_buffer;

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

3608
	smb_buffer->Mid = get_next_mid(ses->server);
L
Linus Torvalds 已提交
3609 3610 3611 3612 3613 3614 3615
	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 已提交
3616
	if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
3617
		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
3618
		*bcc_ptr = 0; /* password is null byte */
3619
		bcc_ptr++;              /* skip password */
3620
		/* already aligned so no need to do it below */
3621
	} else {
3622
		pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
3623 3624 3625
		/* 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
3626
		   weaker LANMAN (which we do not send by default) is accepted
3627 3628
		   by Samba (not sure whether other servers allow
		   NTLMv2 password here) */
3629
#ifdef CONFIG_CIFS_WEAK_PW_HASH
3630
		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
3631
		    (ses->sectype == LANMAN))
3632
			calc_lanman_hash(tcon->password, ses->server->cryptkey,
3633
					 ses->server->sec_mode &
3634 3635
					    SECMODE_PW_ENCRYPT ? true : false,
					 bcc_ptr);
3636 3637
		else
#endif /* CIFS_WEAK_PW_HASH */
3638
		rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
3639
					bcc_ptr, nls_codepage);
3640 3641 3642 3643 3644 3645
		if (rc) {
			cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
				 __func__, rc);
			cifs_buf_release(smb_buffer);
			return rc;
		}
3646

3647
		bcc_ptr += CIFS_AUTH_RESP_SIZE;
S
Steve French 已提交
3648
		if (ses->capabilities & CAP_UNICODE) {
3649 3650 3651 3652
			/* must align unicode strings */
			*bcc_ptr = 0; /* null byte password */
			bcc_ptr++;
		}
3653
	}
L
Linus Torvalds 已提交
3654

3655
	if (ses->server->sign)
L
Linus Torvalds 已提交
3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666
		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 =
3667
		    cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
3668
			6 /* max utf8 char length in bytes */ *
3669 3670
			(/* server len*/ + 256 /* share len */), nls_codepage);
		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
L
Linus Torvalds 已提交
3671 3672 3673 3674 3675 3676 3677 3678 3679
		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];
3680
	be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
L
Linus Torvalds 已提交
3681 3682
	pSMB->ByteCount = cpu_to_le16(count);

3683
	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
3684
			 0);
L
Linus Torvalds 已提交
3685 3686

	/* above now done in SendReceive */
A
Aurelien Aptel 已提交
3687
	if (rc == 0) {
3688 3689
		bool is_unicode;

L
Linus Torvalds 已提交
3690
		tcon->tidStatus = CifsGood;
S
Steve French 已提交
3691
		tcon->need_reconnect = false;
L
Linus Torvalds 已提交
3692 3693
		tcon->tid = smb_buffer_response->Tid;
		bcc_ptr = pByteArea(smb_buffer_response);
3694
		bytes_left = get_bcc(smb_buffer_response);
3695
		length = strnlen(bcc_ptr, bytes_left - 2);
3696 3697 3698 3699 3700
		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
			is_unicode = true;
		else
			is_unicode = false;

3701

3702
		/* skip service field (NB: this field is always ASCII) */
3703 3704 3705
		if (length == 3) {
			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
			    (bcc_ptr[2] == 'C')) {
3706
				cifs_dbg(FYI, "IPC connection\n");
A
Aurelien Aptel 已提交
3707 3708
				tcon->ipc = true;
				tcon->pipe = true;
3709 3710 3711 3712
			}
		} else if (length == 2) {
			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
				/* the most common case */
3713
				cifs_dbg(FYI, "disk share connection\n");
3714 3715
			}
		}
3716
		bcc_ptr += length + 1;
3717
		bytes_left -= (length + 1);
3718
		strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
3719 3720

		/* mostly informational -- no need to fail on error here */
3721
		kfree(tcon->nativeFileSystem);
3722
		tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
3723
						      bytes_left, is_unicode,
3724 3725
						      nls_codepage);

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

S
Steve French 已提交
3728
		if ((smb_buffer_response->WordCount == 3) ||
S
Steve French 已提交
3729 3730
			 (smb_buffer_response->WordCount == 7))
			/* field is in same location */
3731 3732 3733
			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
		else
			tcon->Flags = 0;
3734
		cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
L
Linus Torvalds 已提交
3735 3736
	}

3737
	cifs_buf_release(smb_buffer);
L
Linus Torvalds 已提交
3738 3739 3740
	return rc;
}

3741 3742
static void delayed_free(struct rcu_head *p)
{
3743 3744 3745 3746 3747
	struct cifs_sb_info *cifs_sb = container_of(p, struct cifs_sb_info, rcu);

	unload_nls(cifs_sb->local_nls);
	cifs_cleanup_volume_info(cifs_sb->ctx);
	kfree(cifs_sb);
3748 3749
}

A
Al Viro 已提交
3750 3751
void
cifs_umount(struct cifs_sb_info *cifs_sb)
L
Linus Torvalds 已提交
3752
{
J
Jeff Layton 已提交
3753 3754 3755
	struct rb_root *root = &cifs_sb->tlink_tree;
	struct rb_node *node;
	struct tcon_link *tlink;
3756

3757 3758
	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);

J
Jeff Layton 已提交
3759 3760 3761 3762 3763 3764
	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 已提交
3765

J
Jeff Layton 已提交
3766 3767 3768 3769 3770
		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);
3771

3772
	kfree(cifs_sb->prepath);
3773
#ifdef CONFIG_CIFS_DFS_UPCALL
3774
	dfs_cache_del_vol(cifs_sb->origin_fullpath);
3775 3776
	kfree(cifs_sb->origin_fullpath);
#endif
3777
	call_rcu(&cifs_sb->rcu, delayed_free);
3778
}
L
Linus Torvalds 已提交
3779

3780 3781
int
cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
L
Linus Torvalds 已提交
3782 3783
{
	int rc = 0;
3784
	struct TCP_Server_Info *server = cifs_ses_server(ses);
L
Linus Torvalds 已提交
3785

3786 3787 3788
	if (!server->ops->need_neg || !server->ops->negotiate)
		return -ENOSYS;

3789
	/* only send once per connect */
3790
	if (!server->ops->need_neg(server))
3791 3792
		return 0;

3793
	rc = server->ops->negotiate(xid, ses);
3794 3795
	if (rc == 0) {
		spin_lock(&GlobalMid_Lock);
3796
		if (server->tcpStatus == CifsNeedNegotiate)
3797 3798 3799 3800 3801 3802 3803 3804 3805
			server->tcpStatus = CifsGood;
		else
			rc = -EHOSTDOWN;
		spin_unlock(&GlobalMid_Lock);
	}

	return rc;
}

3806 3807 3808
int
cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
		   struct nls_table *nls_info)
3809
{
3810
	int rc = -ENOSYS;
3811
	struct TCP_Server_Info *server = cifs_ses_server(ses);
3812

3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825
	if (!ses->binding) {
		ses->capabilities = server->capabilities;
		if (linuxExtEnabled == 0)
			ses->capabilities &= (~server->vals->cap_unix);

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

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

3830 3831 3832
	if (server->ops->sess_setup)
		rc = server->ops->sess_setup(xid, ses, nls_info);

3833
	if (rc)
3834
		cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
3835

L
Linus Torvalds 已提交
3836 3837 3838
	return rc;
}

3839
static int
3840
cifs_set_vol_auth(struct smb3_fs_context *ctx, struct cifs_ses *ses)
3841
{
3842
	ctx->sectype = ses->sectype;
3843 3844

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

3848
	return cifs_set_cifscreds(ctx, ses);
3849 3850
}

3851
static struct cifs_tcon *
3852
cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
3853
{
3854
	int rc;
3855 3856 3857
	struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
	struct cifs_ses *ses;
	struct cifs_tcon *tcon = NULL;
3858
	struct smb3_fs_context *ctx;
3859

3860 3861
	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
	if (ctx == NULL)
3862
		return ERR_PTR(-ENOMEM);
3863

3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880
	ctx->local_nls = cifs_sb->local_nls;
	ctx->linux_uid = fsuid;
	ctx->cred_uid = fsuid;
	ctx->UNC = master_tcon->treeName;
	ctx->retry = master_tcon->retry;
	ctx->nocase = master_tcon->nocase;
	ctx->nohandlecache = master_tcon->nohandlecache;
	ctx->local_lease = master_tcon->local_lease;
	ctx->no_lease = master_tcon->no_lease;
	ctx->resilient = master_tcon->use_resilient;
	ctx->persistent = master_tcon->use_persistent;
	ctx->handle_timeout = master_tcon->handle_timeout;
	ctx->no_linux_ext = !master_tcon->unix_ext;
	ctx->linux_ext = master_tcon->posix_extensions;
	ctx->sectype = master_tcon->ses->sectype;
	ctx->sign = master_tcon->ses->sign;
	ctx->seal = master_tcon->seal;
3881 3882 3883
#ifdef CONFIG_CIFS_SWN_UPCALL
	ctx->witness = master_tcon->use_witness;
#endif
3884 3885

	rc = cifs_set_vol_auth(ctx, master_tcon->ses);
3886 3887 3888 3889
	if (rc) {
		tcon = ERR_PTR(rc);
		goto out;
	}
3890 3891

	/* get a reference for the same TCP session */
3892
	spin_lock(&cifs_tcp_ses_lock);
3893
	++master_tcon->ses->server->srv_count;
3894
	spin_unlock(&cifs_tcp_ses_lock);
3895

3896
	ses = cifs_get_smb_ses(master_tcon->ses->server, ctx);
3897
	if (IS_ERR(ses)) {
3898
		tcon = (struct cifs_tcon *)ses;
3899
		cifs_put_tcp_session(master_tcon->ses->server, 0);
3900 3901 3902
		goto out;
	}

3903
	tcon = cifs_get_tcon(ses, ctx);
3904 3905 3906 3907 3908
	if (IS_ERR(tcon)) {
		cifs_put_smb_ses(ses);
		goto out;
	}

3909
	if (cap_unix(ses))
3910
		reset_cifs_unix_caps(0, tcon, NULL, ctx);
3911

3912
out:
3913 3914 3915
	kfree(ctx->username);
	kfree_sensitive(ctx->password);
	kfree(ctx);
3916 3917 3918 3919

	return tcon;
}

3920
struct cifs_tcon *
3921 3922 3923 3924 3925
cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
{
	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
}

J
Jeff Layton 已提交
3926 3927
/* find and return a tlink with given uid */
static struct tcon_link *
3928
tlink_rb_search(struct rb_root *root, kuid_t uid)
J
Jeff Layton 已提交
3929 3930 3931 3932 3933 3934 3935
{
	struct rb_node *node = root->rb_node;
	struct tcon_link *tlink;

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

3936
		if (uid_gt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
3937
			node = node->rb_left;
3938
		else if (uid_lt(tlink->tl_uid, uid))
J
Jeff Layton 已提交
3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956
			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;

3957
		if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
J
Jeff Layton 已提交
3958 3959 3960 3961 3962 3963 3964 3965 3966
			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);
}

3967 3968 3969 3970 3971 3972 3973
/*
 * 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.
 *
3974
 * First, search the rbtree for an existing tcon for this fsuid. If one
3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986
 * 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;
3987
	kuid_t fsuid = current_fsuid();
3988 3989 3990 3991 3992 3993
	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 已提交
3994
	tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
3995 3996 3997 3998 3999 4000 4001 4002
	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 已提交
4003
		newtlink->tl_uid = fsuid;
4004 4005 4006 4007 4008 4009 4010
		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 已提交
4011
		tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
4012 4013 4014 4015 4016 4017 4018
		if (tlink) {
			cifs_get_tlink(tlink);
			spin_unlock(&cifs_sb->tlink_tree_lock);
			kfree(newtlink);
			goto wait_for_construction;
		}
		tlink = newtlink;
J
Jeff Layton 已提交
4019 4020
		tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
		spin_unlock(&cifs_sb->tlink_tree_lock);
4021 4022 4023 4024 4025 4026
	} else {
wait_for_construction:
		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
				  TASK_INTERRUPTIBLE);
		if (ret) {
			cifs_put_tlink(tlink);
4027
			return ERR_PTR(-ERESTARTSYS);
4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054
		}

		/* 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;
}
4055 4056 4057 4058 4059 4060 4061 4062 4063 4064

/*
 * 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 已提交
4065
	struct rb_root *root = &cifs_sb->tlink_tree;
4066
	struct rb_node *node;
J
Jeff Layton 已提交
4067 4068
	struct rb_node *tmp;
	struct tcon_link *tlink;
4069

J
Jeff Layton 已提交
4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087
	/*
	 * 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;
4088

J
Jeff Layton 已提交
4089 4090 4091 4092 4093 4094 4095 4096 4097
		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);
4098

J
Jeff Layton 已提交
4099
	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4100 4101
				TLINK_IDLE_EXPIRE);
}
4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115

#ifdef CONFIG_CIFS_DFS_UPCALL
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
	int rc;
	struct TCP_Server_Info *server = tcon->ses->server;
	const struct smb_version_operations *ops = server->ops;
	struct dfs_cache_tgt_list tl;
	struct dfs_cache_tgt_iterator *it = NULL;
	char *tree;
	const char *tcp_host;
	size_t tcp_host_len;
	const char *dfs_host;
	size_t dfs_host_len;
4116
	char *share = NULL, *prefix = NULL;
4117 4118
	struct dfs_info3_param ref = {0};
	bool isroot;
4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133

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

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

4134
	rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl);
4135 4136
	if (rc)
		goto out;
4137 4138
	isroot = ref.server_type == DFS_TYPE_ROOT;
	free_dfs_info_param(&ref);
4139 4140 4141 4142 4143 4144

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

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

4145 4146
		kfree(share);
		kfree(prefix);
4147 4148
		share = NULL;
		prefix = NULL;
4149 4150

		rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix);
4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176
		if (rc) {
			cifs_dbg(VFS, "%s: failed to parse target share %d\n",
				 __func__, rc);
			continue;
		}

		extract_unc_hostname(share, &dfs_host, &dfs_host_len);

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

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

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

		if (tcon->ipc) {
4177
			scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share);
4178 4179
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
		} else {
4180
			scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
4181
			rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
4182 4183
			/* Only handle prefix paths of DFS link targets */
			if (!rc && !isroot) {
4184
				rc = update_super_prepath(tcon, prefix);
4185 4186 4187 4188 4189 4190 4191
				break;
			}
		}
		if (rc == -EREMOTE)
			break;
	}

4192 4193 4194
	kfree(share);
	kfree(prefix);

4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213
	if (!rc) {
		if (it)
			rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it);
		else
			rc = -ENOENT;
	}
	dfs_cache_free_tgts(&tl);
out:
	kfree(tree);
	return rc;
}
#else
int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
{
	const struct smb_version_operations *ops = tcon->ses->server->ops;

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