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