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