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
ksmbd_ipc_validate_version(struct genl_info * m)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
ksmbd_nl_init_fixup(void)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
rpc_context_flags(struct ksmbd_session * sess)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
ipc_update_last_active(void)222 static void ipc_update_last_active(void)
223 {
224 if (server_conf.ipc_timeout)
225 server_conf.ipc_last_active = jiffies;
226 }
227
ipc_msg_alloc(size_t sz)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
ipc_msg_free(struct ksmbd_ipc_msg * msg)239 static void ipc_msg_free(struct ksmbd_ipc_msg *msg)
240 {
241 kvfree(msg);
242 }
243
ipc_msg_handle_free(int handle)244 static void ipc_msg_handle_free(int handle)
245 {
246 if (handle >= 0)
247 ksmbd_release_id(&ipc_ida, handle);
248 }
249
handle_response(int type,void * payload,size_t sz)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 continue;
271 }
272
273 entry->response = kvzalloc(sz, GFP_KERNEL);
274 if (!entry->response) {
275 ret = -ENOMEM;
276 break;
277 }
278
279 memcpy(entry->response, payload, sz);
280 entry->msg_sz = sz;
281 wake_up_interruptible(&entry->wait);
282 ret = 0;
283 break;
284 }
285 up_read(&ipc_msg_table_lock);
286
287 return ret;
288 }
289
ipc_server_config_on_startup(struct ksmbd_startup_request * req)290 static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
291 {
292 int ret;
293
294 ksmbd_set_fd_limit(req->file_max);
295 server_conf.flags = req->flags;
296 server_conf.signing = req->signing;
297 server_conf.tcp_port = req->tcp_port;
298 server_conf.ipc_timeout = req->ipc_timeout * HZ;
299 if (check_mul_overflow(req->deadtime, SMB_ECHO_INTERVAL,
300 &server_conf.deadtime)) {
301 ret = -EINVAL;
302 goto out;
303 }
304 server_conf.share_fake_fscaps = req->share_fake_fscaps;
305 ksmbd_init_domain(req->sub_auth);
306
307 if (req->smb2_max_read)
308 init_smb2_max_read_size(req->smb2_max_read);
309 if (req->smb2_max_write)
310 init_smb2_max_write_size(req->smb2_max_write);
311 if (req->smb2_max_trans)
312 init_smb2_max_trans_size(req->smb2_max_trans);
313 if (req->smb2_max_credits) {
314 init_smb2_max_credits(req->smb2_max_credits);
315 server_conf.max_inflight_req =
316 req->smb2_max_credits;
317 }
318 if (req->smbd_max_io_size)
319 init_smbd_max_io_size(req->smbd_max_io_size);
320
321 if (req->max_connections)
322 server_conf.max_connections = req->max_connections;
323
324 ret = ksmbd_set_netbios_name(req->netbios_name);
325 ret |= ksmbd_set_server_string(req->server_string);
326 ret |= ksmbd_set_work_group(req->work_group);
327 ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
328 req->ifc_list_sz);
329 out:
330 if (ret) {
331 pr_err("Server configuration error: %s %s %s\n",
332 req->netbios_name, req->server_string,
333 req->work_group);
334 return ret;
335 }
336
337 if (req->min_prot[0]) {
338 ret = ksmbd_lookup_protocol_idx(req->min_prot);
339 if (ret >= 0)
340 server_conf.min_protocol = ret;
341 }
342 if (req->max_prot[0]) {
343 ret = ksmbd_lookup_protocol_idx(req->max_prot);
344 if (ret >= 0)
345 server_conf.max_protocol = ret;
346 }
347
348 if (server_conf.ipc_timeout)
349 schedule_delayed_work(&ipc_timer_work, server_conf.ipc_timeout);
350 return 0;
351 }
352
handle_startup_event(struct sk_buff * skb,struct genl_info * info)353 static int handle_startup_event(struct sk_buff *skb, struct genl_info *info)
354 {
355 int ret = 0;
356
357 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
358 if (!netlink_capable(skb, CAP_NET_ADMIN))
359 return -EPERM;
360 #endif
361
362 if (!ksmbd_ipc_validate_version(info))
363 return -EINVAL;
364
365 if (!info->attrs[KSMBD_EVENT_STARTING_UP])
366 return -EINVAL;
367
368 mutex_lock(&startup_lock);
369 if (!ksmbd_server_configurable()) {
370 mutex_unlock(&startup_lock);
371 pr_err("Server reset is in progress, can't start daemon\n");
372 return -EINVAL;
373 }
374
375 if (ksmbd_tools_pid) {
376 if (ksmbd_ipc_heartbeat_request() == 0) {
377 ret = -EINVAL;
378 goto out;
379 }
380
381 pr_err("Reconnect to a new user space daemon\n");
382 } else {
383 struct ksmbd_startup_request *req;
384
385 req = nla_data(info->attrs[info->genlhdr->cmd]);
386 ret = ipc_server_config_on_startup(req);
387 if (ret)
388 goto out;
389 server_queue_ctrl_init_work();
390 }
391
392 ksmbd_tools_pid = info->snd_portid;
393 ipc_update_last_active();
394
395 out:
396 mutex_unlock(&startup_lock);
397 return ret;
398 }
399
handle_unsupported_event(struct sk_buff * skb,struct genl_info * info)400 static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info)
401 {
402 pr_err("Unknown IPC event: %d, ignore.\n", info->genlhdr->cmd);
403 return -EINVAL;
404 }
405
handle_generic_event(struct sk_buff * skb,struct genl_info * info)406 static int handle_generic_event(struct sk_buff *skb, struct genl_info *info)
407 {
408 void *payload;
409 int sz;
410 int type = info->genlhdr->cmd;
411
412 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
413 if (!netlink_capable(skb, CAP_NET_ADMIN))
414 return -EPERM;
415 #endif
416
417 if (type > KSMBD_EVENT_MAX) {
418 WARN_ON(1);
419 return -EINVAL;
420 }
421
422 if (!ksmbd_ipc_validate_version(info))
423 return -EINVAL;
424
425 if (!info->attrs[type])
426 return -EINVAL;
427
428 payload = nla_data(info->attrs[info->genlhdr->cmd]);
429 sz = nla_len(info->attrs[info->genlhdr->cmd]);
430 return handle_response(type, payload, sz);
431 }
432
ipc_msg_send(struct ksmbd_ipc_msg * msg)433 static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
434 {
435 struct genlmsghdr *nlh;
436 struct sk_buff *skb;
437 int ret = -EINVAL;
438
439 if (!ksmbd_tools_pid)
440 return ret;
441
442 skb = genlmsg_new(msg->sz, GFP_KERNEL);
443 if (!skb)
444 return -ENOMEM;
445
446 nlh = genlmsg_put(skb, 0, 0, &ksmbd_genl_family, 0, msg->type);
447 if (!nlh)
448 goto out;
449
450 ret = nla_put(skb, msg->type, msg->sz, msg->payload);
451 if (ret) {
452 genlmsg_cancel(skb, nlh);
453 goto out;
454 }
455
456 genlmsg_end(skb, nlh);
457 ret = genlmsg_unicast(&init_net, skb, ksmbd_tools_pid);
458 if (!ret)
459 ipc_update_last_active();
460 return ret;
461
462 out:
463 nlmsg_free(skb);
464 return ret;
465 }
466
ipc_validate_msg(struct ipc_msg_table_entry * entry)467 static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
468 {
469 unsigned int msg_sz = entry->msg_sz;
470
471 if (entry->type == KSMBD_EVENT_RPC_REQUEST) {
472 struct ksmbd_rpc_command *resp = entry->response;
473
474 msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;
475 } else if (entry->type == KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST) {
476 struct ksmbd_spnego_authen_response *resp = entry->response;
477
478 msg_sz = sizeof(struct ksmbd_spnego_authen_response) +
479 resp->session_key_len + resp->spnego_blob_len;
480 } else if (entry->type == KSMBD_EVENT_SHARE_CONFIG_REQUEST) {
481 struct ksmbd_share_config_response *resp = entry->response;
482
483 if (resp->payload_sz) {
484 if (resp->payload_sz < resp->veto_list_sz)
485 return -EINVAL;
486
487 msg_sz = sizeof(struct ksmbd_share_config_response) +
488 resp->payload_sz;
489 }
490 }
491
492 return entry->msg_sz != msg_sz ? -EINVAL : 0;
493 }
494
ipc_msg_send_request(struct ksmbd_ipc_msg * msg,unsigned int handle)495 static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle)
496 {
497 struct ipc_msg_table_entry entry;
498 int ret;
499
500 if ((int)handle < 0)
501 return NULL;
502
503 entry.type = msg->type;
504 entry.response = NULL;
505 init_waitqueue_head(&entry.wait);
506
507 down_write(&ipc_msg_table_lock);
508 entry.handle = handle;
509 hash_add(ipc_msg_table, &entry.ipc_table_hlist, entry.handle);
510 up_write(&ipc_msg_table_lock);
511
512 ret = ipc_msg_send(msg);
513 if (ret)
514 goto out;
515
516 ret = wait_event_interruptible_timeout(entry.wait,
517 entry.response != NULL,
518 IPC_WAIT_TIMEOUT);
519 if (entry.response) {
520 ret = ipc_validate_msg(&entry);
521 if (ret) {
522 kvfree(entry.response);
523 entry.response = NULL;
524 }
525 }
526 out:
527 down_write(&ipc_msg_table_lock);
528 hash_del(&entry.ipc_table_hlist);
529 up_write(&ipc_msg_table_lock);
530 return entry.response;
531 }
532
ksmbd_ipc_heartbeat_request(void)533 static int ksmbd_ipc_heartbeat_request(void)
534 {
535 struct ksmbd_ipc_msg *msg;
536 int ret;
537
538 msg = ipc_msg_alloc(sizeof(struct ksmbd_heartbeat));
539 if (!msg)
540 return -EINVAL;
541
542 msg->type = KSMBD_EVENT_HEARTBEAT_REQUEST;
543 ret = ipc_msg_send(msg);
544 ipc_msg_free(msg);
545 return ret;
546 }
547
ksmbd_ipc_login_request(const char * account)548 struct ksmbd_login_response *ksmbd_ipc_login_request(const char *account)
549 {
550 struct ksmbd_ipc_msg *msg;
551 struct ksmbd_login_request *req;
552 struct ksmbd_login_response *resp;
553
554 if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
555 return NULL;
556
557 msg = ipc_msg_alloc(sizeof(struct ksmbd_login_request));
558 if (!msg)
559 return NULL;
560
561 msg->type = KSMBD_EVENT_LOGIN_REQUEST;
562 req = (struct ksmbd_login_request *)msg->payload;
563 req->handle = ksmbd_acquire_id(&ipc_ida);
564 strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
565
566 resp = ipc_msg_send_request(msg, req->handle);
567 ipc_msg_handle_free(req->handle);
568 ipc_msg_free(msg);
569 return resp;
570 }
571
572 struct ksmbd_spnego_authen_response *
ksmbd_ipc_spnego_authen_request(const char * spnego_blob,int blob_len)573 ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len)
574 {
575 struct ksmbd_ipc_msg *msg;
576 struct ksmbd_spnego_authen_request *req;
577 struct ksmbd_spnego_authen_response *resp;
578
579 if (blob_len > KSMBD_IPC_MAX_PAYLOAD)
580 return NULL;
581
582 msg = ipc_msg_alloc(sizeof(struct ksmbd_spnego_authen_request) +
583 blob_len + 1);
584 if (!msg)
585 return NULL;
586
587 msg->type = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST;
588 req = (struct ksmbd_spnego_authen_request *)msg->payload;
589 req->handle = ksmbd_acquire_id(&ipc_ida);
590 req->spnego_blob_len = blob_len;
591 memcpy(req->spnego_blob, spnego_blob, blob_len);
592
593 resp = ipc_msg_send_request(msg, req->handle);
594 ipc_msg_handle_free(req->handle);
595 ipc_msg_free(msg);
596 return resp;
597 }
598
599 struct ksmbd_tree_connect_response *
ksmbd_ipc_tree_connect_request(struct ksmbd_session * sess,struct ksmbd_share_config * share,struct ksmbd_tree_connect * tree_conn,struct sockaddr * peer_addr)600 ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
601 struct ksmbd_share_config *share,
602 struct ksmbd_tree_connect *tree_conn,
603 struct sockaddr *peer_addr)
604 {
605 struct ksmbd_ipc_msg *msg;
606 struct ksmbd_tree_connect_request *req;
607 struct ksmbd_tree_connect_response *resp;
608
609 if (strlen(user_name(sess->user)) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
610 return NULL;
611
612 if (strlen(share->name) >= KSMBD_REQ_MAX_SHARE_NAME)
613 return NULL;
614
615 msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_connect_request));
616 if (!msg)
617 return NULL;
618
619 msg->type = KSMBD_EVENT_TREE_CONNECT_REQUEST;
620 req = (struct ksmbd_tree_connect_request *)msg->payload;
621
622 req->handle = ksmbd_acquire_id(&ipc_ida);
623 req->account_flags = sess->user->flags;
624 req->session_id = sess->id;
625 req->connect_id = tree_conn->id;
626 strscpy(req->account, user_name(sess->user), KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
627 strscpy(req->share, share->name, KSMBD_REQ_MAX_SHARE_NAME);
628 snprintf(req->peer_addr, sizeof(req->peer_addr), "%pIS", peer_addr);
629
630 if (peer_addr->sa_family == AF_INET6)
631 req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_IPV6;
632 if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
633 req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_SMB2;
634
635 resp = ipc_msg_send_request(msg, req->handle);
636 ipc_msg_handle_free(req->handle);
637 ipc_msg_free(msg);
638 return resp;
639 }
640
ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,unsigned long long connect_id)641 int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
642 unsigned long long connect_id)
643 {
644 struct ksmbd_ipc_msg *msg;
645 struct ksmbd_tree_disconnect_request *req;
646 int ret;
647
648 msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_disconnect_request));
649 if (!msg)
650 return -ENOMEM;
651
652 msg->type = KSMBD_EVENT_TREE_DISCONNECT_REQUEST;
653 req = (struct ksmbd_tree_disconnect_request *)msg->payload;
654 req->session_id = session_id;
655 req->connect_id = connect_id;
656
657 ret = ipc_msg_send(msg);
658 ipc_msg_free(msg);
659 return ret;
660 }
661
ksmbd_ipc_logout_request(const char * account,int flags)662 int ksmbd_ipc_logout_request(const char *account, int flags)
663 {
664 struct ksmbd_ipc_msg *msg;
665 struct ksmbd_logout_request *req;
666 int ret;
667
668 if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
669 return -EINVAL;
670
671 msg = ipc_msg_alloc(sizeof(struct ksmbd_logout_request));
672 if (!msg)
673 return -ENOMEM;
674
675 msg->type = KSMBD_EVENT_LOGOUT_REQUEST;
676 req = (struct ksmbd_logout_request *)msg->payload;
677 req->account_flags = flags;
678 strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
679
680 ret = ipc_msg_send(msg);
681 ipc_msg_free(msg);
682 return ret;
683 }
684
685 struct ksmbd_share_config_response *
ksmbd_ipc_share_config_request(const char * name)686 ksmbd_ipc_share_config_request(const char *name)
687 {
688 struct ksmbd_ipc_msg *msg;
689 struct ksmbd_share_config_request *req;
690 struct ksmbd_share_config_response *resp;
691
692 if (strlen(name) >= KSMBD_REQ_MAX_SHARE_NAME)
693 return NULL;
694
695 msg = ipc_msg_alloc(sizeof(struct ksmbd_share_config_request));
696 if (!msg)
697 return NULL;
698
699 msg->type = KSMBD_EVENT_SHARE_CONFIG_REQUEST;
700 req = (struct ksmbd_share_config_request *)msg->payload;
701 req->handle = ksmbd_acquire_id(&ipc_ida);
702 strscpy(req->share_name, name, KSMBD_REQ_MAX_SHARE_NAME);
703
704 resp = ipc_msg_send_request(msg, req->handle);
705 ipc_msg_handle_free(req->handle);
706 ipc_msg_free(msg);
707 return resp;
708 }
709
ksmbd_rpc_open(struct ksmbd_session * sess,int handle)710 struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle)
711 {
712 struct ksmbd_ipc_msg *msg;
713 struct ksmbd_rpc_command *req;
714 struct ksmbd_rpc_command *resp;
715
716 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
717 if (!msg)
718 return NULL;
719
720 msg->type = KSMBD_EVENT_RPC_REQUEST;
721 req = (struct ksmbd_rpc_command *)msg->payload;
722 req->handle = handle;
723 req->flags = ksmbd_session_rpc_method(sess, handle);
724 req->flags |= KSMBD_RPC_OPEN_METHOD;
725 req->payload_sz = 0;
726
727 resp = ipc_msg_send_request(msg, req->handle);
728 ipc_msg_free(msg);
729 return resp;
730 }
731
ksmbd_rpc_close(struct ksmbd_session * sess,int handle)732 struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle)
733 {
734 struct ksmbd_ipc_msg *msg;
735 struct ksmbd_rpc_command *req;
736 struct ksmbd_rpc_command *resp;
737
738 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
739 if (!msg)
740 return NULL;
741
742 msg->type = KSMBD_EVENT_RPC_REQUEST;
743 req = (struct ksmbd_rpc_command *)msg->payload;
744 req->handle = handle;
745 req->flags = ksmbd_session_rpc_method(sess, handle);
746 req->flags |= KSMBD_RPC_CLOSE_METHOD;
747 req->payload_sz = 0;
748
749 resp = ipc_msg_send_request(msg, req->handle);
750 ipc_msg_free(msg);
751 return resp;
752 }
753
ksmbd_rpc_write(struct ksmbd_session * sess,int handle,void * payload,size_t payload_sz)754 struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle,
755 void *payload, size_t payload_sz)
756 {
757 struct ksmbd_ipc_msg *msg;
758 struct ksmbd_rpc_command *req;
759 struct ksmbd_rpc_command *resp;
760
761 if (payload_sz > KSMBD_IPC_MAX_PAYLOAD)
762 return NULL;
763
764 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
765 if (!msg)
766 return NULL;
767
768 msg->type = KSMBD_EVENT_RPC_REQUEST;
769 req = (struct ksmbd_rpc_command *)msg->payload;
770 req->handle = handle;
771 req->flags = ksmbd_session_rpc_method(sess, handle);
772 req->flags |= rpc_context_flags(sess);
773 req->flags |= KSMBD_RPC_WRITE_METHOD;
774 req->payload_sz = payload_sz;
775 memcpy(req->payload, payload, payload_sz);
776
777 resp = ipc_msg_send_request(msg, req->handle);
778 ipc_msg_free(msg);
779 return resp;
780 }
781
ksmbd_rpc_read(struct ksmbd_session * sess,int handle)782 struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)
783 {
784 struct ksmbd_ipc_msg *msg;
785 struct ksmbd_rpc_command *req;
786 struct ksmbd_rpc_command *resp;
787
788 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
789 if (!msg)
790 return NULL;
791
792 msg->type = KSMBD_EVENT_RPC_REQUEST;
793 req = (struct ksmbd_rpc_command *)msg->payload;
794 req->handle = handle;
795 req->flags = ksmbd_session_rpc_method(sess, handle);
796 req->flags |= rpc_context_flags(sess);
797 req->flags |= KSMBD_RPC_READ_METHOD;
798 req->payload_sz = 0;
799
800 resp = ipc_msg_send_request(msg, req->handle);
801 ipc_msg_free(msg);
802 return resp;
803 }
804
ksmbd_rpc_ioctl(struct ksmbd_session * sess,int handle,void * payload,size_t payload_sz)805 struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle,
806 void *payload, size_t payload_sz)
807 {
808 struct ksmbd_ipc_msg *msg;
809 struct ksmbd_rpc_command *req;
810 struct ksmbd_rpc_command *resp;
811
812 if (payload_sz > KSMBD_IPC_MAX_PAYLOAD)
813 return NULL;
814
815 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
816 if (!msg)
817 return NULL;
818
819 msg->type = KSMBD_EVENT_RPC_REQUEST;
820 req = (struct ksmbd_rpc_command *)msg->payload;
821 req->handle = handle;
822 req->flags = ksmbd_session_rpc_method(sess, handle);
823 req->flags |= rpc_context_flags(sess);
824 req->flags |= KSMBD_RPC_IOCTL_METHOD;
825 req->payload_sz = payload_sz;
826 memcpy(req->payload, payload, payload_sz);
827
828 resp = ipc_msg_send_request(msg, req->handle);
829 ipc_msg_free(msg);
830 return resp;
831 }
832
ksmbd_rpc_rap(struct ksmbd_session * sess,void * payload,size_t payload_sz)833 struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payload,
834 size_t payload_sz)
835 {
836 struct ksmbd_ipc_msg *msg;
837 struct ksmbd_rpc_command *req;
838 struct ksmbd_rpc_command *resp;
839
840 msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
841 if (!msg)
842 return NULL;
843
844 msg->type = KSMBD_EVENT_RPC_REQUEST;
845 req = (struct ksmbd_rpc_command *)msg->payload;
846 req->handle = ksmbd_acquire_id(&ipc_ida);
847 req->flags = rpc_context_flags(sess);
848 req->flags |= KSMBD_RPC_RAP_METHOD;
849 req->payload_sz = payload_sz;
850 memcpy(req->payload, payload, payload_sz);
851
852 resp = ipc_msg_send_request(msg, req->handle);
853 ipc_msg_handle_free(req->handle);
854 ipc_msg_free(msg);
855 return resp;
856 }
857
__ipc_heartbeat(void)858 static int __ipc_heartbeat(void)
859 {
860 unsigned long delta;
861
862 if (!ksmbd_server_running())
863 return 0;
864
865 if (time_after(jiffies, server_conf.ipc_last_active)) {
866 delta = (jiffies - server_conf.ipc_last_active);
867 } else {
868 ipc_update_last_active();
869 schedule_delayed_work(&ipc_timer_work,
870 server_conf.ipc_timeout);
871 return 0;
872 }
873
874 if (delta < server_conf.ipc_timeout) {
875 schedule_delayed_work(&ipc_timer_work,
876 server_conf.ipc_timeout - delta);
877 return 0;
878 }
879
880 if (ksmbd_ipc_heartbeat_request() == 0) {
881 schedule_delayed_work(&ipc_timer_work,
882 server_conf.ipc_timeout);
883 return 0;
884 }
885
886 mutex_lock(&startup_lock);
887 WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
888 server_conf.ipc_last_active = 0;
889 ksmbd_tools_pid = 0;
890 pr_err("No IPC daemon response for %lus\n", delta / HZ);
891 mutex_unlock(&startup_lock);
892 return -EINVAL;
893 }
894
ipc_timer_heartbeat(struct work_struct * w)895 static void ipc_timer_heartbeat(struct work_struct *w)
896 {
897 if (__ipc_heartbeat())
898 server_queue_ctrl_reset_work();
899 }
900
ksmbd_ipc_id_alloc(void)901 int ksmbd_ipc_id_alloc(void)
902 {
903 return ksmbd_acquire_id(&ipc_ida);
904 }
905
ksmbd_rpc_id_free(int handle)906 void ksmbd_rpc_id_free(int handle)
907 {
908 ksmbd_release_id(&ipc_ida, handle);
909 }
910
ksmbd_ipc_release(void)911 void ksmbd_ipc_release(void)
912 {
913 cancel_delayed_work_sync(&ipc_timer_work);
914 genl_unregister_family(&ksmbd_genl_family);
915 }
916
ksmbd_ipc_soft_reset(void)917 void ksmbd_ipc_soft_reset(void)
918 {
919 mutex_lock(&startup_lock);
920 ksmbd_tools_pid = 0;
921 cancel_delayed_work_sync(&ipc_timer_work);
922 mutex_unlock(&startup_lock);
923 }
924
ksmbd_ipc_init(void)925 int ksmbd_ipc_init(void)
926 {
927 int ret = 0;
928
929 ksmbd_nl_init_fixup();
930 INIT_DELAYED_WORK(&ipc_timer_work, ipc_timer_heartbeat);
931
932 ret = genl_register_family(&ksmbd_genl_family);
933 if (ret) {
934 pr_err("Failed to register KSMBD netlink interface %d\n", ret);
935 cancel_delayed_work_sync(&ipc_timer_work);
936 }
937
938 return ret;
939 }
940