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