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 const char *session_account_type(struct ksmbd_session *session) 82 { 83 if (user_guest(session->user)) 84 return "guest"; 85 if (ksmbd_anonymous_user(session->user)) 86 return "anonymous"; 87 return "user"; 88 } 89 90 static unsigned int session_open_file_count(struct ksmbd_session *session) 91 { 92 struct ksmbd_file *fp; 93 unsigned int count = 0; 94 unsigned int id; 95 96 read_lock(&session->file_table.lock); 97 idr_for_each_entry(session->file_table.idr, fp, id) 98 count++; 99 read_unlock(&session->file_table.lock); 100 return count; 101 } 102 103 static int show_proc_session(struct seq_file *m, void *v) 104 { 105 struct ksmbd_session *sess; 106 struct ksmbd_tree_connect *tree_conn; 107 struct ksmbd_share_config *share_conf; 108 struct channel *chan; 109 unsigned long id; 110 int i = 0; 111 112 sess = (struct ksmbd_session *)m->private; 113 ksmbd_user_session_get(sess); 114 115 seq_printf(m, "user:\t%s\n", session_user_name(sess)); 116 seq_printf(m, "account_type:\t%s\n", 117 session_account_type(sess)); 118 seq_printf(m, "id:\t%llu\n", sess->id); 119 seq_printf(m, "state:\t%s\n", session_state_string(sess)); 120 seq_printf(m, "dialect:\t0x%04x\n", sess->dialect); 121 seq_printf(m, "last_active_seconds:\t%lu\n", 122 jiffies_to_msecs(jiffies - sess->last_active) / MSEC_PER_SEC); 123 seq_printf(m, "open_files:\t%u\n", 124 session_open_file_count(sess)); 125 126 i = 0; 127 down_read(&sess->chann_lock); 128 xa_for_each(&sess->ksmbd_chann_list, id, chan) { 129 const char *name; 130 131 #if IS_ENABLED(CONFIG_IPV6) 132 if (chan->conn->inet_addr) 133 seq_printf(m, "client:\t%pI4\n", 134 &chan->conn->inet_addr); 135 else 136 seq_printf(m, "client:\t%pI6c\n", 137 &chan->conn->inet6_addr); 138 #else 139 seq_printf(m, "client:\t%pI4\n", 140 &chan->conn->inet_addr); 141 #endif 142 seq_puts(m, "capabilities:\t"); 143 ksmbd_proc_show_flag_names(m, 144 ksmbd_sess_cap_const_names, 145 ARRAY_SIZE(ksmbd_sess_cap_const_names), 146 chan->conn->vals->req_capabilities); 147 seq_putc(m, '\n'); 148 seq_printf(m, "posix_extensions:\t%s\n", 149 chan->conn->posix_ext_supported ? "yes" : "no"); 150 151 if (sess->sign) { 152 unsigned int algorithm = 153 le16_to_cpu(chan->conn->signing_algorithm); 154 155 name = ksmbd_proc_const_name(ksmbd_signing_const_names, 156 ARRAY_SIZE(ksmbd_signing_const_names), 157 algorithm); 158 if (name) 159 seq_printf(m, "signing:\t%s\n", name); 160 else 161 seq_printf(m, "signing:\t0x%04x\n", 162 algorithm); 163 } 164 if (sess->enc) { 165 unsigned int cipher = le16_to_cpu(chan->conn->cipher_type); 166 167 name = ksmbd_proc_const_name(ksmbd_cipher_const_names, 168 ARRAY_SIZE(ksmbd_cipher_const_names), 169 cipher); 170 if (name) 171 seq_printf(m, "encryption:\t%s\n", name); 172 else 173 seq_printf(m, "encryption:\t0x%04x\n", 174 cipher); 175 } 176 i++; 177 } 178 up_read(&sess->chann_lock); 179 180 seq_printf(m, "channels:\t%d\n", i); 181 182 i = 0; 183 down_read(&sess->tree_conns_lock); 184 xa_for_each(&sess->tree_conns, id, tree_conn) { 185 share_conf = tree_conn->share_conf; 186 seq_printf(m, "share:\t%s\n", share_conf->name); 187 seq_printf(m, "tree_id:\t%d\n", tree_conn->id); 188 seq_printf(m, "share_type:\t%s\n", 189 test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_PIPE) ? 190 "pipe" : "disk"); 191 i++; 192 } 193 up_read(&sess->tree_conns_lock); 194 seq_printf(m, "tree_connects:\t%d\n", i); 195 196 ksmbd_user_session_put(sess); 197 return 0; 198 } 199 200 static int create_proc_session(struct ksmbd_session *sess) 201 { 202 char name[30]; 203 204 snprintf(name, sizeof(name), "sessions/%llu", sess->id); 205 sess->proc_entry = ksmbd_proc_create(name, 206 show_proc_session, sess); 207 if (!sess->proc_entry) 208 return -ENOMEM; 209 return 0; 210 } 211 212 static void delete_proc_session(struct ksmbd_session *sess) 213 { 214 if (sess->proc_entry) 215 proc_remove(sess->proc_entry); 216 } 217 218 static int show_proc_sessions(struct seq_file *m, void *v) 219 { 220 struct ksmbd_session *session; 221 struct channel *chan; 222 int i; 223 unsigned long id; 224 225 down_read(&sessions_table_lock); 226 hash_for_each(sessions_table, i, session, hlist) { 227 down_read(&session->chann_lock); 228 xa_for_each(&session->ksmbd_chann_list, id, chan) { 229 down_read(&chan->conn->session_lock); 230 ksmbd_user_session_get(session); 231 232 #if IS_ENABLED(CONFIG_IPV6) 233 if (!chan->conn->inet_addr) 234 seq_printf(m, "client:\t%pI6c\n", &chan->conn->inet6_addr); 235 else 236 #endif 237 seq_printf(m, "client:\t%pI4\n", &chan->conn->inet_addr); 238 seq_printf(m, "user:\t%s\n", session_user_name(session)); 239 seq_printf(m, "id:\t%llu\n", session->id); 240 seq_printf(m, "state:\t%s\n\n", 241 session_state_string(session)); 242 243 ksmbd_user_session_put(session); 244 up_read(&chan->conn->session_lock); 245 } 246 up_read(&session->chann_lock); 247 } 248 up_read(&sessions_table_lock); 249 return 0; 250 } 251 252 int create_proc_sessions(void) 253 { 254 if (!ksmbd_proc_create("sessions/sessions", 255 show_proc_sessions, NULL)) 256 return -ENOMEM; 257 return 0; 258 } 259 #else 260 int create_proc_sessions(void) { return 0; } 261 static int create_proc_session(struct ksmbd_session *sess) { return 0; } 262 static void delete_proc_session(struct ksmbd_session *sess) {} 263 #endif 264 265 static void free_channel_list(struct ksmbd_session *sess) 266 { 267 struct channel *chann; 268 unsigned long index; 269 270 down_write(&sess->chann_lock); 271 xa_for_each(&sess->ksmbd_chann_list, index, chann) { 272 xa_erase(&sess->ksmbd_chann_list, index); 273 kfree_sensitive(chann); 274 } 275 276 xa_destroy(&sess->ksmbd_chann_list); 277 up_write(&sess->chann_lock); 278 } 279 280 static void __session_rpc_close(struct ksmbd_session *sess, 281 struct ksmbd_session_rpc *entry) 282 { 283 struct ksmbd_rpc_command *resp; 284 285 resp = ksmbd_rpc_close(sess, entry->id); 286 if (!resp) 287 pr_err("Unable to close RPC pipe %d\n", entry->id); 288 289 kvfree(resp); 290 ksmbd_rpc_id_free(entry->id); 291 kfree(entry); 292 } 293 294 static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess) 295 { 296 struct ksmbd_session_rpc *entry; 297 long index; 298 299 down_write(&sess->rpc_lock); 300 xa_for_each(&sess->rpc_handle_list, index, entry) { 301 xa_erase(&sess->rpc_handle_list, index); 302 __session_rpc_close(sess, entry); 303 } 304 up_write(&sess->rpc_lock); 305 306 xa_destroy(&sess->rpc_handle_list); 307 } 308 309 static int __rpc_method(char *rpc_name) 310 { 311 if (!strcmp(rpc_name, "\\srvsvc") || !strcmp(rpc_name, "srvsvc")) 312 return KSMBD_RPC_SRVSVC_METHOD_INVOKE; 313 314 if (!strcmp(rpc_name, "\\wkssvc") || !strcmp(rpc_name, "wkssvc")) 315 return KSMBD_RPC_WKSSVC_METHOD_INVOKE; 316 317 if (!strcmp(rpc_name, "LANMAN") || !strcmp(rpc_name, "lanman")) 318 return KSMBD_RPC_RAP_METHOD; 319 320 if (!strcmp(rpc_name, "\\samr") || !strcmp(rpc_name, "samr")) 321 return KSMBD_RPC_SAMR_METHOD_INVOKE; 322 323 if (!strcmp(rpc_name, "\\lsarpc") || !strcmp(rpc_name, "lsarpc")) 324 return KSMBD_RPC_LSARPC_METHOD_INVOKE; 325 326 if (!strcmp(rpc_name, "\\mdssvc") || !strcmp(rpc_name, "mdssvc")) 327 return -ENOENT; 328 329 pr_err("Unsupported RPC: %s\n", rpc_name); 330 return -ENOENT; 331 } 332 333 int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name) 334 { 335 struct ksmbd_session_rpc *entry, *old; 336 struct ksmbd_rpc_command *resp; 337 int method, id; 338 339 method = __rpc_method(rpc_name); 340 if (method < 0) 341 return method; 342 343 entry = kzalloc_obj(struct ksmbd_session_rpc, KSMBD_DEFAULT_GFP); 344 if (!entry) 345 return -ENOMEM; 346 347 entry->method = method; 348 entry->id = id = ksmbd_ipc_id_alloc(); 349 if (id < 0) 350 goto free_entry; 351 352 down_write(&sess->rpc_lock); 353 old = xa_store(&sess->rpc_handle_list, id, entry, KSMBD_DEFAULT_GFP); 354 if (xa_is_err(old)) { 355 up_write(&sess->rpc_lock); 356 goto free_id; 357 } 358 359 resp = ksmbd_rpc_open(sess, id); 360 if (!resp) { 361 xa_erase(&sess->rpc_handle_list, entry->id); 362 up_write(&sess->rpc_lock); 363 goto free_id; 364 } 365 366 up_write(&sess->rpc_lock); 367 kvfree(resp); 368 return id; 369 free_id: 370 ksmbd_rpc_id_free(entry->id); 371 free_entry: 372 kfree(entry); 373 return -EINVAL; 374 } 375 376 void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id) 377 { 378 struct ksmbd_session_rpc *entry; 379 380 down_write(&sess->rpc_lock); 381 entry = xa_erase(&sess->rpc_handle_list, id); 382 if (entry) 383 __session_rpc_close(sess, entry); 384 up_write(&sess->rpc_lock); 385 } 386 387 int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id) 388 { 389 struct ksmbd_session_rpc *entry; 390 391 lockdep_assert_held(&sess->rpc_lock); 392 entry = xa_load(&sess->rpc_handle_list, id); 393 394 return entry ? entry->method : 0; 395 } 396 397 void ksmbd_session_destroy(struct ksmbd_session *sess) 398 { 399 if (!sess) 400 return; 401 402 delete_proc_session(sess); 403 ksmbd_tree_conn_session_logoff(sess); 404 ksmbd_destroy_file_table(sess); 405 if (sess->user) 406 ksmbd_free_user(sess->user); 407 ksmbd_launch_ksmbd_durable_scavenger(); 408 ksmbd_session_rpc_clear_list(sess); 409 free_channel_list(sess); 410 kfree_sensitive(sess->Preauth_HashValue); 411 ksmbd_release_id(&session_ida, sess->id); 412 ida_destroy(&sess->tree_conn_ida); 413 kfree_sensitive(sess); 414 } 415 416 static void ksmbd_session_remove_from_table(struct ksmbd_session *sess) 417 { 418 hash_del(&sess->hlist); 419 ksmbd_counter_dec(KSMBD_COUNTER_SESSIONS); 420 } 421 422 struct ksmbd_session *__session_lookup(unsigned long long id) 423 { 424 struct ksmbd_session *sess; 425 426 hash_for_each_possible(sessions_table, sess, hlist, id) { 427 if (id == sess->id) { 428 sess->last_active = jiffies; 429 return sess; 430 } 431 } 432 return NULL; 433 } 434 435 static void ksmbd_expire_session(struct ksmbd_conn *conn) 436 { 437 unsigned long id; 438 struct ksmbd_session *sess; 439 440 down_write(&sessions_table_lock); 441 down_write(&conn->session_lock); 442 xa_for_each(&conn->sessions, id, sess) { 443 if (atomic_read(&sess->refcnt) <= 1 && 444 (sess->state != SMB2_SESSION_VALID || 445 time_after(jiffies, 446 sess->last_active + SMB2_SESSION_TIMEOUT))) { 447 xa_erase(&conn->sessions, sess->id); 448 ksmbd_session_remove_from_table(sess); 449 ksmbd_session_destroy(sess); 450 continue; 451 } 452 } 453 up_write(&conn->session_lock); 454 up_write(&sessions_table_lock); 455 } 456 457 int ksmbd_session_register(struct ksmbd_conn *conn, 458 struct ksmbd_session *sess) 459 { 460 int ret; 461 462 sess->dialect = conn->dialect; 463 memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); 464 ksmbd_expire_session(conn); 465 ret = xa_err(xa_store(&conn->sessions, sess->id, sess, 466 KSMBD_DEFAULT_GFP)); 467 if (ret) { 468 down_write(&sessions_table_lock); 469 ksmbd_session_remove_from_table(sess); 470 up_write(&sessions_table_lock); 471 ksmbd_user_session_put(sess); 472 } 473 474 return ret; 475 } 476 477 static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess) 478 { 479 struct channel *chann; 480 481 down_write(&sess->chann_lock); 482 chann = xa_erase(&sess->ksmbd_chann_list, (long)conn); 483 up_write(&sess->chann_lock); 484 if (!chann) 485 return -ENOENT; 486 487 kfree_sensitive(chann); 488 return 0; 489 } 490 491 void ksmbd_sessions_deregister(struct ksmbd_conn *conn) 492 { 493 struct ksmbd_session *sess; 494 unsigned long id; 495 struct hlist_node *tmp; 496 int bkt; 497 498 down_write(&sessions_table_lock); 499 hash_for_each_safe(sessions_table, bkt, tmp, sess, hlist) { 500 if (!ksmbd_chann_del(conn, sess) && 501 xa_empty(&sess->ksmbd_chann_list)) { 502 ksmbd_session_remove_from_table(sess); 503 down_write(&conn->session_lock); 504 xa_erase(&conn->sessions, sess->id); 505 up_write(&conn->session_lock); 506 if (atomic_dec_and_test(&sess->refcnt)) 507 ksmbd_session_destroy(sess); 508 } 509 } 510 511 down_write(&conn->session_lock); 512 xa_for_each(&conn->sessions, id, sess) { 513 ksmbd_chann_del(conn, sess); 514 if (xa_empty(&sess->ksmbd_chann_list)) { 515 xa_erase(&conn->sessions, sess->id); 516 ksmbd_session_remove_from_table(sess); 517 if (atomic_dec_and_test(&sess->refcnt)) 518 ksmbd_session_destroy(sess); 519 } 520 } 521 up_write(&conn->session_lock); 522 up_write(&sessions_table_lock); 523 } 524 525 bool is_ksmbd_session_in_connection(struct ksmbd_conn *conn, 526 unsigned long long id) 527 { 528 struct ksmbd_session *sess; 529 530 down_read(&conn->session_lock); 531 sess = xa_load(&conn->sessions, id); 532 if (sess) { 533 up_read(&conn->session_lock); 534 return true; 535 } 536 up_read(&conn->session_lock); 537 538 return false; 539 } 540 541 struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, 542 unsigned long long id) 543 { 544 struct ksmbd_session *sess; 545 546 down_read(&conn->session_lock); 547 sess = xa_load(&conn->sessions, id); 548 if (sess) { 549 sess->last_active = jiffies; 550 ksmbd_user_session_get(sess); 551 } 552 up_read(&conn->session_lock); 553 return sess; 554 } 555 556 struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id) 557 { 558 struct ksmbd_session *sess; 559 560 down_read(&sessions_table_lock); 561 sess = __session_lookup(id); 562 if (sess) 563 ksmbd_user_session_get(sess); 564 up_read(&sessions_table_lock); 565 566 return sess; 567 } 568 569 struct ksmbd_session *ksmbd_session_lookup_all_states(struct ksmbd_conn *conn, 570 unsigned long long id) 571 { 572 struct ksmbd_session *sess; 573 bool channel_found; 574 575 sess = ksmbd_session_lookup(conn, id); 576 if (!sess) { 577 sess = ksmbd_session_lookup_slowpath(id); 578 if (!sess) 579 return NULL; 580 581 down_read(&sess->chann_lock); 582 channel_found = xa_load(&sess->ksmbd_chann_list, (long)conn); 583 up_read(&sess->chann_lock); 584 if (!channel_found) { 585 ksmbd_user_session_put(sess); 586 sess = NULL; 587 } 588 } 589 return sess; 590 } 591 592 struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn, 593 unsigned long long id) 594 { 595 struct ksmbd_session *sess; 596 597 sess = ksmbd_session_lookup_all_states(conn, id); 598 if (sess && sess->state != SMB2_SESSION_VALID) { 599 ksmbd_user_session_put(sess); 600 sess = NULL; 601 } 602 return sess; 603 } 604 605 void ksmbd_user_session_get(struct ksmbd_session *sess) 606 { 607 atomic_inc(&sess->refcnt); 608 } 609 610 void ksmbd_user_session_put(struct ksmbd_session *sess) 611 { 612 if (!sess) 613 return; 614 615 if (atomic_read(&sess->refcnt) <= 0) 616 WARN_ON(1); 617 else if (atomic_dec_and_test(&sess->refcnt)) 618 ksmbd_session_destroy(sess); 619 } 620 621 struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn, 622 u64 sess_id) 623 { 624 struct preauth_session *sess; 625 626 sess = kmalloc_obj(struct preauth_session, KSMBD_DEFAULT_GFP); 627 if (!sess) 628 return NULL; 629 630 sess->id = sess_id; 631 memcpy(sess->Preauth_HashValue, conn->preauth_info->Preauth_HashValue, 632 PREAUTH_HASHVALUE_SIZE); 633 list_add(&sess->preauth_entry, &conn->preauth_sess_table); 634 635 return sess; 636 } 637 638 void ksmbd_preauth_session_destroy(struct ksmbd_conn *conn) 639 { 640 struct preauth_session *sess, *tmp; 641 642 list_for_each_entry_safe(sess, tmp, &conn->preauth_sess_table, 643 preauth_entry) { 644 list_del(&sess->preauth_entry); 645 kfree(sess); 646 } 647 } 648 649 void destroy_previous_session(struct ksmbd_conn *conn, 650 struct ksmbd_user *user, u64 id) 651 { 652 struct ksmbd_session *prev_sess; 653 struct ksmbd_user *prev_user; 654 int err; 655 656 down_write(&sessions_table_lock); 657 down_write(&conn->session_lock); 658 prev_sess = __session_lookup(id); 659 if (!prev_sess || prev_sess->state == SMB2_SESSION_EXPIRED) 660 goto out; 661 662 prev_user = prev_sess->user; 663 if (!prev_user || 664 strcmp(user->name, prev_user->name) || 665 user->passkey_sz != prev_user->passkey_sz || 666 memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) 667 goto out; 668 669 down_write(&prev_sess->chann_lock); 670 if (prev_sess->tearing_down) { 671 up_write(&prev_sess->chann_lock); 672 goto out; 673 } 674 prev_sess->tearing_down = true; 675 up_write(&prev_sess->chann_lock); 676 677 ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_RECONNECT); 678 err = ksmbd_conn_wait_idle_sess(conn, prev_sess); 679 if (err) { 680 down_write(&prev_sess->chann_lock); 681 prev_sess->tearing_down = false; 682 up_write(&prev_sess->chann_lock); 683 ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_GOOD); 684 goto out; 685 } 686 687 ksmbd_destroy_file_table(prev_sess); 688 prev_sess->kerberos_expiry = 0; 689 prev_sess->state = SMB2_SESSION_EXPIRED; 690 ksmbd_all_conn_set_status(prev_sess, KSMBD_SESS_NEED_SETUP); 691 ksmbd_launch_ksmbd_durable_scavenger(); 692 out: 693 up_write(&conn->session_lock); 694 up_write(&sessions_table_lock); 695 } 696 697 static bool ksmbd_preauth_session_id_match(struct preauth_session *sess, 698 unsigned long long id) 699 { 700 return sess->id == id; 701 } 702 703 struct preauth_session *ksmbd_preauth_session_lookup(struct ksmbd_conn *conn, 704 unsigned long long id) 705 { 706 struct preauth_session *sess = NULL; 707 708 list_for_each_entry(sess, &conn->preauth_sess_table, preauth_entry) { 709 if (ksmbd_preauth_session_id_match(sess, id)) 710 return sess; 711 } 712 return NULL; 713 } 714 715 static int __init_smb2_session(struct ksmbd_session *sess) 716 { 717 int id = ksmbd_acquire_smb2_uid(&session_ida); 718 719 if (id < 0) 720 return -EINVAL; 721 sess->id = id; 722 return 0; 723 } 724 725 static struct ksmbd_session *__session_create(int protocol) 726 { 727 struct ksmbd_session *sess; 728 int ret; 729 730 if (protocol != CIFDS_SESSION_FLAG_SMB2) 731 return NULL; 732 733 sess = kzalloc_obj(struct ksmbd_session, KSMBD_DEFAULT_GFP); 734 if (!sess) 735 return NULL; 736 737 ida_init(&sess->tree_conn_ida); 738 739 if (ksmbd_init_file_table(&sess->file_table)) 740 goto error; 741 742 sess->last_active = jiffies; 743 sess->state = SMB2_SESSION_IN_PROGRESS; 744 set_session_flag(sess, protocol); 745 xa_init(&sess->tree_conns); 746 xa_init(&sess->ksmbd_chann_list); 747 xa_init(&sess->rpc_handle_list); 748 sess->sequence_number = 1; 749 atomic_set(&sess->refcnt, 2); 750 init_rwsem(&sess->tree_conns_lock); 751 init_rwsem(&sess->rpc_lock); 752 init_rwsem(&sess->chann_lock); 753 754 ret = __init_smb2_session(sess); 755 if (ret) 756 goto error; 757 758 down_write(&sessions_table_lock); 759 hash_add(sessions_table, &sess->hlist, sess->id); 760 ksmbd_counter_inc(KSMBD_COUNTER_SESSIONS); 761 up_write(&sessions_table_lock); 762 763 if (create_proc_session(sess)) 764 pr_warn_ratelimited("Unable to create session %llu procfs entry\n", sess->id); 765 return sess; 766 767 error: 768 ksmbd_session_destroy(sess); 769 return NULL; 770 } 771 772 struct ksmbd_session *ksmbd_smb2_session_create(void) 773 { 774 return __session_create(CIFDS_SESSION_FLAG_SMB2); 775 } 776 777 int ksmbd_acquire_tree_conn_id(struct ksmbd_session *sess) 778 { 779 int id = -EINVAL; 780 781 if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2)) 782 id = ksmbd_acquire_smb2_tid(&sess->tree_conn_ida); 783 784 return id; 785 } 786 787 void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id) 788 { 789 if (id >= 0) 790 ksmbd_release_id(&sess->tree_conn_ida, id); 791 } 792