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_sensitive(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_sensitive(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 struct hlist_node *tmp; 461 int bkt; 462 463 down_write(&sessions_table_lock); 464 hash_for_each_safe(sessions_table, bkt, tmp, sess, hlist) { 465 if (!ksmbd_chann_del(conn, sess) && 466 xa_empty(&sess->ksmbd_chann_list)) { 467 hash_del(&sess->hlist); 468 down_write(&conn->session_lock); 469 xa_erase(&conn->sessions, sess->id); 470 up_write(&conn->session_lock); 471 if (atomic_dec_and_test(&sess->refcnt)) 472 ksmbd_session_destroy(sess); 473 } 474 } 475 476 down_write(&conn->session_lock); 477 xa_for_each(&conn->sessions, id, sess) { 478 unsigned long chann_id; 479 struct channel *chann; 480 481 xa_for_each(&sess->ksmbd_chann_list, chann_id, chann) { 482 if (chann->conn != conn) 483 ksmbd_conn_set_exiting(chann->conn); 484 } 485 486 ksmbd_chann_del(conn, sess); 487 if (xa_empty(&sess->ksmbd_chann_list)) { 488 xa_erase(&conn->sessions, sess->id); 489 hash_del(&sess->hlist); 490 if (atomic_dec_and_test(&sess->refcnt)) 491 ksmbd_session_destroy(sess); 492 } 493 } 494 up_write(&conn->session_lock); 495 up_write(&sessions_table_lock); 496 } 497 498 bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn, 499 unsigned long long id) 500 { 501 struct ksmbd_session *sess; 502 503 down_read(&conn->session_lock); 504 sess = xa_load(&conn->sessions, id); 505 if (sess) { 506 up_read(&conn->session_lock); 507 return true; 508 } 509 up_read(&conn->session_lock); 510 511 return false; 512 } 513 514 struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, 515 unsigned long long id) 516 { 517 struct ksmbd_session *sess; 518 519 down_read(&conn->session_lock); 520 sess = xa_load(&conn->sessions, id); 521 if (sess) { 522 sess->last_active = jiffies; 523 ksmbd_user_session_get(sess); 524 } 525 up_read(&conn->session_lock); 526 return sess; 527 } 528 529 struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id) 530 { 531 struct ksmbd_session *sess; 532 533 down_read(&sessions_table_lock); 534 sess = __session_lookup(id); 535 if (sess) 536 ksmbd_user_session_get(sess); 537 up_read(&sessions_table_lock); 538 539 return sess; 540 } 541 542 struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn, 543 unsigned long long id) 544 { 545 struct ksmbd_session *sess; 546 547 sess = ksmbd_session_lookup(conn, id); 548 if (!sess && conn->binding) { 549 sess = ksmbd_session_lookup_slowpath(id); 550 if (sess && !xa_load(&sess->ksmbd_chann_list, (long)conn)) { 551 ksmbd_user_session_put(sess); 552 sess = NULL; 553 } 554 } 555 if (sess && sess->state != SMB2_SESSION_VALID) { 556 ksmbd_user_session_put(sess); 557 sess = NULL; 558 } 559 return sess; 560 } 561 562 void ksmbd_user_session_get(struct ksmbd_session *sess) 563 { 564 atomic_inc(&sess->refcnt); 565 } 566 567 void ksmbd_user_session_put(struct ksmbd_session *sess) 568 { 569 if (!sess) 570 return; 571 572 if (atomic_read(&sess->refcnt) <= 0) 573 WARN_ON(1); 574 else if (atomic_dec_and_test(&sess->refcnt)) 575 ksmbd_session_destroy(sess); 576 } 577 578 struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn, 579 u64 sess_id) 580 { 581 struct preauth_session *sess; 582 583 sess = kmalloc_obj(struct preauth_session, KSMBD_DEFAULT_GFP); 584 if (!sess) 585 return NULL; 586 587 sess->id = sess_id; 588 memcpy(sess->Preauth_HashValue, conn->preauth_info->Preauth_HashValue, 589 PREAUTH_HASHVALUE_SIZE); 590 list_add(&sess->preauth_entry, &conn->preauth_sess_table); 591 592 return sess; 593 } 594 595 void destroy_previous_session(struct ksmbd_conn *conn, 596 struct ksmbd_user *user, u64 id) 597 { 598 struct ksmbd_session *prev_sess; 599 struct ksmbd_user *prev_user; 600 int err; 601 602 down_write(&sessions_table_lock); 603 down_write(&conn->session_lock); 604 prev_sess = __session_lookup(id); 605 if (!prev_sess || prev_sess->state == SMB2_SESSION_EXPIRED) 606 goto out; 607 608 prev_user = prev_sess->user; 609 if (!prev_user || 610 strcmp(user->name, prev_user->name) || 611 user->passkey_sz != prev_user->passkey_sz || 612 memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) 613 goto out; 614 615 ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT); 616 err = ksmbd_conn_wait_idle_sess_id(conn, id); 617 if (err) { 618 ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP); 619 goto out; 620 } 621 622 ksmbd_destroy_file_table(prev_sess); 623 prev_sess->state = SMB2_SESSION_EXPIRED; 624 ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP); 625 ksmbd_launch_ksmbd_durable_scavenger(); 626 out: 627 up_write(&conn->session_lock); 628 up_write(&sessions_table_lock); 629 } 630 631 static bool ksmbd_preauth_session_id_match(struct preauth_session *sess, 632 unsigned long long id) 633 { 634 return sess->id == id; 635 } 636 637 struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn, 638 unsigned long long id) 639 { 640 struct preauth_session *sess = NULL; 641 642 list_for_each_entry(sess, &conn->preauth_sess_table, preauth_entry) { 643 if (ksmbd_preauth_session_id_match(sess, id)) 644 return sess; 645 } 646 return NULL; 647 } 648 649 static int __init_smb2_session(struct ksmbd_session *sess) 650 { 651 int id = ksmbd_acquire_smb2_uid(&session_ida); 652 653 if (id < 0) 654 return -EINVAL; 655 sess->id = id; 656 return 0; 657 } 658 659 static struct ksmbd_session *__session_create(int protocol) 660 { 661 struct ksmbd_session *sess; 662 int ret; 663 664 if (protocol != CIFDS_SESSION_FLAG_SMB2) 665 return NULL; 666 667 sess = kzalloc_obj(struct ksmbd_session, KSMBD_DEFAULT_GFP); 668 if (!sess) 669 return NULL; 670 671 ida_init(&sess->tree_conn_ida); 672 673 if (ksmbd_init_file_table(&sess->file_table)) 674 goto error; 675 676 sess->last_active = jiffies; 677 sess->state = SMB2_SESSION_IN_PROGRESS; 678 set_session_flag(sess, protocol); 679 xa_init(&sess->tree_conns); 680 xa_init(&sess->ksmbd_chann_list); 681 xa_init(&sess->rpc_handle_list); 682 sess->sequence_number = 1; 683 atomic_set(&sess->refcnt, 2); 684 init_rwsem(&sess->tree_conns_lock); 685 init_rwsem(&sess->rpc_lock); 686 init_rwsem(&sess->chann_lock); 687 688 ret = __init_smb2_session(sess); 689 if (ret) 690 goto error; 691 692 down_write(&sessions_table_lock); 693 hash_add(sessions_table, &sess->hlist, sess->id); 694 up_write(&sessions_table_lock); 695 696 create_proc_session(sess); 697 ksmbd_counter_inc(KSMBD_COUNTER_SESSIONS); 698 return sess; 699 700 error: 701 ksmbd_session_destroy(sess); 702 return NULL; 703 } 704 705 struct ksmbd_session *ksmbd_smb2_session_create(void) 706 { 707 return __session_create(CIFDS_SESSION_FLAG_SMB2); 708 } 709 710 int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess) 711 { 712 int id = -EINVAL; 713 714 if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2)) 715 id = ksmbd_acquire_smb2_tid(&sess->tree_conn_ida); 716 717 return id; 718 } 719 720 void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id) 721 { 722 if (id >= 0) 723 ksmbd_release_id(&sess->tree_conn_ida, id); 724 } 725