1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2018 Samsung Electronics Co., Ltd. 4 */ 5 6 #include <linux/jhash.h> 7 #include <linux/slab.h> 8 #include <linux/rwsem.h> 9 #include <linux/mutex.h> 10 #include <linux/wait.h> 11 #include <linux/hashtable.h> 12 #include <net/net_namespace.h> 13 #include <net/genetlink.h> 14 #include <linux/socket.h> 15 #include <linux/workqueue.h> 16 17 #include "vfs_cache.h" 18 #include "transport_ipc.h" 19 #include "server.h" 20 #include "smb_common.h" 21 22 #include "mgmt/user_config.h" 23 #include "mgmt/share_config.h" 24 #include "mgmt/user_session.h" 25 #include "mgmt/tree_connect.h" 26 #include "mgmt/ksmbd_ida.h" 27 #include "connection.h" 28 #include "transport_tcp.h" 29 #include "transport_rdma.h" 30 31 #define IPC_WAIT_TIMEOUT (2 * HZ) 32 33 #define IPC_MSG_HASH_BITS 3 34 static DEFINE_HASHTABLE(ipc_msg_table, IPC_MSG_HASH_BITS); 35 static DECLARE_RWSEM(ipc_msg_table_lock); 36 static DEFINE_MUTEX(startup_lock); 37 38 static DEFINE_IDA(ipc_ida); 39 40 static unsigned int ksmbd_tools_pid; 41 42 static bool ksmbd_ipc_validate_version(struct genl_info *m) 43 { 44 if (m->genlhdr->version != KSMBD_GENL_VERSION) { 45 pr_err("%s. ksmbd: %d, kernel module: %d. %s.\n", 46 "Daemon and kernel module version mismatch", 47 m->genlhdr->version, 48 KSMBD_GENL_VERSION, 49 "User-space ksmbd should terminate"); 50 return false; 51 } 52 return true; 53 } 54 55 struct ksmbd_ipc_msg { 56 unsigned int type; 57 unsigned int sz; 58 unsigned char payload[]; 59 }; 60 61 struct ipc_msg_table_entry { 62 unsigned int handle; 63 unsigned int type; 64 wait_queue_head_t wait; 65 struct hlist_node ipc_table_hlist; 66 67 void *response; 68 unsigned int msg_sz; 69 }; 70 71 static struct delayed_work ipc_timer_work; 72 73 static int handle_startup_event(struct sk_buff *skb, struct genl_info *info); 74 static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info); 75 static int handle_generic_event(struct sk_buff *skb, struct genl_info *info); 76 static int ksmbd_ipc_heartbeat_request(void); 77 78 static const struct nla_policy ksmbd_nl_policy[KSMBD_EVENT_MAX + 1] = { 79 [KSMBD_EVENT_UNSPEC] = { 80 .len = 0, 81 }, 82 [KSMBD_EVENT_HEARTBEAT_REQUEST] = { 83 .len = sizeof(struct ksmbd_heartbeat), 84 }, 85 [KSMBD_EVENT_STARTING_UP] = { 86 .len = sizeof(struct ksmbd_startup_request), 87 }, 88 [KSMBD_EVENT_SHUTTING_DOWN] = { 89 .len = sizeof(struct ksmbd_shutdown_request), 90 }, 91 [KSMBD_EVENT_LOGIN_REQUEST] = { 92 .len = sizeof(struct ksmbd_login_request), 93 }, 94 [KSMBD_EVENT_LOGIN_RESPONSE] = { 95 .len = sizeof(struct ksmbd_login_response), 96 }, 97 [KSMBD_EVENT_SHARE_CONFIG_REQUEST] = { 98 .len = sizeof(struct ksmbd_share_config_request), 99 }, 100 [KSMBD_EVENT_SHARE_CONFIG_RESPONSE] = { 101 .len = sizeof(struct ksmbd_share_config_response), 102 }, 103 [KSMBD_EVENT_TREE_CONNECT_REQUEST] = { 104 .len = sizeof(struct ksmbd_tree_connect_request), 105 }, 106 [KSMBD_EVENT_TREE_CONNECT_RESPONSE] = { 107 .len = sizeof(struct ksmbd_tree_connect_response), 108 }, 109 [KSMBD_EVENT_TREE_DISCONNECT_REQUEST] = { 110 .len = sizeof(struct ksmbd_tree_disconnect_request), 111 }, 112 [KSMBD_EVENT_LOGOUT_REQUEST] = { 113 .len = sizeof(struct ksmbd_logout_request), 114 }, 115 [KSMBD_EVENT_RPC_REQUEST] = { 116 }, 117 [KSMBD_EVENT_RPC_RESPONSE] = { 118 }, 119 [KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST] = { 120 }, 121 [KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE] = { 122 }, 123 }; 124 125 static struct genl_ops ksmbd_genl_ops[] = { 126 { 127 .cmd = KSMBD_EVENT_UNSPEC, 128 .doit = handle_unsupported_event, 129 }, 130 { 131 .cmd = KSMBD_EVENT_HEARTBEAT_REQUEST, 132 .doit = handle_unsupported_event, 133 }, 134 { 135 .cmd = KSMBD_EVENT_STARTING_UP, 136 .doit = handle_startup_event, 137 }, 138 { 139 .cmd = KSMBD_EVENT_SHUTTING_DOWN, 140 .doit = handle_unsupported_event, 141 }, 142 { 143 .cmd = KSMBD_EVENT_LOGIN_REQUEST, 144 .doit = handle_unsupported_event, 145 }, 146 { 147 .cmd = KSMBD_EVENT_LOGIN_RESPONSE, 148 .doit = handle_generic_event, 149 }, 150 { 151 .cmd = KSMBD_EVENT_SHARE_CONFIG_REQUEST, 152 .doit = handle_unsupported_event, 153 }, 154 { 155 .cmd = KSMBD_EVENT_SHARE_CONFIG_RESPONSE, 156 .doit = handle_generic_event, 157 }, 158 { 159 .cmd = KSMBD_EVENT_TREE_CONNECT_REQUEST, 160 .doit = handle_unsupported_event, 161 }, 162 { 163 .cmd = KSMBD_EVENT_TREE_CONNECT_RESPONSE, 164 .doit = handle_generic_event, 165 }, 166 { 167 .cmd = KSMBD_EVENT_TREE_DISCONNECT_REQUEST, 168 .doit = handle_unsupported_event, 169 }, 170 { 171 .cmd = KSMBD_EVENT_LOGOUT_REQUEST, 172 .doit = handle_unsupported_event, 173 }, 174 { 175 .cmd = KSMBD_EVENT_RPC_REQUEST, 176 .doit = handle_unsupported_event, 177 }, 178 { 179 .cmd = KSMBD_EVENT_RPC_RESPONSE, 180 .doit = handle_generic_event, 181 }, 182 { 183 .cmd = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST, 184 .doit = handle_unsupported_event, 185 }, 186 { 187 .cmd = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE, 188 .doit = handle_generic_event, 189 }, 190 }; 191 192 static struct genl_family ksmbd_genl_family = { 193 .name = KSMBD_GENL_NAME, 194 .version = KSMBD_GENL_VERSION, 195 .hdrsize = 0, 196 .maxattr = KSMBD_EVENT_MAX, 197 .netnsok = true, 198 .module = THIS_MODULE, 199 .ops = ksmbd_genl_ops, 200 .n_ops = ARRAY_SIZE(ksmbd_genl_ops), 201 .resv_start_op = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE + 1, 202 }; 203 204 static void ksmbd_nl_init_fixup(void) 205 { 206 int i; 207 208 for (i = 0; i < ARRAY_SIZE(ksmbd_genl_ops); i++) 209 ksmbd_genl_ops[i].validate = GENL_DONT_VALIDATE_STRICT | 210 GENL_DONT_VALIDATE_DUMP; 211 212 ksmbd_genl_family.policy = ksmbd_nl_policy; 213 } 214 215 static int rpc_context_flags(struct ksmbd_session *sess) 216 { 217 if (user_guest(sess->user)) 218 return KSMBD_RPC_RESTRICTED_CONTEXT; 219 return 0; 220 } 221 222 static void ipc_update_last_active(void) 223 { 224 if (server_conf.ipc_timeout) 225 server_conf.ipc_last_active = jiffies; 226 } 227 228 static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz) 229 { 230 struct ksmbd_ipc_msg *msg; 231 size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg); 232 233 msg = kvzalloc(msg_sz, GFP_KERNEL); 234 if (msg) 235 msg->sz = sz; 236 return msg; 237 } 238 239 static void ipc_msg_free(struct ksmbd_ipc_msg *msg) 240 { 241 kvfree(msg); 242 } 243 244 static void ipc_msg_handle_free(int handle) 245 { 246 if (handle >= 0) 247 ksmbd_release_id(&ipc_ida, handle); 248 } 249 250 static int handle_response(int type, void *payload, size_t sz) 251 { 252 unsigned int handle = *(unsigned int *)payload; 253 struct ipc_msg_table_entry *entry; 254 int ret = 0; 255 256 ipc_update_last_active(); 257 down_read(&ipc_msg_table_lock); 258 hash_for_each_possible(ipc_msg_table, entry, ipc_table_hlist, handle) { 259 if (handle != entry->handle) 260 continue; 261 262 entry->response = NULL; 263 /* 264 * Response message type value should be equal to 265 * request message type + 1. 266 */ 267 if (entry->type + 1 != type) { 268 pr_err("Waiting for IPC type %d, got %d. Ignore.\n", 269 entry->type + 1, type); 270 } 271 272 entry->response = kvzalloc(sz, GFP_KERNEL); 273 if (!entry->response) { 274 ret = -ENOMEM; 275 break; 276 } 277 278 memcpy(entry->response, payload, sz); 279 entry->msg_sz = sz; 280 wake_up_interruptible(&entry->wait); 281 ret = 0; 282 break; 283 } 284 up_read(&ipc_msg_table_lock); 285 286 return ret; 287 } 288 289 static int ipc_server_config_on_startup(struct ksmbd_startup_request *req) 290 { 291 int ret; 292 293 ksmbd_set_fd_limit(req->file_max); 294 server_conf.flags = req->flags; 295 server_conf.signing = req->signing; 296 server_conf.tcp_port = req->tcp_port; 297 server_conf.ipc_timeout = req->ipc_timeout * HZ; 298 server_conf.deadtime = req->deadtime * SMB_ECHO_INTERVAL; 299 server_conf.share_fake_fscaps = req->share_fake_fscaps; 300 ksmbd_init_domain(req->sub_auth); 301 302 if (req->smb2_max_read) 303 init_smb2_max_read_size(req->smb2_max_read); 304 if (req->smb2_max_write) 305 init_smb2_max_write_size(req->smb2_max_write); 306 if (req->smb2_max_trans) 307 init_smb2_max_trans_size(req->smb2_max_trans); 308 if (req->smb2_max_credits) 309 init_smb2_max_credits(req->smb2_max_credits); 310 if (req->smbd_max_io_size) 311 init_smbd_max_io_size(req->smbd_max_io_size); 312 313 if (req->max_connections) 314 server_conf.max_connections = req->max_connections; 315 316 ret = ksmbd_set_netbios_name(req->netbios_name); 317 ret |= ksmbd_set_server_string(req->server_string); 318 ret |= ksmbd_set_work_group(req->work_group); 319 ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req), 320 req->ifc_list_sz); 321 if (ret) { 322 pr_err("Server configuration error: %s %s %s\n", 323 req->netbios_name, req->server_string, 324 req->work_group); 325 return ret; 326 } 327 328 if (req->min_prot[0]) { 329 ret = ksmbd_lookup_protocol_idx(req->min_prot); 330 if (ret >= 0) 331 server_conf.min_protocol = ret; 332 } 333 if (req->max_prot[0]) { 334 ret = ksmbd_lookup_protocol_idx(req->max_prot); 335 if (ret >= 0) 336 server_conf.max_protocol = ret; 337 } 338 339 if (server_conf.ipc_timeout) 340 schedule_delayed_work(&ipc_timer_work, server_conf.ipc_timeout); 341 return 0; 342 } 343 344 static int handle_startup_event(struct sk_buff *skb, struct genl_info *info) 345 { 346 int ret = 0; 347 348 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN 349 if (!netlink_capable(skb, CAP_NET_ADMIN)) 350 return -EPERM; 351 #endif 352 353 if (!ksmbd_ipc_validate_version(info)) 354 return -EINVAL; 355 356 if (!info->attrs[KSMBD_EVENT_STARTING_UP]) 357 return -EINVAL; 358 359 mutex_lock(&startup_lock); 360 if (!ksmbd_server_configurable()) { 361 mutex_unlock(&startup_lock); 362 pr_err("Server reset is in progress, can't start daemon\n"); 363 return -EINVAL; 364 } 365 366 if (ksmbd_tools_pid) { 367 if (ksmbd_ipc_heartbeat_request() == 0) { 368 ret = -EINVAL; 369 goto out; 370 } 371 372 pr_err("Reconnect to a new user space daemon\n"); 373 } else { 374 struct ksmbd_startup_request *req; 375 376 req = nla_data(info->attrs[info->genlhdr->cmd]); 377 ret = ipc_server_config_on_startup(req); 378 if (ret) 379 goto out; 380 server_queue_ctrl_init_work(); 381 } 382 383 ksmbd_tools_pid = info->snd_portid; 384 ipc_update_last_active(); 385 386 out: 387 mutex_unlock(&startup_lock); 388 return ret; 389 } 390 391 static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info) 392 { 393 pr_err("Unknown IPC event: %d, ignore.\n", info->genlhdr->cmd); 394 return -EINVAL; 395 } 396 397 static int handle_generic_event(struct sk_buff *skb, struct genl_info *info) 398 { 399 void *payload; 400 int sz; 401 int type = info->genlhdr->cmd; 402 403 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN 404 if (!netlink_capable(skb, CAP_NET_ADMIN)) 405 return -EPERM; 406 #endif 407 408 if (type > KSMBD_EVENT_MAX) { 409 WARN_ON(1); 410 return -EINVAL; 411 } 412 413 if (!ksmbd_ipc_validate_version(info)) 414 return -EINVAL; 415 416 if (!info->attrs[type]) 417 return -EINVAL; 418 419 payload = nla_data(info->attrs[info->genlhdr->cmd]); 420 sz = nla_len(info->attrs[info->genlhdr->cmd]); 421 return handle_response(type, payload, sz); 422 } 423 424 static int ipc_msg_send(struct ksmbd_ipc_msg *msg) 425 { 426 struct genlmsghdr *nlh; 427 struct sk_buff *skb; 428 int ret = -EINVAL; 429 430 if (!ksmbd_tools_pid) 431 return ret; 432 433 skb = genlmsg_new(msg->sz, GFP_KERNEL); 434 if (!skb) 435 return -ENOMEM; 436 437 nlh = genlmsg_put(skb, 0, 0, &ksmbd_genl_family, 0, msg->type); 438 if (!nlh) 439 goto out; 440 441 ret = nla_put(skb, msg->type, msg->sz, msg->payload); 442 if (ret) { 443 genlmsg_cancel(skb, nlh); 444 goto out; 445 } 446 447 genlmsg_end(skb, nlh); 448 ret = genlmsg_unicast(&init_net, skb, ksmbd_tools_pid); 449 if (!ret) 450 ipc_update_last_active(); 451 return ret; 452 453 out: 454 nlmsg_free(skb); 455 return ret; 456 } 457 458 static int ipc_validate_msg(struct ipc_msg_table_entry *entry) 459 { 460 unsigned int msg_sz = entry->msg_sz; 461 462 if (entry->type == KSMBD_EVENT_RPC_REQUEST) { 463 struct ksmbd_rpc_command *resp = entry->response; 464 465 msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz; 466 } else if (entry->type == KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST) { 467 struct ksmbd_spnego_authen_response *resp = entry->response; 468 469 msg_sz = sizeof(struct ksmbd_spnego_authen_response) + 470 resp->session_key_len + resp->spnego_blob_len; 471 } else if (entry->type == KSMBD_EVENT_SHARE_CONFIG_REQUEST) { 472 struct ksmbd_share_config_response *resp = entry->response; 473 474 if (resp->payload_sz) { 475 if (resp->payload_sz < resp->veto_list_sz) 476 return -EINVAL; 477 478 msg_sz = sizeof(struct ksmbd_share_config_response) + 479 resp->payload_sz; 480 } 481 } 482 483 return entry->msg_sz != msg_sz ? -EINVAL : 0; 484 } 485 486 static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle) 487 { 488 struct ipc_msg_table_entry entry; 489 int ret; 490 491 if ((int)handle < 0) 492 return NULL; 493 494 entry.type = msg->type; 495 entry.response = NULL; 496 init_waitqueue_head(&entry.wait); 497 498 down_write(&ipc_msg_table_lock); 499 entry.handle = handle; 500 hash_add(ipc_msg_table, &entry.ipc_table_hlist, entry.handle); 501 up_write(&ipc_msg_table_lock); 502 503 ret = ipc_msg_send(msg); 504 if (ret) 505 goto out; 506 507 ret = wait_event_interruptible_timeout(entry.wait, 508 entry.response != NULL, 509 IPC_WAIT_TIMEOUT); 510 if (entry.response) { 511 ret = ipc_validate_msg(&entry); 512 if (ret) { 513 kvfree(entry.response); 514 entry.response = NULL; 515 } 516 } 517 out: 518 down_write(&ipc_msg_table_lock); 519 hash_del(&entry.ipc_table_hlist); 520 up_write(&ipc_msg_table_lock); 521 return entry.response; 522 } 523 524 static int ksmbd_ipc_heartbeat_request(void) 525 { 526 struct ksmbd_ipc_msg *msg; 527 int ret; 528 529 msg = ipc_msg_alloc(sizeof(struct ksmbd_heartbeat)); 530 if (!msg) 531 return -EINVAL; 532 533 msg->type = KSMBD_EVENT_HEARTBEAT_REQUEST; 534 ret = ipc_msg_send(msg); 535 ipc_msg_free(msg); 536 return ret; 537 } 538 539 struct ksmbd_login_response *ksmbd_ipc_login_request(const char *account) 540 { 541 struct ksmbd_ipc_msg *msg; 542 struct ksmbd_login_request *req; 543 struct ksmbd_login_response *resp; 544 545 if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ) 546 return NULL; 547 548 msg = ipc_msg_alloc(sizeof(struct ksmbd_login_request)); 549 if (!msg) 550 return NULL; 551 552 msg->type = KSMBD_EVENT_LOGIN_REQUEST; 553 req = (struct ksmbd_login_request *)msg->payload; 554 req->handle = ksmbd_acquire_id(&ipc_ida); 555 strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ); 556 557 resp = ipc_msg_send_request(msg, req->handle); 558 ipc_msg_handle_free(req->handle); 559 ipc_msg_free(msg); 560 return resp; 561 } 562 563 struct ksmbd_spnego_authen_response * 564 ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len) 565 { 566 struct ksmbd_ipc_msg *msg; 567 struct ksmbd_spnego_authen_request *req; 568 struct ksmbd_spnego_authen_response *resp; 569 570 msg = ipc_msg_alloc(sizeof(struct ksmbd_spnego_authen_request) + 571 blob_len + 1); 572 if (!msg) 573 return NULL; 574 575 msg->type = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST; 576 req = (struct ksmbd_spnego_authen_request *)msg->payload; 577 req->handle = ksmbd_acquire_id(&ipc_ida); 578 req->spnego_blob_len = blob_len; 579 memcpy(req->spnego_blob, spnego_blob, blob_len); 580 581 resp = ipc_msg_send_request(msg, req->handle); 582 ipc_msg_handle_free(req->handle); 583 ipc_msg_free(msg); 584 return resp; 585 } 586 587 struct ksmbd_tree_connect_response * 588 ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess, 589 struct ksmbd_share_config *share, 590 struct ksmbd_tree_connect *tree_conn, 591 struct sockaddr *peer_addr) 592 { 593 struct ksmbd_ipc_msg *msg; 594 struct ksmbd_tree_connect_request *req; 595 struct ksmbd_tree_connect_response *resp; 596 597 if (strlen(user_name(sess->user)) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ) 598 return NULL; 599 600 if (strlen(share->name) >= KSMBD_REQ_MAX_SHARE_NAME) 601 return NULL; 602 603 msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_connect_request)); 604 if (!msg) 605 return NULL; 606 607 msg->type = KSMBD_EVENT_TREE_CONNECT_REQUEST; 608 req = (struct ksmbd_tree_connect_request *)msg->payload; 609 610 req->handle = ksmbd_acquire_id(&ipc_ida); 611 req->account_flags = sess->user->flags; 612 req->session_id = sess->id; 613 req->connect_id = tree_conn->id; 614 strscpy(req->account, user_name(sess->user), KSMBD_REQ_MAX_ACCOUNT_NAME_SZ); 615 strscpy(req->share, share->name, KSMBD_REQ_MAX_SHARE_NAME); 616 snprintf(req->peer_addr, sizeof(req->peer_addr), "%pIS", peer_addr); 617 618 if (peer_addr->sa_family == AF_INET6) 619 req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_IPV6; 620 if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2)) 621 req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_SMB2; 622 623 resp = ipc_msg_send_request(msg, req->handle); 624 ipc_msg_handle_free(req->handle); 625 ipc_msg_free(msg); 626 return resp; 627 } 628 629 int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id, 630 unsigned long long connect_id) 631 { 632 struct ksmbd_ipc_msg *msg; 633 struct ksmbd_tree_disconnect_request *req; 634 int ret; 635 636 msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_disconnect_request)); 637 if (!msg) 638 return -ENOMEM; 639 640 msg->type = KSMBD_EVENT_TREE_DISCONNECT_REQUEST; 641 req = (struct ksmbd_tree_disconnect_request *)msg->payload; 642 req->session_id = session_id; 643 req->connect_id = connect_id; 644 645 ret = ipc_msg_send(msg); 646 ipc_msg_free(msg); 647 return ret; 648 } 649 650 int ksmbd_ipc_logout_request(const char *account, int flags) 651 { 652 struct ksmbd_ipc_msg *msg; 653 struct ksmbd_logout_request *req; 654 int ret; 655 656 if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ) 657 return -EINVAL; 658 659 msg = ipc_msg_alloc(sizeof(struct ksmbd_logout_request)); 660 if (!msg) 661 return -ENOMEM; 662 663 msg->type = KSMBD_EVENT_LOGOUT_REQUEST; 664 req = (struct ksmbd_logout_request *)msg->payload; 665 req->account_flags = flags; 666 strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ); 667 668 ret = ipc_msg_send(msg); 669 ipc_msg_free(msg); 670 return ret; 671 } 672 673 struct ksmbd_share_config_response * 674 ksmbd_ipc_share_config_request(const char *name) 675 { 676 struct ksmbd_ipc_msg *msg; 677 struct ksmbd_share_config_request *req; 678 struct ksmbd_share_config_response *resp; 679 680 if (strlen(name) >= KSMBD_REQ_MAX_SHARE_NAME) 681 return NULL; 682 683 msg = ipc_msg_alloc(sizeof(struct ksmbd_share_config_request)); 684 if (!msg) 685 return NULL; 686 687 msg->type = KSMBD_EVENT_SHARE_CONFIG_REQUEST; 688 req = (struct ksmbd_share_config_request *)msg->payload; 689 req->handle = ksmbd_acquire_id(&ipc_ida); 690 strscpy(req->share_name, name, KSMBD_REQ_MAX_SHARE_NAME); 691 692 resp = ipc_msg_send_request(msg, req->handle); 693 ipc_msg_handle_free(req->handle); 694 ipc_msg_free(msg); 695 return resp; 696 } 697 698 struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle) 699 { 700 struct ksmbd_ipc_msg *msg; 701 struct ksmbd_rpc_command *req; 702 struct ksmbd_rpc_command *resp; 703 704 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command)); 705 if (!msg) 706 return NULL; 707 708 msg->type = KSMBD_EVENT_RPC_REQUEST; 709 req = (struct ksmbd_rpc_command *)msg->payload; 710 req->handle = handle; 711 req->flags = ksmbd_session_rpc_method(sess, handle); 712 req->flags |= KSMBD_RPC_OPEN_METHOD; 713 req->payload_sz = 0; 714 715 resp = ipc_msg_send_request(msg, req->handle); 716 ipc_msg_free(msg); 717 return resp; 718 } 719 720 struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle) 721 { 722 struct ksmbd_ipc_msg *msg; 723 struct ksmbd_rpc_command *req; 724 struct ksmbd_rpc_command *resp; 725 726 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command)); 727 if (!msg) 728 return NULL; 729 730 msg->type = KSMBD_EVENT_RPC_REQUEST; 731 req = (struct ksmbd_rpc_command *)msg->payload; 732 req->handle = handle; 733 req->flags = ksmbd_session_rpc_method(sess, handle); 734 req->flags |= KSMBD_RPC_CLOSE_METHOD; 735 req->payload_sz = 0; 736 737 resp = ipc_msg_send_request(msg, req->handle); 738 ipc_msg_free(msg); 739 return resp; 740 } 741 742 struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle, 743 void *payload, size_t payload_sz) 744 { 745 struct ksmbd_ipc_msg *msg; 746 struct ksmbd_rpc_command *req; 747 struct ksmbd_rpc_command *resp; 748 749 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1); 750 if (!msg) 751 return NULL; 752 753 msg->type = KSMBD_EVENT_RPC_REQUEST; 754 req = (struct ksmbd_rpc_command *)msg->payload; 755 req->handle = handle; 756 req->flags = ksmbd_session_rpc_method(sess, handle); 757 req->flags |= rpc_context_flags(sess); 758 req->flags |= KSMBD_RPC_WRITE_METHOD; 759 req->payload_sz = payload_sz; 760 memcpy(req->payload, payload, payload_sz); 761 762 resp = ipc_msg_send_request(msg, req->handle); 763 ipc_msg_free(msg); 764 return resp; 765 } 766 767 struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle) 768 { 769 struct ksmbd_ipc_msg *msg; 770 struct ksmbd_rpc_command *req; 771 struct ksmbd_rpc_command *resp; 772 773 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command)); 774 if (!msg) 775 return NULL; 776 777 msg->type = KSMBD_EVENT_RPC_REQUEST; 778 req = (struct ksmbd_rpc_command *)msg->payload; 779 req->handle = handle; 780 req->flags = ksmbd_session_rpc_method(sess, handle); 781 req->flags |= rpc_context_flags(sess); 782 req->flags |= KSMBD_RPC_READ_METHOD; 783 req->payload_sz = 0; 784 785 resp = ipc_msg_send_request(msg, req->handle); 786 ipc_msg_free(msg); 787 return resp; 788 } 789 790 struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle, 791 void *payload, size_t payload_sz) 792 { 793 struct ksmbd_ipc_msg *msg; 794 struct ksmbd_rpc_command *req; 795 struct ksmbd_rpc_command *resp; 796 797 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1); 798 if (!msg) 799 return NULL; 800 801 msg->type = KSMBD_EVENT_RPC_REQUEST; 802 req = (struct ksmbd_rpc_command *)msg->payload; 803 req->handle = handle; 804 req->flags = ksmbd_session_rpc_method(sess, handle); 805 req->flags |= rpc_context_flags(sess); 806 req->flags |= KSMBD_RPC_IOCTL_METHOD; 807 req->payload_sz = payload_sz; 808 memcpy(req->payload, payload, payload_sz); 809 810 resp = ipc_msg_send_request(msg, req->handle); 811 ipc_msg_free(msg); 812 return resp; 813 } 814 815 struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payload, 816 size_t payload_sz) 817 { 818 struct ksmbd_ipc_msg *msg; 819 struct ksmbd_rpc_command *req; 820 struct ksmbd_rpc_command *resp; 821 822 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1); 823 if (!msg) 824 return NULL; 825 826 msg->type = KSMBD_EVENT_RPC_REQUEST; 827 req = (struct ksmbd_rpc_command *)msg->payload; 828 req->handle = ksmbd_acquire_id(&ipc_ida); 829 req->flags = rpc_context_flags(sess); 830 req->flags |= KSMBD_RPC_RAP_METHOD; 831 req->payload_sz = payload_sz; 832 memcpy(req->payload, payload, payload_sz); 833 834 resp = ipc_msg_send_request(msg, req->handle); 835 ipc_msg_handle_free(req->handle); 836 ipc_msg_free(msg); 837 return resp; 838 } 839 840 static int __ipc_heartbeat(void) 841 { 842 unsigned long delta; 843 844 if (!ksmbd_server_running()) 845 return 0; 846 847 if (time_after(jiffies, server_conf.ipc_last_active)) { 848 delta = (jiffies - server_conf.ipc_last_active); 849 } else { 850 ipc_update_last_active(); 851 schedule_delayed_work(&ipc_timer_work, 852 server_conf.ipc_timeout); 853 return 0; 854 } 855 856 if (delta < server_conf.ipc_timeout) { 857 schedule_delayed_work(&ipc_timer_work, 858 server_conf.ipc_timeout - delta); 859 return 0; 860 } 861 862 if (ksmbd_ipc_heartbeat_request() == 0) { 863 schedule_delayed_work(&ipc_timer_work, 864 server_conf.ipc_timeout); 865 return 0; 866 } 867 868 mutex_lock(&startup_lock); 869 WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING); 870 server_conf.ipc_last_active = 0; 871 ksmbd_tools_pid = 0; 872 pr_err("No IPC daemon response for %lus\n", delta / HZ); 873 mutex_unlock(&startup_lock); 874 return -EINVAL; 875 } 876 877 static void ipc_timer_heartbeat(struct work_struct *w) 878 { 879 if (__ipc_heartbeat()) 880 server_queue_ctrl_reset_work(); 881 } 882 883 int ksmbd_ipc_id_alloc(void) 884 { 885 return ksmbd_acquire_id(&ipc_ida); 886 } 887 888 void ksmbd_rpc_id_free(int handle) 889 { 890 ksmbd_release_id(&ipc_ida, handle); 891 } 892 893 void ksmbd_ipc_release(void) 894 { 895 cancel_delayed_work_sync(&ipc_timer_work); 896 genl_unregister_family(&ksmbd_genl_family); 897 } 898 899 void ksmbd_ipc_soft_reset(void) 900 { 901 mutex_lock(&startup_lock); 902 ksmbd_tools_pid = 0; 903 cancel_delayed_work_sync(&ipc_timer_work); 904 mutex_unlock(&startup_lock); 905 } 906 907 int ksmbd_ipc_init(void) 908 { 909 int ret = 0; 910 911 ksmbd_nl_init_fixup(); 912 INIT_DELAYED_WORK(&ipc_timer_work, ipc_timer_heartbeat); 913 914 ret = genl_register_family(&ksmbd_genl_family); 915 if (ret) { 916 pr_err("Failed to register KSMBD netlink interface %d\n", ret); 917 cancel_delayed_work_sync(&ipc_timer_work); 918 } 919 920 return ret; 921 } 922
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.