~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/smb/server/transport_ipc.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php