xref: /linux/fs/smb/server/mgmt/user_session.c (revision 39f1c201b93f4ff71631bac72cff6eb155f976a4)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
4  */
5 
6 #include <linux/list.h>
7 #include <linux/slab.h>
8 #include <linux/rwsem.h>
9 #include <linux/xarray.h>
10 
11 #include "ksmbd_ida.h"
12 #include "user_session.h"
13 #include "user_config.h"
14 #include "tree_connect.h"
15 #include "share_config.h"
16 #include "../transport_ipc.h"
17 #include "../connection.h"
18 #include "../vfs_cache.h"
19 #include "../misc.h"
20 #include "../stats.h"
21 
22 static DEFINE_IDA(session_ida);
23 
24 #define SESSION_HASH_BITS		12
25 static DEFINE_HASHTABLE(sessions_table, SESSION_HASH_BITS);
26 static DECLARE_RWSEM(sessions_table_lock);
27 
28 struct ksmbd_session_rpc {
29 	int			id;
30 	unsigned int		method;
31 };
32 
33 #ifdef CONFIG_PROC_FS
34 
35 static const struct ksmbd_const_name ksmbd_sess_cap_const_names[] = {
36 	{SMB2_GLOBAL_CAP_DFS, "dfs"},
37 	{SMB2_GLOBAL_CAP_LEASING, "lease"},
38 	{SMB2_GLOBAL_CAP_LARGE_MTU, "large-mtu"},
39 	{SMB2_GLOBAL_CAP_MULTI_CHANNEL, "multi-channel"},
40 	{SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, "persistent-handles"},
41 	{SMB2_GLOBAL_CAP_DIRECTORY_LEASING, "dir-lease"},
42 	{SMB2_GLOBAL_CAP_ENCRYPTION, "encryption"}
43 };
44 
45 static const struct ksmbd_const_name ksmbd_cipher_const_names[] = {
46 	{le16_to_cpu(SMB2_ENCRYPTION_AES128_CCM), "aes128-ccm"},
47 	{le16_to_cpu(SMB2_ENCRYPTION_AES128_GCM), "aes128-gcm"},
48 	{le16_to_cpu(SMB2_ENCRYPTION_AES256_CCM), "aes256-ccm"},
49 	{le16_to_cpu(SMB2_ENCRYPTION_AES256_GCM), "aes256-gcm"},
50 };
51 
52 static const struct ksmbd_const_name ksmbd_signing_const_names[] = {
53 	{SIGNING_ALG_HMAC_SHA256, "hmac-sha256"},
54 	{SIGNING_ALG_AES_CMAC, "aes-cmac"},
55 	{SIGNING_ALG_AES_GMAC, "aes-gmac"},
56 };
57 
58 static const char *session_state_string(struct ksmbd_session *session)
59 {
60 	switch (session->state) {
61 	case SMB2_SESSION_VALID:
62 		return "valid";
63 	case SMB2_SESSION_IN_PROGRESS:
64 		return "progress";
65 	case SMB2_SESSION_EXPIRED:
66 		return "expired";
67 	default:
68 		return "";
69 	}
70 }
71 
72 static const char *session_user_name(struct ksmbd_session *session)
73 {
74 	if (user_guest(session->user))
75 		return "(Guest)";
76 	else if (ksmbd_anonymous_user(session->user))
77 		return "(Anonymous)";
78 	return session->user->name;
79 }
80 
81 static int show_proc_session(struct seq_file *m, void *v)
82 {
83 	struct ksmbd_session *sess;
84 	struct ksmbd_tree_connect *tree_conn;
85 	struct ksmbd_share_config *share_conf;
86 	struct channel *chan;
87 	unsigned long id;
88 	int i = 0;
89 
90 	sess = (struct ksmbd_session *)m->private;
91 	ksmbd_user_session_get(sess);
92 
93 	i = 0;
94 	down_read(&sess->chann_lock);
95 	xa_for_each(&sess->ksmbd_chann_list, id, chan) {
96 #if IS_ENABLED(CONFIG_IPV6)
97 		if (chan->conn->inet_addr)
98 			seq_printf(m, "%-20s\t%pI4\n", "client",
99 					&chan->conn->inet_addr);
100 		else
101 			seq_printf(m, "%-20s\t%pI6c\n", "client",
102 					&chan->conn->inet6_addr);
103 #else
104 		seq_printf(m, "%-20s\t%pI4\n", "client",
105 				&chan->conn->inet_addr);
106 #endif
107 		seq_printf(m, "%-20s\t%s\n", "user", session_user_name(sess));
108 		seq_printf(m, "%-20s\t%llu\n", "id", sess->id);
109 		seq_printf(m, "%-20s\t%s\n", "state",
110 				session_state_string(sess));
111 
112 		seq_printf(m, "%-20s\t", "capabilities");
113 		ksmbd_proc_show_flag_names(m,
114 				ksmbd_sess_cap_const_names,
115 				ARRAY_SIZE(ksmbd_sess_cap_const_names),
116 				chan->conn->vals->req_capabilities);
117 
118 		if (sess->sign) {
119 			seq_printf(m, "%-20s\t", "signing");
120 			ksmbd_proc_show_const_name(m, "%s\t",
121 					ksmbd_signing_const_names,
122 					ARRAY_SIZE(ksmbd_signing_const_names),
123 					le16_to_cpu(chan->conn->signing_algorithm));
124 		} else if (sess->enc) {
125 			seq_printf(m, "%-20s\t", "encryption");
126 			ksmbd_proc_show_const_name(m, "%s\t",
127 					ksmbd_cipher_const_names,
128 					ARRAY_SIZE(ksmbd_cipher_const_names),
129 					le16_to_cpu(chan->conn->cipher_type));
130 		}
131 		i++;
132 	}
133 	up_read(&sess->chann_lock);
134 
135 	seq_printf(m, "%-20s\t%d\n", "channels", i);
136 
137 	i = 0;
138 	down_read(&sess->tree_conns_lock);
139 	xa_for_each(&sess->tree_conns, id, tree_conn) {
140 		share_conf = tree_conn->share_conf;
141 		seq_printf(m, "%-20s\t%s\t%8d", "share",
142 			   share_conf->name, tree_conn->id);
143 		if (test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_PIPE))
144 			seq_printf(m, " %s ", "pipe");
145 		else
146 			seq_printf(m, " %s ", "disk");
147 		seq_putc(m, '\n');
148 	}
149 	up_read(&sess->tree_conns_lock);
150 
151 	ksmbd_user_session_put(sess);
152 	return 0;
153 }
154 
155 void ksmbd_proc_show_flag_names(struct seq_file *m,
156 				const struct ksmbd_const_name *table,
157 				int count,
158 				unsigned int flags)
159 {
160 	int i;
161 
162 	for (i = 0; i < count; i++) {
163 		if (table[i].const_value & flags)
164 			seq_printf(m, "0x%08x\t", table[i].const_value);
165 	}
166 	seq_putc(m, '\n');
167 }
168 
169 void ksmbd_proc_show_const_name(struct seq_file *m,
170 				const char *format,
171 				const struct ksmbd_const_name *table,
172 				int count,
173 				unsigned int const_value)
174 {
175 	int i;
176 
177 	for (i = 0; i < count; i++) {
178 		if (table[i].const_value & const_value)
179 			seq_printf(m, format, table[i].name);
180 	}
181 	seq_putc(m, '\n');
182 }
183 
184 static int create_proc_session(struct ksmbd_session *sess)
185 {
186 	char name[30];
187 
188 	snprintf(name, sizeof(name), "sessions/%llu", sess->id);
189 	sess->proc_entry = ksmbd_proc_create(name,
190 					     show_proc_session, sess);
191 	return 0;
192 }
193 
194 static void delete_proc_session(struct ksmbd_session *sess)
195 {
196 	if (sess->proc_entry)
197 		proc_remove(sess->proc_entry);
198 }
199 
200 static int show_proc_sessions(struct seq_file *m, void *v)
201 {
202 	struct ksmbd_session *session;
203 	struct channel *chan;
204 	int i;
205 	unsigned long id;
206 
207 	seq_printf(m, "#%-40s %-15s %-10s %-10s\n",
208 		   "<client>", "<user>", "<sess_id>", "<state>");
209 
210 	down_read(&sessions_table_lock);
211 	hash_for_each(sessions_table, i, session, hlist) {
212 		down_read(&session->chann_lock);
213 		xa_for_each(&session->ksmbd_chann_list, id, chan) {
214 			down_read(&chan->conn->session_lock);
215 			ksmbd_user_session_get(session);
216 
217 #if IS_ENABLED(CONFIG_IPV6)
218 			if (!chan->conn->inet_addr)
219 				seq_printf(m, " %-40pI6c", &chan->conn->inet6_addr);
220 			else
221 #endif
222 				seq_printf(m, " %-40pI4", &chan->conn->inet_addr);
223 			seq_printf(m, " %-15s %-10llu %-10s\n",
224 				   session_user_name(session),
225 				   session->id,
226 				   session_state_string(session));
227 
228 			ksmbd_user_session_put(session);
229 			up_read(&chan->conn->session_lock);
230 		}
231 		up_read(&session->chann_lock);
232 	}
233 	up_read(&sessions_table_lock);
234 	return 0;
235 }
236 
237 int create_proc_sessions(void)
238 {
239 	if (!ksmbd_proc_create("sessions/sessions",
240 			       show_proc_sessions, NULL))
241 		return -ENOMEM;
242 	return 0;
243 }
244 #else
245 int create_proc_sessions(void) { return 0; }
246 static int create_proc_session(struct ksmbd_session *sess) { return 0; }
247 static void delete_proc_session(struct ksmbd_session *sess) {}
248 #endif
249 
250 static void free_channel_list(struct ksmbd_session *sess)
251 {
252 	struct channel *chann;
253 	unsigned long index;
254 
255 	down_write(&sess->chann_lock);
256 	xa_for_each(&sess->ksmbd_chann_list, index, chann) {
257 		xa_erase(&sess->ksmbd_chann_list, index);
258 		kfree(chann);
259 	}
260 
261 	xa_destroy(&sess->ksmbd_chann_list);
262 	up_write(&sess->chann_lock);
263 }
264 
265 static void __session_rpc_close(struct ksmbd_session *sess,
266 				struct ksmbd_session_rpc *entry)
267 {
268 	struct ksmbd_rpc_command *resp;
269 
270 	resp = ksmbd_rpc_close(sess, entry->id);
271 	if (!resp)
272 		pr_err("Unable to close RPC pipe %d\n", entry->id);
273 
274 	kvfree(resp);
275 	ksmbd_rpc_id_free(entry->id);
276 	kfree(entry);
277 }
278 
279 static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
280 {
281 	struct ksmbd_session_rpc *entry;
282 	long index;
283 
284 	down_write(&sess->rpc_lock);
285 	xa_for_each(&sess->rpc_handle_list, index, entry) {
286 		xa_erase(&sess->rpc_handle_list, index);
287 		__session_rpc_close(sess, entry);
288 	}
289 	up_write(&sess->rpc_lock);
290 
291 	xa_destroy(&sess->rpc_handle_list);
292 }
293 
294 static int __rpc_method(char *rpc_name)
295 {
296 	if (!strcmp(rpc_name, "\\srvsvc") || !strcmp(rpc_name, "srvsvc"))
297 		return KSMBD_RPC_SRVSVC_METHOD_INVOKE;
298 
299 	if (!strcmp(rpc_name, "\\wkssvc") || !strcmp(rpc_name, "wkssvc"))
300 		return KSMBD_RPC_WKSSVC_METHOD_INVOKE;
301 
302 	if (!strcmp(rpc_name, "LANMAN") || !strcmp(rpc_name, "lanman"))
303 		return KSMBD_RPC_RAP_METHOD;
304 
305 	if (!strcmp(rpc_name, "\\samr") || !strcmp(rpc_name, "samr"))
306 		return KSMBD_RPC_SAMR_METHOD_INVOKE;
307 
308 	if (!strcmp(rpc_name, "\\lsarpc") || !strcmp(rpc_name, "lsarpc"))
309 		return KSMBD_RPC_LSARPC_METHOD_INVOKE;
310 
311 	pr_err("Unsupported RPC: %s\n", rpc_name);
312 	return 0;
313 }
314 
315 int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
316 {
317 	struct ksmbd_session_rpc *entry, *old;
318 	struct ksmbd_rpc_command *resp;
319 	int method, id;
320 
321 	method = __rpc_method(rpc_name);
322 	if (!method)
323 		return -EINVAL;
324 
325 	entry = kzalloc_obj(struct ksmbd_session_rpc, KSMBD_DEFAULT_GFP);
326 	if (!entry)
327 		return -ENOMEM;
328 
329 	entry->method = method;
330 	entry->id = id = ksmbd_ipc_id_alloc();
331 	if (id < 0)
332 		goto free_entry;
333 
334 	down_write(&sess->rpc_lock);
335 	old = xa_store(&sess->rpc_handle_list, id, entry, KSMBD_DEFAULT_GFP);
336 	if (xa_is_err(old)) {
337 		up_write(&sess->rpc_lock);
338 		goto free_id;
339 	}
340 
341 	resp = ksmbd_rpc_open(sess, id);
342 	if (!resp) {
343 		xa_erase(&sess->rpc_handle_list, entry->id);
344 		up_write(&sess->rpc_lock);
345 		goto free_id;
346 	}
347 
348 	up_write(&sess->rpc_lock);
349 	kvfree(resp);
350 	return id;
351 free_id:
352 	ksmbd_rpc_id_free(entry->id);
353 free_entry:
354 	kfree(entry);
355 	return -EINVAL;
356 }
357 
358 void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
359 {
360 	struct ksmbd_session_rpc *entry;
361 
362 	down_write(&sess->rpc_lock);
363 	entry = xa_erase(&sess->rpc_handle_list, id);
364 	if (entry)
365 		__session_rpc_close(sess, entry);
366 	up_write(&sess->rpc_lock);
367 }
368 
369 int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
370 {
371 	struct ksmbd_session_rpc *entry;
372 
373 	lockdep_assert_held(&sess->rpc_lock);
374 	entry = xa_load(&sess->rpc_handle_list, id);
375 
376 	return entry ? entry->method : 0;
377 }
378 
379 void ksmbd_session_destroy(struct ksmbd_session *sess)
380 {
381 	if (!sess)
382 		return;
383 
384 	delete_proc_session(sess);
385 	ksmbd_tree_conn_session_logoff(sess);
386 	ksmbd_destroy_file_table(sess);
387 	if (sess->user)
388 		ksmbd_free_user(sess->user);
389 	ksmbd_launch_ksmbd_durable_scavenger();
390 	ksmbd_session_rpc_clear_list(sess);
391 	free_channel_list(sess);
392 	kfree(sess->Preauth_HashValue);
393 	ksmbd_release_id(&session_ida, sess->id);
394 	ida_destroy(&sess->tree_conn_ida);
395 	kfree(sess);
396 }
397 
398 struct ksmbd_session *__session_lookup(unsigned long long id)
399 {
400 	struct ksmbd_session *sess;
401 
402 	hash_for_each_possible(sessions_table, sess, hlist, id) {
403 		if (id == sess->id) {
404 			sess->last_active = jiffies;
405 			return sess;
406 		}
407 	}
408 	return NULL;
409 }
410 
411 static void ksmbd_expire_session(struct ksmbd_conn *conn)
412 {
413 	unsigned long id;
414 	struct ksmbd_session *sess;
415 
416 	down_write(&sessions_table_lock);
417 	down_write(&conn->session_lock);
418 	xa_for_each(&conn->sessions, id, sess) {
419 		if (atomic_read(&sess->refcnt) <= 1 &&
420 		    (sess->state != SMB2_SESSION_VALID ||
421 		     time_after(jiffies,
422 			       sess->last_active + SMB2_SESSION_TIMEOUT))) {
423 			xa_erase(&conn->sessions, sess->id);
424 			hash_del(&sess->hlist);
425 			ksmbd_session_destroy(sess);
426 			continue;
427 		}
428 	}
429 	up_write(&conn->session_lock);
430 	up_write(&sessions_table_lock);
431 }
432 
433 int ksmbd_session_register(struct ksmbd_conn *conn,
434 			   struct ksmbd_session *sess)
435 {
436 	sess->dialect = conn->dialect;
437 	memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
438 	ksmbd_expire_session(conn);
439 	return xa_err(xa_store(&conn->sessions, sess->id, sess, KSMBD_DEFAULT_GFP));
440 }
441 
442 static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
443 {
444 	struct channel *chann;
445 
446 	down_write(&sess->chann_lock);
447 	chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
448 	up_write(&sess->chann_lock);
449 	if (!chann)
450 		return -ENOENT;
451 
452 	kfree(chann);
453 	return 0;
454 }
455 
456 void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
457 {
458 	struct ksmbd_session *sess;
459 	unsigned long id;
460 
461 	down_write(&sessions_table_lock);
462 	if (conn->binding) {
463 		int bkt;
464 		struct hlist_node *tmp;
465 
466 		hash_for_each_safe(sessions_table, bkt, tmp, sess, hlist) {
467 			if (!ksmbd_chann_del(conn, sess) &&
468 			    xa_empty(&sess->ksmbd_chann_list)) {
469 				hash_del(&sess->hlist);
470 				down_write(&conn->session_lock);
471 				xa_erase(&conn->sessions, sess->id);
472 				up_write(&conn->session_lock);
473 				if (atomic_dec_and_test(&sess->refcnt))
474 					ksmbd_session_destroy(sess);
475 			}
476 		}
477 	}
478 
479 	down_write(&conn->session_lock);
480 	xa_for_each(&conn->sessions, id, sess) {
481 		unsigned long chann_id;
482 		struct channel *chann;
483 
484 		xa_for_each(&sess->ksmbd_chann_list, chann_id, chann) {
485 			if (chann->conn != conn)
486 				ksmbd_conn_set_exiting(chann->conn);
487 		}
488 
489 		ksmbd_chann_del(conn, sess);
490 		if (xa_empty(&sess->ksmbd_chann_list)) {
491 			xa_erase(&conn->sessions, sess->id);
492 			hash_del(&sess->hlist);
493 			if (atomic_dec_and_test(&sess->refcnt))
494 				ksmbd_session_destroy(sess);
495 		}
496 	}
497 	up_write(&conn->session_lock);
498 	up_write(&sessions_table_lock);
499 }
500 
501 bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn,
502 				   unsigned long long id)
503 {
504 	struct ksmbd_session *sess;
505 
506 	down_read(&conn->session_lock);
507 	sess = xa_load(&conn->sessions, id);
508 	if (sess) {
509 		up_read(&conn->session_lock);
510 		return true;
511 	}
512 	up_read(&conn->session_lock);
513 
514 	return false;
515 }
516 
517 struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
518 					   unsigned long long id)
519 {
520 	struct ksmbd_session *sess;
521 
522 	down_read(&conn->session_lock);
523 	sess = xa_load(&conn->sessions, id);
524 	if (sess) {
525 		sess->last_active = jiffies;
526 		ksmbd_user_session_get(sess);
527 	}
528 	up_read(&conn->session_lock);
529 	return sess;
530 }
531 
532 struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
533 {
534 	struct ksmbd_session *sess;
535 
536 	down_read(&sessions_table_lock);
537 	sess = __session_lookup(id);
538 	if (sess)
539 		ksmbd_user_session_get(sess);
540 	up_read(&sessions_table_lock);
541 
542 	return sess;
543 }
544 
545 struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
546 					       unsigned long long id)
547 {
548 	struct ksmbd_session *sess;
549 
550 	sess = ksmbd_session_lookup(conn, id);
551 	if (!sess && conn->binding) {
552 		sess = ksmbd_session_lookup_slowpath(id);
553 		if (sess && !xa_load(&sess->ksmbd_chann_list, (long)conn)) {
554 			ksmbd_user_session_put(sess);
555 			sess = NULL;
556 		}
557 	}
558 	if (sess && sess->state != SMB2_SESSION_VALID) {
559 		ksmbd_user_session_put(sess);
560 		sess = NULL;
561 	}
562 	return sess;
563 }
564 
565 void ksmbd_user_session_get(struct ksmbd_session *sess)
566 {
567 	atomic_inc(&sess->refcnt);
568 }
569 
570 void ksmbd_user_session_put(struct ksmbd_session *sess)
571 {
572 	if (!sess)
573 		return;
574 
575 	if (atomic_read(&sess->refcnt) <= 0)
576 		WARN_ON(1);
577 	else if (atomic_dec_and_test(&sess->refcnt))
578 		ksmbd_session_destroy(sess);
579 }
580 
581 struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
582 						    u64 sess_id)
583 {
584 	struct preauth_session *sess;
585 
586 	sess = kmalloc_obj(struct preauth_session, KSMBD_DEFAULT_GFP);
587 	if (!sess)
588 		return NULL;
589 
590 	sess->id = sess_id;
591 	memcpy(sess->Preauth_HashValue, conn->preauth_info->Preauth_HashValue,
592 	       PREAUTH_HASHVALUE_SIZE);
593 	list_add(&sess->preauth_entry, &conn->preauth_sess_table);
594 
595 	return sess;
596 }
597 
598 void destroy_previous_session(struct ksmbd_conn *conn,
599 			      struct ksmbd_user *user, u64 id)
600 {
601 	struct ksmbd_session *prev_sess;
602 	struct ksmbd_user *prev_user;
603 	int err;
604 
605 	down_write(&sessions_table_lock);
606 	down_write(&conn->session_lock);
607 	prev_sess = __session_lookup(id);
608 	if (!prev_sess || prev_sess->state == SMB2_SESSION_EXPIRED)
609 		goto out;
610 
611 	prev_user = prev_sess->user;
612 	if (!prev_user ||
613 	    strcmp(user->name, prev_user->name) ||
614 	    user->passkey_sz != prev_user->passkey_sz ||
615 	    memcmp(user->passkey, prev_user->passkey, user->passkey_sz))
616 		goto out;
617 
618 	ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT);
619 	err = ksmbd_conn_wait_idle_sess_id(conn, id);
620 	if (err) {
621 		ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
622 		goto out;
623 	}
624 
625 	ksmbd_destroy_file_table(prev_sess);
626 	prev_sess->state = SMB2_SESSION_EXPIRED;
627 	ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
628 	ksmbd_launch_ksmbd_durable_scavenger();
629 out:
630 	up_write(&conn->session_lock);
631 	up_write(&sessions_table_lock);
632 }
633 
634 static bool ksmbd_preauth_session_id_match(struct preauth_session *sess,
635 					   unsigned long long id)
636 {
637 	return sess->id == id;
638 }
639 
640 struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn,
641 						     unsigned long long id)
642 {
643 	struct preauth_session *sess = NULL;
644 
645 	list_for_each_entry(sess, &conn->preauth_sess_table, preauth_entry) {
646 		if (ksmbd_preauth_session_id_match(sess, id))
647 			return sess;
648 	}
649 	return NULL;
650 }
651 
652 static int __init_smb2_session(struct ksmbd_session *sess)
653 {
654 	int id = ksmbd_acquire_smb2_uid(&session_ida);
655 
656 	if (id < 0)
657 		return -EINVAL;
658 	sess->id = id;
659 	return 0;
660 }
661 
662 static struct ksmbd_session *__session_create(int protocol)
663 {
664 	struct ksmbd_session *sess;
665 	int ret;
666 
667 	if (protocol != CIFDS_SESSION_FLAG_SMB2)
668 		return NULL;
669 
670 	sess = kzalloc_obj(struct ksmbd_session, KSMBD_DEFAULT_GFP);
671 	if (!sess)
672 		return NULL;
673 
674 	ida_init(&sess->tree_conn_ida);
675 
676 	if (ksmbd_init_file_table(&sess->file_table))
677 		goto error;
678 
679 	sess->last_active = jiffies;
680 	sess->state = SMB2_SESSION_IN_PROGRESS;
681 	set_session_flag(sess, protocol);
682 	xa_init(&sess->tree_conns);
683 	xa_init(&sess->ksmbd_chann_list);
684 	xa_init(&sess->rpc_handle_list);
685 	sess->sequence_number = 1;
686 	atomic_set(&sess->refcnt, 2);
687 	init_rwsem(&sess->tree_conns_lock);
688 	init_rwsem(&sess->rpc_lock);
689 	init_rwsem(&sess->chann_lock);
690 
691 	ret = __init_smb2_session(sess);
692 	if (ret)
693 		goto error;
694 
695 	down_write(&sessions_table_lock);
696 	hash_add(sessions_table, &sess->hlist, sess->id);
697 	up_write(&sessions_table_lock);
698 
699 	create_proc_session(sess);
700 	ksmbd_counter_inc(KSMBD_COUNTER_SESSIONS);
701 	return sess;
702 
703 error:
704 	ksmbd_session_destroy(sess);
705 	return NULL;
706 }
707 
708 struct ksmbd_session *ksmbd_smb2_session_create(void)
709 {
710 	return __session_create(CIFDS_SESSION_FLAG_SMB2);
711 }
712 
713 int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess)
714 {
715 	int id = -EINVAL;
716 
717 	if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
718 		id = ksmbd_acquire_smb2_tid(&sess->tree_conn_ida);
719 
720 	return id;
721 }
722 
723 void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id)
724 {
725 	if (id >= 0)
726 		ksmbd_release_id(&sess->tree_conn_ida, id);
727 }
728