server.c (14244B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org> 4 * Copyright (C) 2018 Samsung Electronics Co., Ltd. 5 */ 6 7#include "glob.h" 8#include "oplock.h" 9#include "misc.h" 10#include <linux/sched/signal.h> 11#include <linux/workqueue.h> 12#include <linux/sysfs.h> 13#include <linux/module.h> 14#include <linux/moduleparam.h> 15 16#include "server.h" 17#include "smb_common.h" 18#include "smbstatus.h" 19#include "connection.h" 20#include "transport_ipc.h" 21#include "mgmt/user_session.h" 22#include "crypto_ctx.h" 23#include "auth.h" 24 25int ksmbd_debug_types; 26 27struct ksmbd_server_config server_conf; 28 29enum SERVER_CTRL_TYPE { 30 SERVER_CTRL_TYPE_INIT, 31 SERVER_CTRL_TYPE_RESET, 32}; 33 34struct server_ctrl_struct { 35 int type; 36 struct work_struct ctrl_work; 37}; 38 39static DEFINE_MUTEX(ctrl_lock); 40 41static int ___server_conf_set(int idx, char *val) 42{ 43 if (idx >= ARRAY_SIZE(server_conf.conf)) 44 return -EINVAL; 45 46 if (!val || val[0] == 0x00) 47 return -EINVAL; 48 49 kfree(server_conf.conf[idx]); 50 server_conf.conf[idx] = kstrdup(val, GFP_KERNEL); 51 if (!server_conf.conf[idx]) 52 return -ENOMEM; 53 return 0; 54} 55 56int ksmbd_set_netbios_name(char *v) 57{ 58 return ___server_conf_set(SERVER_CONF_NETBIOS_NAME, v); 59} 60 61int ksmbd_set_server_string(char *v) 62{ 63 return ___server_conf_set(SERVER_CONF_SERVER_STRING, v); 64} 65 66int ksmbd_set_work_group(char *v) 67{ 68 return ___server_conf_set(SERVER_CONF_WORK_GROUP, v); 69} 70 71char *ksmbd_netbios_name(void) 72{ 73 return server_conf.conf[SERVER_CONF_NETBIOS_NAME]; 74} 75 76char *ksmbd_server_string(void) 77{ 78 return server_conf.conf[SERVER_CONF_SERVER_STRING]; 79} 80 81char *ksmbd_work_group(void) 82{ 83 return server_conf.conf[SERVER_CONF_WORK_GROUP]; 84} 85 86/** 87 * check_conn_state() - check state of server thread connection 88 * @work: smb work containing server thread information 89 * 90 * Return: 0 on valid connection, otherwise 1 to reconnect 91 */ 92static inline int check_conn_state(struct ksmbd_work *work) 93{ 94 struct smb_hdr *rsp_hdr; 95 96 if (ksmbd_conn_exiting(work) || ksmbd_conn_need_reconnect(work)) { 97 rsp_hdr = work->response_buf; 98 rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED; 99 return 1; 100 } 101 return 0; 102} 103 104#define SERVER_HANDLER_CONTINUE 0 105#define SERVER_HANDLER_ABORT 1 106 107static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn, 108 u16 *cmd) 109{ 110 struct smb_version_cmds *cmds; 111 u16 command; 112 int ret; 113 114 if (check_conn_state(work)) 115 return SERVER_HANDLER_CONTINUE; 116 117 if (ksmbd_verify_smb_message(work)) 118 return SERVER_HANDLER_ABORT; 119 120 command = conn->ops->get_cmd_val(work); 121 *cmd = command; 122 123andx_again: 124 if (command >= conn->max_cmds) { 125 conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER); 126 return SERVER_HANDLER_CONTINUE; 127 } 128 129 cmds = &conn->cmds[command]; 130 if (!cmds->proc) { 131 ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command); 132 conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED); 133 return SERVER_HANDLER_CONTINUE; 134 } 135 136 if (work->sess && conn->ops->is_sign_req(work, command)) { 137 ret = conn->ops->check_sign_req(work); 138 if (!ret) { 139 conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED); 140 return SERVER_HANDLER_CONTINUE; 141 } 142 } 143 144 ret = cmds->proc(work); 145 146 if (ret < 0) 147 ksmbd_debug(CONN, "Failed to process %u [%d]\n", command, ret); 148 /* AndX commands - chained request can return positive values */ 149 else if (ret > 0) { 150 command = ret; 151 *cmd = command; 152 goto andx_again; 153 } 154 155 if (work->send_no_response) 156 return SERVER_HANDLER_ABORT; 157 return SERVER_HANDLER_CONTINUE; 158} 159 160static void __handle_ksmbd_work(struct ksmbd_work *work, 161 struct ksmbd_conn *conn) 162{ 163 u16 command = 0; 164 int rc; 165 166 if (conn->ops->allocate_rsp_buf(work)) 167 return; 168 169 if (conn->ops->is_transform_hdr && 170 conn->ops->is_transform_hdr(work->request_buf)) { 171 rc = conn->ops->decrypt_req(work); 172 if (rc < 0) { 173 conn->ops->set_rsp_status(work, STATUS_DATA_ERROR); 174 goto send; 175 } 176 177 work->encrypted = true; 178 } 179 180 rc = conn->ops->init_rsp_hdr(work); 181 if (rc) { 182 /* either uid or tid is not correct */ 183 conn->ops->set_rsp_status(work, STATUS_INVALID_HANDLE); 184 goto send; 185 } 186 187 if (conn->ops->check_user_session) { 188 rc = conn->ops->check_user_session(work); 189 if (rc < 0) { 190 command = conn->ops->get_cmd_val(work); 191 conn->ops->set_rsp_status(work, 192 STATUS_USER_SESSION_DELETED); 193 goto send; 194 } else if (rc > 0) { 195 rc = conn->ops->get_ksmbd_tcon(work); 196 if (rc < 0) { 197 conn->ops->set_rsp_status(work, 198 STATUS_NETWORK_NAME_DELETED); 199 goto send; 200 } 201 } 202 } 203 204 do { 205 rc = __process_request(work, conn, &command); 206 if (rc == SERVER_HANDLER_ABORT) 207 break; 208 209 /* 210 * Call smb2_set_rsp_credits() function to set number of credits 211 * granted in hdr of smb2 response. 212 */ 213 if (conn->ops->set_rsp_credits) { 214 spin_lock(&conn->credits_lock); 215 rc = conn->ops->set_rsp_credits(work); 216 spin_unlock(&conn->credits_lock); 217 if (rc < 0) { 218 conn->ops->set_rsp_status(work, 219 STATUS_INVALID_PARAMETER); 220 goto send; 221 } 222 } 223 224 if (work->sess && 225 (work->sess->sign || smb3_11_final_sess_setup_resp(work) || 226 conn->ops->is_sign_req(work, command))) 227 conn->ops->set_sign_rsp(work); 228 } while (is_chained_smb2_message(work)); 229 230 if (work->send_no_response) 231 return; 232 233send: 234 smb3_preauth_hash_rsp(work); 235 if (work->sess && work->sess->enc && work->encrypted && 236 conn->ops->encrypt_resp) { 237 rc = conn->ops->encrypt_resp(work); 238 if (rc < 0) { 239 conn->ops->set_rsp_status(work, STATUS_DATA_ERROR); 240 goto send; 241 } 242 } 243 244 ksmbd_conn_write(work); 245} 246 247/** 248 * handle_ksmbd_work() - process pending smb work requests 249 * @wk: smb work containing request command buffer 250 * 251 * called by kworker threads to processing remaining smb work requests 252 */ 253static void handle_ksmbd_work(struct work_struct *wk) 254{ 255 struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work); 256 struct ksmbd_conn *conn = work->conn; 257 258 atomic64_inc(&conn->stats.request_served); 259 260 __handle_ksmbd_work(work, conn); 261 262 ksmbd_conn_try_dequeue_request(work); 263 ksmbd_free_work_struct(work); 264 atomic_dec(&conn->r_count); 265} 266 267/** 268 * queue_ksmbd_work() - queue a smb request to worker thread queue 269 * for proccessing smb command and sending response 270 * @conn: connection instance 271 * 272 * read remaining data from socket create and submit work. 273 */ 274static int queue_ksmbd_work(struct ksmbd_conn *conn) 275{ 276 struct ksmbd_work *work; 277 278 work = ksmbd_alloc_work_struct(); 279 if (!work) { 280 pr_err("allocation for work failed\n"); 281 return -ENOMEM; 282 } 283 284 work->conn = conn; 285 work->request_buf = conn->request_buf; 286 conn->request_buf = NULL; 287 288 if (ksmbd_init_smb_server(work)) { 289 ksmbd_free_work_struct(work); 290 return -EINVAL; 291 } 292 293 ksmbd_conn_enqueue_request(work); 294 atomic_inc(&conn->r_count); 295 /* update activity on connection */ 296 conn->last_active = jiffies; 297 INIT_WORK(&work->work, handle_ksmbd_work); 298 ksmbd_queue_work(work); 299 return 0; 300} 301 302static int ksmbd_server_process_request(struct ksmbd_conn *conn) 303{ 304 return queue_ksmbd_work(conn); 305} 306 307static int ksmbd_server_terminate_conn(struct ksmbd_conn *conn) 308{ 309 ksmbd_sessions_deregister(conn); 310 destroy_lease_table(conn); 311 return 0; 312} 313 314static void ksmbd_server_tcp_callbacks_init(void) 315{ 316 struct ksmbd_conn_ops ops; 317 318 ops.process_fn = ksmbd_server_process_request; 319 ops.terminate_fn = ksmbd_server_terminate_conn; 320 321 ksmbd_conn_init_server_callbacks(&ops); 322} 323 324static void server_conf_free(void) 325{ 326 int i; 327 328 for (i = 0; i < ARRAY_SIZE(server_conf.conf); i++) { 329 kfree(server_conf.conf[i]); 330 server_conf.conf[i] = NULL; 331 } 332} 333 334static int server_conf_init(void) 335{ 336 WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP); 337 server_conf.enforced_signing = 0; 338 server_conf.min_protocol = ksmbd_min_protocol(); 339 server_conf.max_protocol = ksmbd_max_protocol(); 340 server_conf.auth_mechs = KSMBD_AUTH_NTLMSSP; 341#ifdef CONFIG_SMB_SERVER_KERBEROS5 342 server_conf.auth_mechs |= KSMBD_AUTH_KRB5 | 343 KSMBD_AUTH_MSKRB5; 344#endif 345 return 0; 346} 347 348static void server_ctrl_handle_init(struct server_ctrl_struct *ctrl) 349{ 350 int ret; 351 352 ret = ksmbd_conn_transport_init(); 353 if (ret) { 354 server_queue_ctrl_reset_work(); 355 return; 356 } 357 358 WRITE_ONCE(server_conf.state, SERVER_STATE_RUNNING); 359} 360 361static void server_ctrl_handle_reset(struct server_ctrl_struct *ctrl) 362{ 363 ksmbd_ipc_soft_reset(); 364 ksmbd_conn_transport_destroy(); 365 server_conf_free(); 366 server_conf_init(); 367 WRITE_ONCE(server_conf.state, SERVER_STATE_STARTING_UP); 368} 369 370static void server_ctrl_handle_work(struct work_struct *work) 371{ 372 struct server_ctrl_struct *ctrl; 373 374 ctrl = container_of(work, struct server_ctrl_struct, ctrl_work); 375 376 mutex_lock(&ctrl_lock); 377 switch (ctrl->type) { 378 case SERVER_CTRL_TYPE_INIT: 379 server_ctrl_handle_init(ctrl); 380 break; 381 case SERVER_CTRL_TYPE_RESET: 382 server_ctrl_handle_reset(ctrl); 383 break; 384 default: 385 pr_err("Unknown server work type: %d\n", ctrl->type); 386 } 387 mutex_unlock(&ctrl_lock); 388 kfree(ctrl); 389 module_put(THIS_MODULE); 390} 391 392static int __queue_ctrl_work(int type) 393{ 394 struct server_ctrl_struct *ctrl; 395 396 ctrl = kmalloc(sizeof(struct server_ctrl_struct), GFP_KERNEL); 397 if (!ctrl) 398 return -ENOMEM; 399 400 __module_get(THIS_MODULE); 401 ctrl->type = type; 402 INIT_WORK(&ctrl->ctrl_work, server_ctrl_handle_work); 403 queue_work(system_long_wq, &ctrl->ctrl_work); 404 return 0; 405} 406 407int server_queue_ctrl_init_work(void) 408{ 409 return __queue_ctrl_work(SERVER_CTRL_TYPE_INIT); 410} 411 412int server_queue_ctrl_reset_work(void) 413{ 414 return __queue_ctrl_work(SERVER_CTRL_TYPE_RESET); 415} 416 417static ssize_t stats_show(struct class *class, struct class_attribute *attr, 418 char *buf) 419{ 420 /* 421 * Inc this each time you change stats output format, 422 * so user space will know what to do. 423 */ 424 static int stats_version = 2; 425 static const char * const state[] = { 426 "startup", 427 "running", 428 "reset", 429 "shutdown" 430 }; 431 432 ssize_t sz = scnprintf(buf, PAGE_SIZE, "%d %s %d %lu\n", stats_version, 433 state[server_conf.state], server_conf.tcp_port, 434 server_conf.ipc_last_active / HZ); 435 return sz; 436} 437 438static ssize_t kill_server_store(struct class *class, 439 struct class_attribute *attr, const char *buf, 440 size_t len) 441{ 442 if (!sysfs_streq(buf, "hard")) 443 return len; 444 445 pr_info("kill command received\n"); 446 mutex_lock(&ctrl_lock); 447 WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING); 448 __module_get(THIS_MODULE); 449 server_ctrl_handle_reset(NULL); 450 module_put(THIS_MODULE); 451 mutex_unlock(&ctrl_lock); 452 return len; 453} 454 455static const char * const debug_type_strings[] = {"smb", "auth", "vfs", 456 "oplock", "ipc", "conn", 457 "rdma"}; 458 459static ssize_t debug_show(struct class *class, struct class_attribute *attr, 460 char *buf) 461{ 462 ssize_t sz = 0; 463 int i, pos = 0; 464 465 for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) { 466 if ((ksmbd_debug_types >> i) & 1) { 467 pos = scnprintf(buf + sz, 468 PAGE_SIZE - sz, 469 "[%s] ", 470 debug_type_strings[i]); 471 } else { 472 pos = scnprintf(buf + sz, 473 PAGE_SIZE - sz, 474 "%s ", 475 debug_type_strings[i]); 476 } 477 sz += pos; 478 } 479 sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n"); 480 return sz; 481} 482 483static ssize_t debug_store(struct class *class, struct class_attribute *attr, 484 const char *buf, size_t len) 485{ 486 int i; 487 488 for (i = 0; i < ARRAY_SIZE(debug_type_strings); i++) { 489 if (sysfs_streq(buf, "all")) { 490 if (ksmbd_debug_types == KSMBD_DEBUG_ALL) 491 ksmbd_debug_types = 0; 492 else 493 ksmbd_debug_types = KSMBD_DEBUG_ALL; 494 break; 495 } 496 497 if (sysfs_streq(buf, debug_type_strings[i])) { 498 if (ksmbd_debug_types & (1 << i)) 499 ksmbd_debug_types &= ~(1 << i); 500 else 501 ksmbd_debug_types |= (1 << i); 502 break; 503 } 504 } 505 506 return len; 507} 508 509static CLASS_ATTR_RO(stats); 510static CLASS_ATTR_WO(kill_server); 511static CLASS_ATTR_RW(debug); 512 513static struct attribute *ksmbd_control_class_attrs[] = { 514 &class_attr_stats.attr, 515 &class_attr_kill_server.attr, 516 &class_attr_debug.attr, 517 NULL, 518}; 519ATTRIBUTE_GROUPS(ksmbd_control_class); 520 521static struct class ksmbd_control_class = { 522 .name = "ksmbd-control", 523 .owner = THIS_MODULE, 524 .class_groups = ksmbd_control_class_groups, 525}; 526 527static int ksmbd_server_shutdown(void) 528{ 529 WRITE_ONCE(server_conf.state, SERVER_STATE_SHUTTING_DOWN); 530 531 class_unregister(&ksmbd_control_class); 532 ksmbd_workqueue_destroy(); 533 ksmbd_ipc_release(); 534 ksmbd_conn_transport_destroy(); 535 ksmbd_crypto_destroy(); 536 ksmbd_free_global_file_table(); 537 destroy_lease_table(NULL); 538 ksmbd_work_pool_destroy(); 539 ksmbd_exit_file_cache(); 540 server_conf_free(); 541 return 0; 542} 543 544static int __init ksmbd_server_init(void) 545{ 546 int ret; 547 548 ret = class_register(&ksmbd_control_class); 549 if (ret) { 550 pr_err("Unable to register ksmbd-control class\n"); 551 return ret; 552 } 553 554 ksmbd_server_tcp_callbacks_init(); 555 556 ret = server_conf_init(); 557 if (ret) 558 goto err_unregister; 559 560 ret = ksmbd_work_pool_init(); 561 if (ret) 562 goto err_unregister; 563 564 ret = ksmbd_init_file_cache(); 565 if (ret) 566 goto err_destroy_work_pools; 567 568 ret = ksmbd_ipc_init(); 569 if (ret) 570 goto err_exit_file_cache; 571 572 ret = ksmbd_init_global_file_table(); 573 if (ret) 574 goto err_ipc_release; 575 576 ret = ksmbd_inode_hash_init(); 577 if (ret) 578 goto err_destroy_file_table; 579 580 ret = ksmbd_crypto_create(); 581 if (ret) 582 goto err_release_inode_hash; 583 584 ret = ksmbd_workqueue_init(); 585 if (ret) 586 goto err_crypto_destroy; 587 588 pr_warn_once("The ksmbd server is experimental\n"); 589 590 return 0; 591 592err_crypto_destroy: 593 ksmbd_crypto_destroy(); 594err_release_inode_hash: 595 ksmbd_release_inode_hash(); 596err_destroy_file_table: 597 ksmbd_free_global_file_table(); 598err_ipc_release: 599 ksmbd_ipc_release(); 600err_exit_file_cache: 601 ksmbd_exit_file_cache(); 602err_destroy_work_pools: 603 ksmbd_work_pool_destroy(); 604err_unregister: 605 class_unregister(&ksmbd_control_class); 606 607 return ret; 608} 609 610/** 611 * ksmbd_server_exit() - shutdown forker thread and free memory at module exit 612 */ 613static void __exit ksmbd_server_exit(void) 614{ 615 ksmbd_server_shutdown(); 616 ksmbd_release_inode_hash(); 617} 618 619MODULE_AUTHOR("Namjae Jeon <linkinjeon@kernel.org>"); 620MODULE_VERSION(KSMBD_VERSION); 621MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER"); 622MODULE_LICENSE("GPL"); 623MODULE_SOFTDEP("pre: ecb"); 624MODULE_SOFTDEP("pre: hmac"); 625MODULE_SOFTDEP("pre: md5"); 626MODULE_SOFTDEP("pre: nls"); 627MODULE_SOFTDEP("pre: aes"); 628MODULE_SOFTDEP("pre: cmac"); 629MODULE_SOFTDEP("pre: sha256"); 630MODULE_SOFTDEP("pre: sha512"); 631MODULE_SOFTDEP("pre: aead2"); 632MODULE_SOFTDEP("pre: ccm"); 633MODULE_SOFTDEP("pre: gcm"); 634MODULE_SOFTDEP("pre: crc32"); 635module_init(ksmbd_server_init) 636module_exit(ksmbd_server_exit)