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