0001
0002
0003
0004
0005
0006 #include <linux/jhash.h>
0007 #include <linux/slab.h>
0008 #include <linux/rwsem.h>
0009 #include <linux/mutex.h>
0010 #include <linux/wait.h>
0011 #include <linux/hashtable.h>
0012 #include <net/net_namespace.h>
0013 #include <net/genetlink.h>
0014 #include <linux/socket.h>
0015 #include <linux/workqueue.h>
0016
0017 #include "vfs_cache.h"
0018 #include "transport_ipc.h"
0019 #include "server.h"
0020 #include "smb_common.h"
0021
0022 #include "mgmt/user_config.h"
0023 #include "mgmt/share_config.h"
0024 #include "mgmt/user_session.h"
0025 #include "mgmt/tree_connect.h"
0026 #include "mgmt/ksmbd_ida.h"
0027 #include "connection.h"
0028 #include "transport_tcp.h"
0029 #include "transport_rdma.h"
0030
0031 #define IPC_WAIT_TIMEOUT (2 * HZ)
0032
0033 #define IPC_MSG_HASH_BITS 3
0034 static DEFINE_HASHTABLE(ipc_msg_table, IPC_MSG_HASH_BITS);
0035 static DECLARE_RWSEM(ipc_msg_table_lock);
0036 static DEFINE_MUTEX(startup_lock);
0037
0038 static DEFINE_IDA(ipc_ida);
0039
0040 static unsigned int ksmbd_tools_pid;
0041
0042 static bool ksmbd_ipc_validate_version(struct genl_info *m)
0043 {
0044 if (m->genlhdr->version != KSMBD_GENL_VERSION) {
0045 pr_err("%s. ksmbd: %d, kernel module: %d. %s.\n",
0046 "Daemon and kernel module version mismatch",
0047 m->genlhdr->version,
0048 KSMBD_GENL_VERSION,
0049 "User-space ksmbd should terminate");
0050 return false;
0051 }
0052 return true;
0053 }
0054
0055 struct ksmbd_ipc_msg {
0056 unsigned int type;
0057 unsigned int sz;
0058 unsigned char payload[];
0059 };
0060
0061 struct ipc_msg_table_entry {
0062 unsigned int handle;
0063 unsigned int type;
0064 wait_queue_head_t wait;
0065 struct hlist_node ipc_table_hlist;
0066
0067 void *response;
0068 };
0069
0070 static struct delayed_work ipc_timer_work;
0071
0072 static int handle_startup_event(struct sk_buff *skb, struct genl_info *info);
0073 static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info);
0074 static int handle_generic_event(struct sk_buff *skb, struct genl_info *info);
0075 static int ksmbd_ipc_heartbeat_request(void);
0076
0077 static const struct nla_policy ksmbd_nl_policy[KSMBD_EVENT_MAX] = {
0078 [KSMBD_EVENT_UNSPEC] = {
0079 .len = 0,
0080 },
0081 [KSMBD_EVENT_HEARTBEAT_REQUEST] = {
0082 .len = sizeof(struct ksmbd_heartbeat),
0083 },
0084 [KSMBD_EVENT_STARTING_UP] = {
0085 .len = sizeof(struct ksmbd_startup_request),
0086 },
0087 [KSMBD_EVENT_SHUTTING_DOWN] = {
0088 .len = sizeof(struct ksmbd_shutdown_request),
0089 },
0090 [KSMBD_EVENT_LOGIN_REQUEST] = {
0091 .len = sizeof(struct ksmbd_login_request),
0092 },
0093 [KSMBD_EVENT_LOGIN_RESPONSE] = {
0094 .len = sizeof(struct ksmbd_login_response),
0095 },
0096 [KSMBD_EVENT_SHARE_CONFIG_REQUEST] = {
0097 .len = sizeof(struct ksmbd_share_config_request),
0098 },
0099 [KSMBD_EVENT_SHARE_CONFIG_RESPONSE] = {
0100 .len = sizeof(struct ksmbd_share_config_response),
0101 },
0102 [KSMBD_EVENT_TREE_CONNECT_REQUEST] = {
0103 .len = sizeof(struct ksmbd_tree_connect_request),
0104 },
0105 [KSMBD_EVENT_TREE_CONNECT_RESPONSE] = {
0106 .len = sizeof(struct ksmbd_tree_connect_response),
0107 },
0108 [KSMBD_EVENT_TREE_DISCONNECT_REQUEST] = {
0109 .len = sizeof(struct ksmbd_tree_disconnect_request),
0110 },
0111 [KSMBD_EVENT_LOGOUT_REQUEST] = {
0112 .len = sizeof(struct ksmbd_logout_request),
0113 },
0114 [KSMBD_EVENT_RPC_REQUEST] = {
0115 },
0116 [KSMBD_EVENT_RPC_RESPONSE] = {
0117 },
0118 [KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST] = {
0119 },
0120 [KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE] = {
0121 },
0122 };
0123
0124 static struct genl_ops ksmbd_genl_ops[] = {
0125 {
0126 .cmd = KSMBD_EVENT_UNSPEC,
0127 .doit = handle_unsupported_event,
0128 },
0129 {
0130 .cmd = KSMBD_EVENT_HEARTBEAT_REQUEST,
0131 .doit = handle_unsupported_event,
0132 },
0133 {
0134 .cmd = KSMBD_EVENT_STARTING_UP,
0135 .doit = handle_startup_event,
0136 },
0137 {
0138 .cmd = KSMBD_EVENT_SHUTTING_DOWN,
0139 .doit = handle_unsupported_event,
0140 },
0141 {
0142 .cmd = KSMBD_EVENT_LOGIN_REQUEST,
0143 .doit = handle_unsupported_event,
0144 },
0145 {
0146 .cmd = KSMBD_EVENT_LOGIN_RESPONSE,
0147 .doit = handle_generic_event,
0148 },
0149 {
0150 .cmd = KSMBD_EVENT_SHARE_CONFIG_REQUEST,
0151 .doit = handle_unsupported_event,
0152 },
0153 {
0154 .cmd = KSMBD_EVENT_SHARE_CONFIG_RESPONSE,
0155 .doit = handle_generic_event,
0156 },
0157 {
0158 .cmd = KSMBD_EVENT_TREE_CONNECT_REQUEST,
0159 .doit = handle_unsupported_event,
0160 },
0161 {
0162 .cmd = KSMBD_EVENT_TREE_CONNECT_RESPONSE,
0163 .doit = handle_generic_event,
0164 },
0165 {
0166 .cmd = KSMBD_EVENT_TREE_DISCONNECT_REQUEST,
0167 .doit = handle_unsupported_event,
0168 },
0169 {
0170 .cmd = KSMBD_EVENT_LOGOUT_REQUEST,
0171 .doit = handle_unsupported_event,
0172 },
0173 {
0174 .cmd = KSMBD_EVENT_RPC_REQUEST,
0175 .doit = handle_unsupported_event,
0176 },
0177 {
0178 .cmd = KSMBD_EVENT_RPC_RESPONSE,
0179 .doit = handle_generic_event,
0180 },
0181 {
0182 .cmd = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST,
0183 .doit = handle_unsupported_event,
0184 },
0185 {
0186 .cmd = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE,
0187 .doit = handle_generic_event,
0188 },
0189 };
0190
0191 static struct genl_family ksmbd_genl_family = {
0192 .name = KSMBD_GENL_NAME,
0193 .version = KSMBD_GENL_VERSION,
0194 .hdrsize = 0,
0195 .maxattr = KSMBD_EVENT_MAX,
0196 .netnsok = true,
0197 .module = THIS_MODULE,
0198 .ops = ksmbd_genl_ops,
0199 .n_ops = ARRAY_SIZE(ksmbd_genl_ops),
0200 };
0201
0202 static void ksmbd_nl_init_fixup(void)
0203 {
0204 int i;
0205
0206 for (i = 0; i < ARRAY_SIZE(ksmbd_genl_ops); i++)
0207 ksmbd_genl_ops[i].validate = GENL_DONT_VALIDATE_STRICT |
0208 GENL_DONT_VALIDATE_DUMP;
0209
0210 ksmbd_genl_family.policy = ksmbd_nl_policy;
0211 }
0212
0213 static int rpc_context_flags(struct ksmbd_session *sess)
0214 {
0215 if (user_guest(sess->user))
0216 return KSMBD_RPC_RESTRICTED_CONTEXT;
0217 return 0;
0218 }
0219
0220 static void ipc_update_last_active(void)
0221 {
0222 if (server_conf.ipc_timeout)
0223 server_conf.ipc_last_active = jiffies;
0224 }
0225
0226 static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz)
0227 {
0228 struct ksmbd_ipc_msg *msg;
0229 size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg);
0230
0231 msg = kvmalloc(msg_sz, GFP_KERNEL | __GFP_ZERO);
0232 if (msg)
0233 msg->sz = sz;
0234 return msg;
0235 }
0236
0237 static void ipc_msg_free(struct ksmbd_ipc_msg *msg)
0238 {
0239 kvfree(msg);
0240 }
0241
0242 static void ipc_msg_handle_free(int handle)
0243 {
0244 if (handle >= 0)
0245 ksmbd_release_id(&ipc_ida, handle);
0246 }
0247
0248 static int handle_response(int type, void *payload, size_t sz)
0249 {
0250 unsigned int handle = *(unsigned int *)payload;
0251 struct ipc_msg_table_entry *entry;
0252 int ret = 0;
0253
0254 ipc_update_last_active();
0255 down_read(&ipc_msg_table_lock);
0256 hash_for_each_possible(ipc_msg_table, entry, ipc_table_hlist, handle) {
0257 if (handle != entry->handle)
0258 continue;
0259
0260 entry->response = NULL;
0261
0262
0263
0264
0265 if (entry->type + 1 != type) {
0266 pr_err("Waiting for IPC type %d, got %d. Ignore.\n",
0267 entry->type + 1, type);
0268 }
0269
0270 entry->response = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
0271 if (!entry->response) {
0272 ret = -ENOMEM;
0273 break;
0274 }
0275
0276 memcpy(entry->response, payload, sz);
0277 wake_up_interruptible(&entry->wait);
0278 ret = 0;
0279 break;
0280 }
0281 up_read(&ipc_msg_table_lock);
0282
0283 return ret;
0284 }
0285
0286 static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
0287 {
0288 int ret;
0289
0290 ksmbd_set_fd_limit(req->file_max);
0291 server_conf.flags = req->flags;
0292 server_conf.signing = req->signing;
0293 server_conf.tcp_port = req->tcp_port;
0294 server_conf.ipc_timeout = req->ipc_timeout * HZ;
0295 server_conf.deadtime = req->deadtime * SMB_ECHO_INTERVAL;
0296 server_conf.share_fake_fscaps = req->share_fake_fscaps;
0297 ksmbd_init_domain(req->sub_auth);
0298
0299 if (req->smb2_max_read)
0300 init_smb2_max_read_size(req->smb2_max_read);
0301 if (req->smb2_max_write)
0302 init_smb2_max_write_size(req->smb2_max_write);
0303 if (req->smb2_max_trans)
0304 init_smb2_max_trans_size(req->smb2_max_trans);
0305 if (req->smb2_max_credits)
0306 init_smb2_max_credits(req->smb2_max_credits);
0307 if (req->smbd_max_io_size)
0308 init_smbd_max_io_size(req->smbd_max_io_size);
0309
0310 ret = ksmbd_set_netbios_name(req->netbios_name);
0311 ret |= ksmbd_set_server_string(req->server_string);
0312 ret |= ksmbd_set_work_group(req->work_group);
0313 ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
0314 req->ifc_list_sz);
0315 if (ret) {
0316 pr_err("Server configuration error: %s %s %s\n",
0317 req->netbios_name, req->server_string,
0318 req->work_group);
0319 return ret;
0320 }
0321
0322 if (req->min_prot[0]) {
0323 ret = ksmbd_lookup_protocol_idx(req->min_prot);
0324 if (ret >= 0)
0325 server_conf.min_protocol = ret;
0326 }
0327 if (req->max_prot[0]) {
0328 ret = ksmbd_lookup_protocol_idx(req->max_prot);
0329 if (ret >= 0)
0330 server_conf.max_protocol = ret;
0331 }
0332
0333 if (server_conf.ipc_timeout)
0334 schedule_delayed_work(&ipc_timer_work, server_conf.ipc_timeout);
0335 return 0;
0336 }
0337
0338 static int handle_startup_event(struct sk_buff *skb, struct genl_info *info)
0339 {
0340 int ret = 0;
0341
0342 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
0343 if (!netlink_capable(skb, CAP_NET_ADMIN))
0344 return -EPERM;
0345 #endif
0346
0347 if (!ksmbd_ipc_validate_version(info))
0348 return -EINVAL;
0349
0350 if (!info->attrs[KSMBD_EVENT_STARTING_UP])
0351 return -EINVAL;
0352
0353 mutex_lock(&startup_lock);
0354 if (!ksmbd_server_configurable()) {
0355 mutex_unlock(&startup_lock);
0356 pr_err("Server reset is in progress, can't start daemon\n");
0357 return -EINVAL;
0358 }
0359
0360 if (ksmbd_tools_pid) {
0361 if (ksmbd_ipc_heartbeat_request() == 0) {
0362 ret = -EINVAL;
0363 goto out;
0364 }
0365
0366 pr_err("Reconnect to a new user space daemon\n");
0367 } else {
0368 struct ksmbd_startup_request *req;
0369
0370 req = nla_data(info->attrs[info->genlhdr->cmd]);
0371 ret = ipc_server_config_on_startup(req);
0372 if (ret)
0373 goto out;
0374 server_queue_ctrl_init_work();
0375 }
0376
0377 ksmbd_tools_pid = info->snd_portid;
0378 ipc_update_last_active();
0379
0380 out:
0381 mutex_unlock(&startup_lock);
0382 return ret;
0383 }
0384
0385 static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info)
0386 {
0387 pr_err("Unknown IPC event: %d, ignore.\n", info->genlhdr->cmd);
0388 return -EINVAL;
0389 }
0390
0391 static int handle_generic_event(struct sk_buff *skb, struct genl_info *info)
0392 {
0393 void *payload;
0394 int sz;
0395 int type = info->genlhdr->cmd;
0396
0397 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
0398 if (!netlink_capable(skb, CAP_NET_ADMIN))
0399 return -EPERM;
0400 #endif
0401
0402 if (type >= KSMBD_EVENT_MAX) {
0403 WARN_ON(1);
0404 return -EINVAL;
0405 }
0406
0407 if (!ksmbd_ipc_validate_version(info))
0408 return -EINVAL;
0409
0410 if (!info->attrs[type])
0411 return -EINVAL;
0412
0413 payload = nla_data(info->attrs[info->genlhdr->cmd]);
0414 sz = nla_len(info->attrs[info->genlhdr->cmd]);
0415 return handle_response(type, payload, sz);
0416 }
0417
0418 static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
0419 {
0420 struct genlmsghdr *nlh;
0421 struct sk_buff *skb;
0422 int ret = -EINVAL;
0423
0424 if (!ksmbd_tools_pid)
0425 return ret;
0426
0427 skb = genlmsg_new(msg->sz, GFP_KERNEL);
0428 if (!skb)
0429 return -ENOMEM;
0430
0431 nlh = genlmsg_put(skb, 0, 0, &ksmbd_genl_family, 0, msg->type);
0432 if (!nlh)
0433 goto out;
0434
0435 ret = nla_put(skb, msg->type, msg->sz, msg->payload);
0436 if (ret) {
0437 genlmsg_cancel(skb, nlh);
0438 goto out;
0439 }
0440
0441 genlmsg_end(skb, nlh);
0442 ret = genlmsg_unicast(&init_net, skb, ksmbd_tools_pid);
0443 if (!ret)
0444 ipc_update_last_active();
0445 return ret;
0446
0447 out:
0448 nlmsg_free(skb);
0449 return ret;
0450 }
0451
0452 static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle)
0453 {
0454 struct ipc_msg_table_entry entry;
0455 int ret;
0456
0457 if ((int)handle < 0)
0458 return NULL;
0459
0460 entry.type = msg->type;
0461 entry.response = NULL;
0462 init_waitqueue_head(&entry.wait);
0463
0464 down_write(&ipc_msg_table_lock);
0465 entry.handle = handle;
0466 hash_add(ipc_msg_table, &entry.ipc_table_hlist, entry.handle);
0467 up_write(&ipc_msg_table_lock);
0468
0469 ret = ipc_msg_send(msg);
0470 if (ret)
0471 goto out;
0472
0473 ret = wait_event_interruptible_timeout(entry.wait,
0474 entry.response != NULL,
0475 IPC_WAIT_TIMEOUT);
0476 out:
0477 down_write(&ipc_msg_table_lock);
0478 hash_del(&entry.ipc_table_hlist);
0479 up_write(&ipc_msg_table_lock);
0480 return entry.response;
0481 }
0482
0483 static int ksmbd_ipc_heartbeat_request(void)
0484 {
0485 struct ksmbd_ipc_msg *msg;
0486 int ret;
0487
0488 msg = ipc_msg_alloc(sizeof(struct ksmbd_heartbeat));
0489 if (!msg)
0490 return -EINVAL;
0491
0492 msg->type = KSMBD_EVENT_HEARTBEAT_REQUEST;
0493 ret = ipc_msg_send(msg);
0494 ipc_msg_free(msg);
0495 return ret;
0496 }
0497
0498 struct ksmbd_login_response *ksmbd_ipc_login_request(const char *account)
0499 {
0500 struct ksmbd_ipc_msg *msg;
0501 struct ksmbd_login_request *req;
0502 struct ksmbd_login_response *resp;
0503
0504 if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
0505 return NULL;
0506
0507 msg = ipc_msg_alloc(sizeof(struct ksmbd_login_request));
0508 if (!msg)
0509 return NULL;
0510
0511 msg->type = KSMBD_EVENT_LOGIN_REQUEST;
0512 req = (struct ksmbd_login_request *)msg->payload;
0513 req->handle = ksmbd_acquire_id(&ipc_ida);
0514 strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
0515
0516 resp = ipc_msg_send_request(msg, req->handle);
0517 ipc_msg_handle_free(req->handle);
0518 ipc_msg_free(msg);
0519 return resp;
0520 }
0521
0522 struct ksmbd_spnego_authen_response *
0523 ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len)
0524 {
0525 struct ksmbd_ipc_msg *msg;
0526 struct ksmbd_spnego_authen_request *req;
0527 struct ksmbd_spnego_authen_response *resp;
0528
0529 msg = ipc_msg_alloc(sizeof(struct ksmbd_spnego_authen_request) +
0530 blob_len + 1);
0531 if (!msg)
0532 return NULL;
0533
0534 msg->type = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST;
0535 req = (struct ksmbd_spnego_authen_request *)msg->payload;
0536 req->handle = ksmbd_acquire_id(&ipc_ida);
0537 req->spnego_blob_len = blob_len;
0538 memcpy(req->spnego_blob, spnego_blob, blob_len);
0539
0540 resp = ipc_msg_send_request(msg, req->handle);
0541 ipc_msg_handle_free(req->handle);
0542 ipc_msg_free(msg);
0543 return resp;
0544 }
0545
0546 struct ksmbd_tree_connect_response *
0547 ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
0548 struct ksmbd_share_config *share,
0549 struct ksmbd_tree_connect *tree_conn,
0550 struct sockaddr *peer_addr)
0551 {
0552 struct ksmbd_ipc_msg *msg;
0553 struct ksmbd_tree_connect_request *req;
0554 struct ksmbd_tree_connect_response *resp;
0555
0556 if (strlen(user_name(sess->user)) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
0557 return NULL;
0558
0559 if (strlen(share->name) >= KSMBD_REQ_MAX_SHARE_NAME)
0560 return NULL;
0561
0562 msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_connect_request));
0563 if (!msg)
0564 return NULL;
0565
0566 msg->type = KSMBD_EVENT_TREE_CONNECT_REQUEST;
0567 req = (struct ksmbd_tree_connect_request *)msg->payload;
0568
0569 req->handle = ksmbd_acquire_id(&ipc_ida);
0570 req->account_flags = sess->user->flags;
0571 req->session_id = sess->id;
0572 req->connect_id = tree_conn->id;
0573 strscpy(req->account, user_name(sess->user), KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
0574 strscpy(req->share, share->name, KSMBD_REQ_MAX_SHARE_NAME);
0575 snprintf(req->peer_addr, sizeof(req->peer_addr), "%pIS", peer_addr);
0576
0577 if (peer_addr->sa_family == AF_INET6)
0578 req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_IPV6;
0579 if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
0580 req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_SMB2;
0581
0582 resp = ipc_msg_send_request(msg, req->handle);
0583 ipc_msg_handle_free(req->handle);
0584 ipc_msg_free(msg);
0585 return resp;
0586 }
0587
0588 int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
0589 unsigned long long connect_id)
0590 {
0591 struct ksmbd_ipc_msg *msg;
0592 struct ksmbd_tree_disconnect_request *req;
0593 int ret;
0594
0595 msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_disconnect_request));
0596 if (!msg)
0597 return -ENOMEM;
0598
0599 msg->type = KSMBD_EVENT_TREE_DISCONNECT_REQUEST;
0600 req = (struct ksmbd_tree_disconnect_request *)msg->payload;
0601 req->session_id = session_id;
0602 req->connect_id = connect_id;
0603
0604 ret = ipc_msg_send(msg);
0605 ipc_msg_free(msg);
0606 return ret;
0607 }
0608
0609 int ksmbd_ipc_logout_request(const char *account, int flags)
0610 {
0611 struct ksmbd_ipc_msg *msg;
0612 struct ksmbd_logout_request *req;
0613 int ret;
0614
0615 if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
0616 return -EINVAL;
0617
0618 msg = ipc_msg_alloc(sizeof(struct ksmbd_logout_request));
0619 if (!msg)
0620 return -ENOMEM;
0621
0622 msg->type = KSMBD_EVENT_LOGOUT_REQUEST;
0623 req = (struct ksmbd_logout_request *)msg->payload;
0624 req->account_flags = flags;
0625 strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
0626
0627 ret = ipc_msg_send(msg);
0628 ipc_msg_free(msg);
0629 return ret;
0630 }
0631
0632 struct ksmbd_share_config_response *
0633 ksmbd_ipc_share_config_request(const char *name)
0634 {
0635 struct ksmbd_ipc_msg *msg;
0636 struct ksmbd_share_config_request *req;
0637 struct ksmbd_share_config_response *resp;
0638
0639 if (strlen(name) >= KSMBD_REQ_MAX_SHARE_NAME)
0640 return NULL;
0641
0642 msg = ipc_msg_alloc(sizeof(struct ksmbd_share_config_request));
0643 if (!msg)
0644 return NULL;
0645
0646 msg->type = KSMBD_EVENT_SHARE_CONFIG_REQUEST;
0647 req = (struct ksmbd_share_config_request *)msg->payload;
0648 req->handle = ksmbd_acquire_id(&ipc_ida);
0649 strscpy(req->share_name, name, KSMBD_REQ_MAX_SHARE_NAME);
0650
0651 resp = ipc_msg_send_request(msg, req->handle);
0652 ipc_msg_handle_free(req->handle);
0653 ipc_msg_free(msg);
0654 return resp;
0655 }
0656
0657 struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle)
0658 {
0659 struct ksmbd_ipc_msg *msg;
0660 struct ksmbd_rpc_command *req;
0661 struct ksmbd_rpc_command *resp;
0662
0663 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
0664 if (!msg)
0665 return NULL;
0666
0667 msg->type = KSMBD_EVENT_RPC_REQUEST;
0668 req = (struct ksmbd_rpc_command *)msg->payload;
0669 req->handle = handle;
0670 req->flags = ksmbd_session_rpc_method(sess, handle);
0671 req->flags |= KSMBD_RPC_OPEN_METHOD;
0672 req->payload_sz = 0;
0673
0674 resp = ipc_msg_send_request(msg, req->handle);
0675 ipc_msg_free(msg);
0676 return resp;
0677 }
0678
0679 struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle)
0680 {
0681 struct ksmbd_ipc_msg *msg;
0682 struct ksmbd_rpc_command *req;
0683 struct ksmbd_rpc_command *resp;
0684
0685 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
0686 if (!msg)
0687 return NULL;
0688
0689 msg->type = KSMBD_EVENT_RPC_REQUEST;
0690 req = (struct ksmbd_rpc_command *)msg->payload;
0691 req->handle = handle;
0692 req->flags = ksmbd_session_rpc_method(sess, handle);
0693 req->flags |= KSMBD_RPC_CLOSE_METHOD;
0694 req->payload_sz = 0;
0695
0696 resp = ipc_msg_send_request(msg, req->handle);
0697 ipc_msg_free(msg);
0698 return resp;
0699 }
0700
0701 struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle,
0702 void *payload, size_t payload_sz)
0703 {
0704 struct ksmbd_ipc_msg *msg;
0705 struct ksmbd_rpc_command *req;
0706 struct ksmbd_rpc_command *resp;
0707
0708 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
0709 if (!msg)
0710 return NULL;
0711
0712 msg->type = KSMBD_EVENT_RPC_REQUEST;
0713 req = (struct ksmbd_rpc_command *)msg->payload;
0714 req->handle = handle;
0715 req->flags = ksmbd_session_rpc_method(sess, handle);
0716 req->flags |= rpc_context_flags(sess);
0717 req->flags |= KSMBD_RPC_WRITE_METHOD;
0718 req->payload_sz = payload_sz;
0719 memcpy(req->payload, payload, payload_sz);
0720
0721 resp = ipc_msg_send_request(msg, req->handle);
0722 ipc_msg_free(msg);
0723 return resp;
0724 }
0725
0726 struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)
0727 {
0728 struct ksmbd_ipc_msg *msg;
0729 struct ksmbd_rpc_command *req;
0730 struct ksmbd_rpc_command *resp;
0731
0732 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
0733 if (!msg)
0734 return NULL;
0735
0736 msg->type = KSMBD_EVENT_RPC_REQUEST;
0737 req = (struct ksmbd_rpc_command *)msg->payload;
0738 req->handle = handle;
0739 req->flags = ksmbd_session_rpc_method(sess, handle);
0740 req->flags |= rpc_context_flags(sess);
0741 req->flags |= KSMBD_RPC_READ_METHOD;
0742 req->payload_sz = 0;
0743
0744 resp = ipc_msg_send_request(msg, req->handle);
0745 ipc_msg_free(msg);
0746 return resp;
0747 }
0748
0749 struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle,
0750 void *payload, size_t payload_sz)
0751 {
0752 struct ksmbd_ipc_msg *msg;
0753 struct ksmbd_rpc_command *req;
0754 struct ksmbd_rpc_command *resp;
0755
0756 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
0757 if (!msg)
0758 return NULL;
0759
0760 msg->type = KSMBD_EVENT_RPC_REQUEST;
0761 req = (struct ksmbd_rpc_command *)msg->payload;
0762 req->handle = handle;
0763 req->flags = ksmbd_session_rpc_method(sess, handle);
0764 req->flags |= rpc_context_flags(sess);
0765 req->flags |= KSMBD_RPC_IOCTL_METHOD;
0766 req->payload_sz = payload_sz;
0767 memcpy(req->payload, payload, payload_sz);
0768
0769 resp = ipc_msg_send_request(msg, req->handle);
0770 ipc_msg_free(msg);
0771 return resp;
0772 }
0773
0774 struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payload,
0775 size_t payload_sz)
0776 {
0777 struct ksmbd_ipc_msg *msg;
0778 struct ksmbd_rpc_command *req;
0779 struct ksmbd_rpc_command *resp;
0780
0781 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
0782 if (!msg)
0783 return NULL;
0784
0785 msg->type = KSMBD_EVENT_RPC_REQUEST;
0786 req = (struct ksmbd_rpc_command *)msg->payload;
0787 req->handle = ksmbd_acquire_id(&ipc_ida);
0788 req->flags = rpc_context_flags(sess);
0789 req->flags |= KSMBD_RPC_RAP_METHOD;
0790 req->payload_sz = payload_sz;
0791 memcpy(req->payload, payload, payload_sz);
0792
0793 resp = ipc_msg_send_request(msg, req->handle);
0794 ipc_msg_handle_free(req->handle);
0795 ipc_msg_free(msg);
0796 return resp;
0797 }
0798
0799 static int __ipc_heartbeat(void)
0800 {
0801 unsigned long delta;
0802
0803 if (!ksmbd_server_running())
0804 return 0;
0805
0806 if (time_after(jiffies, server_conf.ipc_last_active)) {
0807 delta = (jiffies - server_conf.ipc_last_active);
0808 } else {
0809 ipc_update_last_active();
0810 schedule_delayed_work(&ipc_timer_work,
0811 server_conf.ipc_timeout);
0812 return 0;
0813 }
0814
0815 if (delta < server_conf.ipc_timeout) {
0816 schedule_delayed_work(&ipc_timer_work,
0817 server_conf.ipc_timeout - delta);
0818 return 0;
0819 }
0820
0821 if (ksmbd_ipc_heartbeat_request() == 0) {
0822 schedule_delayed_work(&ipc_timer_work,
0823 server_conf.ipc_timeout);
0824 return 0;
0825 }
0826
0827 mutex_lock(&startup_lock);
0828 WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
0829 server_conf.ipc_last_active = 0;
0830 ksmbd_tools_pid = 0;
0831 pr_err("No IPC daemon response for %lus\n", delta / HZ);
0832 mutex_unlock(&startup_lock);
0833 return -EINVAL;
0834 }
0835
0836 static void ipc_timer_heartbeat(struct work_struct *w)
0837 {
0838 if (__ipc_heartbeat())
0839 server_queue_ctrl_reset_work();
0840 }
0841
0842 int ksmbd_ipc_id_alloc(void)
0843 {
0844 return ksmbd_acquire_id(&ipc_ida);
0845 }
0846
0847 void ksmbd_rpc_id_free(int handle)
0848 {
0849 ksmbd_release_id(&ipc_ida, handle);
0850 }
0851
0852 void ksmbd_ipc_release(void)
0853 {
0854 cancel_delayed_work_sync(&ipc_timer_work);
0855 genl_unregister_family(&ksmbd_genl_family);
0856 }
0857
0858 void ksmbd_ipc_soft_reset(void)
0859 {
0860 mutex_lock(&startup_lock);
0861 ksmbd_tools_pid = 0;
0862 cancel_delayed_work_sync(&ipc_timer_work);
0863 mutex_unlock(&startup_lock);
0864 }
0865
0866 int ksmbd_ipc_init(void)
0867 {
0868 int ret = 0;
0869
0870 ksmbd_nl_init_fixup();
0871 INIT_DELAYED_WORK(&ipc_timer_work, ipc_timer_heartbeat);
0872
0873 ret = genl_register_family(&ksmbd_genl_family);
0874 if (ret) {
0875 pr_err("Failed to register KSMBD netlink interface %d\n", ret);
0876 cancel_delayed_work_sync(&ipc_timer_work);
0877 }
0878
0879 return ret;
0880 }