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