xref: /openbmc/linux/fs/smb/server/transport_ipc.c (revision d699090510c3223641a23834b4710e2d4309a6ad)
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