File Index
Files and directories
Sign in
FILE

transport_ipc.c

File preview with syntax highlighting.

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