Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.9-rc7 921 lines 23 kB view raw
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 unsigned int msg_sz; 69}; 70 71static struct delayed_work ipc_timer_work; 72 73static int handle_startup_event(struct sk_buff *skb, struct genl_info *info); 74static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info); 75static int handle_generic_event(struct sk_buff *skb, struct genl_info *info); 76static int ksmbd_ipc_heartbeat_request(void); 77 78static 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 125static 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 192static 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 204static 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 215static 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 222static void ipc_update_last_active(void) 223{ 224 if (server_conf.ipc_timeout) 225 server_conf.ipc_last_active = jiffies; 226} 227 228static 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 239static void ipc_msg_free(struct ksmbd_ipc_msg *msg) 240{ 241 kvfree(msg); 242} 243 244static void ipc_msg_handle_free(int handle) 245{ 246 if (handle >= 0) 247 ksmbd_release_id(&ipc_ida, handle); 248} 249 250static 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 289static 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 344static 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 386out: 387 mutex_unlock(&startup_lock); 388 return ret; 389} 390 391static 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 397static 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 424static 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 453out: 454 nlmsg_free(skb); 455 return ret; 456} 457 458static 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 486static 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 } 517out: 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 524static 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 539struct 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 563struct ksmbd_spnego_authen_response * 564ksmbd_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 587struct ksmbd_tree_connect_response * 588ksmbd_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 629int 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 650int 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 673struct ksmbd_share_config_response * 674ksmbd_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 698struct 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 720struct 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 742struct 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 767struct 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 790struct 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 815struct 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 840static 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 877static void ipc_timer_heartbeat(struct work_struct *w) 878{ 879 if (__ipc_heartbeat()) 880 server_queue_ctrl_reset_work(); 881} 882 883int ksmbd_ipc_id_alloc(void) 884{ 885 return ksmbd_acquire_id(&ipc_ida); 886} 887 888void ksmbd_rpc_id_free(int handle) 889{ 890 ksmbd_release_id(&ipc_ida, handle); 891} 892 893void ksmbd_ipc_release(void) 894{ 895 cancel_delayed_work_sync(&ipc_timer_work); 896 genl_unregister_family(&ksmbd_genl_family); 897} 898 899void 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 907int 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}