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