Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
0004  */
0005 
0006 #include <linux/jhash.h>
0007 #include <linux/slab.h>
0008 #include <linux/rwsem.h>
0009 #include <linux/mutex.h>
0010 #include <linux/wait.h>
0011 #include <linux/hashtable.h>
0012 #include <net/net_namespace.h>
0013 #include <net/genetlink.h>
0014 #include <linux/socket.h>
0015 #include <linux/workqueue.h>
0016 
0017 #include "vfs_cache.h"
0018 #include "transport_ipc.h"
0019 #include "server.h"
0020 #include "smb_common.h"
0021 
0022 #include "mgmt/user_config.h"
0023 #include "mgmt/share_config.h"
0024 #include "mgmt/user_session.h"
0025 #include "mgmt/tree_connect.h"
0026 #include "mgmt/ksmbd_ida.h"
0027 #include "connection.h"
0028 #include "transport_tcp.h"
0029 #include "transport_rdma.h"
0030 
0031 #define IPC_WAIT_TIMEOUT    (2 * HZ)
0032 
0033 #define IPC_MSG_HASH_BITS   3
0034 static DEFINE_HASHTABLE(ipc_msg_table, IPC_MSG_HASH_BITS);
0035 static DECLARE_RWSEM(ipc_msg_table_lock);
0036 static DEFINE_MUTEX(startup_lock);
0037 
0038 static DEFINE_IDA(ipc_ida);
0039 
0040 static unsigned int ksmbd_tools_pid;
0041 
0042 static bool ksmbd_ipc_validate_version(struct genl_info *m)
0043 {
0044     if (m->genlhdr->version != KSMBD_GENL_VERSION) {
0045         pr_err("%s. ksmbd: %d, kernel module: %d. %s.\n",
0046                "Daemon and kernel module version mismatch",
0047                m->genlhdr->version,
0048                KSMBD_GENL_VERSION,
0049                "User-space ksmbd should terminate");
0050         return false;
0051     }
0052     return true;
0053 }
0054 
0055 struct ksmbd_ipc_msg {
0056     unsigned int        type;
0057     unsigned int        sz;
0058     unsigned char       payload[];
0059 };
0060 
0061 struct ipc_msg_table_entry {
0062     unsigned int        handle;
0063     unsigned int        type;
0064     wait_queue_head_t   wait;
0065     struct hlist_node   ipc_table_hlist;
0066 
0067     void            *response;
0068 };
0069 
0070 static struct delayed_work ipc_timer_work;
0071 
0072 static int handle_startup_event(struct sk_buff *skb, struct genl_info *info);
0073 static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info);
0074 static int handle_generic_event(struct sk_buff *skb, struct genl_info *info);
0075 static int ksmbd_ipc_heartbeat_request(void);
0076 
0077 static const struct nla_policy ksmbd_nl_policy[KSMBD_EVENT_MAX] = {
0078     [KSMBD_EVENT_UNSPEC] = {
0079         .len = 0,
0080     },
0081     [KSMBD_EVENT_HEARTBEAT_REQUEST] = {
0082         .len = sizeof(struct ksmbd_heartbeat),
0083     },
0084     [KSMBD_EVENT_STARTING_UP] = {
0085         .len = sizeof(struct ksmbd_startup_request),
0086     },
0087     [KSMBD_EVENT_SHUTTING_DOWN] = {
0088         .len = sizeof(struct ksmbd_shutdown_request),
0089     },
0090     [KSMBD_EVENT_LOGIN_REQUEST] = {
0091         .len = sizeof(struct ksmbd_login_request),
0092     },
0093     [KSMBD_EVENT_LOGIN_RESPONSE] = {
0094         .len = sizeof(struct ksmbd_login_response),
0095     },
0096     [KSMBD_EVENT_SHARE_CONFIG_REQUEST] = {
0097         .len = sizeof(struct ksmbd_share_config_request),
0098     },
0099     [KSMBD_EVENT_SHARE_CONFIG_RESPONSE] = {
0100         .len = sizeof(struct ksmbd_share_config_response),
0101     },
0102     [KSMBD_EVENT_TREE_CONNECT_REQUEST] = {
0103         .len = sizeof(struct ksmbd_tree_connect_request),
0104     },
0105     [KSMBD_EVENT_TREE_CONNECT_RESPONSE] = {
0106         .len = sizeof(struct ksmbd_tree_connect_response),
0107     },
0108     [KSMBD_EVENT_TREE_DISCONNECT_REQUEST] = {
0109         .len = sizeof(struct ksmbd_tree_disconnect_request),
0110     },
0111     [KSMBD_EVENT_LOGOUT_REQUEST] = {
0112         .len = sizeof(struct ksmbd_logout_request),
0113     },
0114     [KSMBD_EVENT_RPC_REQUEST] = {
0115     },
0116     [KSMBD_EVENT_RPC_RESPONSE] = {
0117     },
0118     [KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST] = {
0119     },
0120     [KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE] = {
0121     },
0122 };
0123 
0124 static struct genl_ops ksmbd_genl_ops[] = {
0125     {
0126         .cmd    = KSMBD_EVENT_UNSPEC,
0127         .doit   = handle_unsupported_event,
0128     },
0129     {
0130         .cmd    = KSMBD_EVENT_HEARTBEAT_REQUEST,
0131         .doit   = handle_unsupported_event,
0132     },
0133     {
0134         .cmd    = KSMBD_EVENT_STARTING_UP,
0135         .doit   = handle_startup_event,
0136     },
0137     {
0138         .cmd    = KSMBD_EVENT_SHUTTING_DOWN,
0139         .doit   = handle_unsupported_event,
0140     },
0141     {
0142         .cmd    = KSMBD_EVENT_LOGIN_REQUEST,
0143         .doit   = handle_unsupported_event,
0144     },
0145     {
0146         .cmd    = KSMBD_EVENT_LOGIN_RESPONSE,
0147         .doit   = handle_generic_event,
0148     },
0149     {
0150         .cmd    = KSMBD_EVENT_SHARE_CONFIG_REQUEST,
0151         .doit   = handle_unsupported_event,
0152     },
0153     {
0154         .cmd    = KSMBD_EVENT_SHARE_CONFIG_RESPONSE,
0155         .doit   = handle_generic_event,
0156     },
0157     {
0158         .cmd    = KSMBD_EVENT_TREE_CONNECT_REQUEST,
0159         .doit   = handle_unsupported_event,
0160     },
0161     {
0162         .cmd    = KSMBD_EVENT_TREE_CONNECT_RESPONSE,
0163         .doit   = handle_generic_event,
0164     },
0165     {
0166         .cmd    = KSMBD_EVENT_TREE_DISCONNECT_REQUEST,
0167         .doit   = handle_unsupported_event,
0168     },
0169     {
0170         .cmd    = KSMBD_EVENT_LOGOUT_REQUEST,
0171         .doit   = handle_unsupported_event,
0172     },
0173     {
0174         .cmd    = KSMBD_EVENT_RPC_REQUEST,
0175         .doit   = handle_unsupported_event,
0176     },
0177     {
0178         .cmd    = KSMBD_EVENT_RPC_RESPONSE,
0179         .doit   = handle_generic_event,
0180     },
0181     {
0182         .cmd    = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST,
0183         .doit   = handle_unsupported_event,
0184     },
0185     {
0186         .cmd    = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE,
0187         .doit   = handle_generic_event,
0188     },
0189 };
0190 
0191 static struct genl_family ksmbd_genl_family = {
0192     .name       = KSMBD_GENL_NAME,
0193     .version    = KSMBD_GENL_VERSION,
0194     .hdrsize    = 0,
0195     .maxattr    = KSMBD_EVENT_MAX,
0196     .netnsok    = true,
0197     .module     = THIS_MODULE,
0198     .ops        = ksmbd_genl_ops,
0199     .n_ops      = ARRAY_SIZE(ksmbd_genl_ops),
0200 };
0201 
0202 static void ksmbd_nl_init_fixup(void)
0203 {
0204     int i;
0205 
0206     for (i = 0; i < ARRAY_SIZE(ksmbd_genl_ops); i++)
0207         ksmbd_genl_ops[i].validate = GENL_DONT_VALIDATE_STRICT |
0208                         GENL_DONT_VALIDATE_DUMP;
0209 
0210     ksmbd_genl_family.policy = ksmbd_nl_policy;
0211 }
0212 
0213 static int rpc_context_flags(struct ksmbd_session *sess)
0214 {
0215     if (user_guest(sess->user))
0216         return KSMBD_RPC_RESTRICTED_CONTEXT;
0217     return 0;
0218 }
0219 
0220 static void ipc_update_last_active(void)
0221 {
0222     if (server_conf.ipc_timeout)
0223         server_conf.ipc_last_active = jiffies;
0224 }
0225 
0226 static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz)
0227 {
0228     struct ksmbd_ipc_msg *msg;
0229     size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg);
0230 
0231     msg = kvmalloc(msg_sz, GFP_KERNEL | __GFP_ZERO);
0232     if (msg)
0233         msg->sz = sz;
0234     return msg;
0235 }
0236 
0237 static void ipc_msg_free(struct ksmbd_ipc_msg *msg)
0238 {
0239     kvfree(msg);
0240 }
0241 
0242 static void ipc_msg_handle_free(int handle)
0243 {
0244     if (handle >= 0)
0245         ksmbd_release_id(&ipc_ida, handle);
0246 }
0247 
0248 static int handle_response(int type, void *payload, size_t sz)
0249 {
0250     unsigned int handle = *(unsigned int *)payload;
0251     struct ipc_msg_table_entry *entry;
0252     int ret = 0;
0253 
0254     ipc_update_last_active();
0255     down_read(&ipc_msg_table_lock);
0256     hash_for_each_possible(ipc_msg_table, entry, ipc_table_hlist, handle) {
0257         if (handle != entry->handle)
0258             continue;
0259 
0260         entry->response = NULL;
0261         /*
0262          * Response message type value should be equal to
0263          * request message type + 1.
0264          */
0265         if (entry->type + 1 != type) {
0266             pr_err("Waiting for IPC type %d, got %d. Ignore.\n",
0267                    entry->type + 1, type);
0268         }
0269 
0270         entry->response = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
0271         if (!entry->response) {
0272             ret = -ENOMEM;
0273             break;
0274         }
0275 
0276         memcpy(entry->response, payload, sz);
0277         wake_up_interruptible(&entry->wait);
0278         ret = 0;
0279         break;
0280     }
0281     up_read(&ipc_msg_table_lock);
0282 
0283     return ret;
0284 }
0285 
0286 static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
0287 {
0288     int ret;
0289 
0290     ksmbd_set_fd_limit(req->file_max);
0291     server_conf.flags = req->flags;
0292     server_conf.signing = req->signing;
0293     server_conf.tcp_port = req->tcp_port;
0294     server_conf.ipc_timeout = req->ipc_timeout * HZ;
0295     server_conf.deadtime = req->deadtime * SMB_ECHO_INTERVAL;
0296     server_conf.share_fake_fscaps = req->share_fake_fscaps;
0297     ksmbd_init_domain(req->sub_auth);
0298 
0299     if (req->smb2_max_read)
0300         init_smb2_max_read_size(req->smb2_max_read);
0301     if (req->smb2_max_write)
0302         init_smb2_max_write_size(req->smb2_max_write);
0303     if (req->smb2_max_trans)
0304         init_smb2_max_trans_size(req->smb2_max_trans);
0305     if (req->smb2_max_credits)
0306         init_smb2_max_credits(req->smb2_max_credits);
0307     if (req->smbd_max_io_size)
0308         init_smbd_max_io_size(req->smbd_max_io_size);
0309 
0310     ret = ksmbd_set_netbios_name(req->netbios_name);
0311     ret |= ksmbd_set_server_string(req->server_string);
0312     ret |= ksmbd_set_work_group(req->work_group);
0313     ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req),
0314                     req->ifc_list_sz);
0315     if (ret) {
0316         pr_err("Server configuration error: %s %s %s\n",
0317                req->netbios_name, req->server_string,
0318                req->work_group);
0319         return ret;
0320     }
0321 
0322     if (req->min_prot[0]) {
0323         ret = ksmbd_lookup_protocol_idx(req->min_prot);
0324         if (ret >= 0)
0325             server_conf.min_protocol = ret;
0326     }
0327     if (req->max_prot[0]) {
0328         ret = ksmbd_lookup_protocol_idx(req->max_prot);
0329         if (ret >= 0)
0330             server_conf.max_protocol = ret;
0331     }
0332 
0333     if (server_conf.ipc_timeout)
0334         schedule_delayed_work(&ipc_timer_work, server_conf.ipc_timeout);
0335     return 0;
0336 }
0337 
0338 static int handle_startup_event(struct sk_buff *skb, struct genl_info *info)
0339 {
0340     int ret = 0;
0341 
0342 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
0343     if (!netlink_capable(skb, CAP_NET_ADMIN))
0344         return -EPERM;
0345 #endif
0346 
0347     if (!ksmbd_ipc_validate_version(info))
0348         return -EINVAL;
0349 
0350     if (!info->attrs[KSMBD_EVENT_STARTING_UP])
0351         return -EINVAL;
0352 
0353     mutex_lock(&startup_lock);
0354     if (!ksmbd_server_configurable()) {
0355         mutex_unlock(&startup_lock);
0356         pr_err("Server reset is in progress, can't start daemon\n");
0357         return -EINVAL;
0358     }
0359 
0360     if (ksmbd_tools_pid) {
0361         if (ksmbd_ipc_heartbeat_request() == 0) {
0362             ret = -EINVAL;
0363             goto out;
0364         }
0365 
0366         pr_err("Reconnect to a new user space daemon\n");
0367     } else {
0368         struct ksmbd_startup_request *req;
0369 
0370         req = nla_data(info->attrs[info->genlhdr->cmd]);
0371         ret = ipc_server_config_on_startup(req);
0372         if (ret)
0373             goto out;
0374         server_queue_ctrl_init_work();
0375     }
0376 
0377     ksmbd_tools_pid = info->snd_portid;
0378     ipc_update_last_active();
0379 
0380 out:
0381     mutex_unlock(&startup_lock);
0382     return ret;
0383 }
0384 
0385 static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info)
0386 {
0387     pr_err("Unknown IPC event: %d, ignore.\n", info->genlhdr->cmd);
0388     return -EINVAL;
0389 }
0390 
0391 static int handle_generic_event(struct sk_buff *skb, struct genl_info *info)
0392 {
0393     void *payload;
0394     int sz;
0395     int type = info->genlhdr->cmd;
0396 
0397 #ifdef CONFIG_SMB_SERVER_CHECK_CAP_NET_ADMIN
0398     if (!netlink_capable(skb, CAP_NET_ADMIN))
0399         return -EPERM;
0400 #endif
0401 
0402     if (type >= KSMBD_EVENT_MAX) {
0403         WARN_ON(1);
0404         return -EINVAL;
0405     }
0406 
0407     if (!ksmbd_ipc_validate_version(info))
0408         return -EINVAL;
0409 
0410     if (!info->attrs[type])
0411         return -EINVAL;
0412 
0413     payload = nla_data(info->attrs[info->genlhdr->cmd]);
0414     sz = nla_len(info->attrs[info->genlhdr->cmd]);
0415     return handle_response(type, payload, sz);
0416 }
0417 
0418 static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
0419 {
0420     struct genlmsghdr *nlh;
0421     struct sk_buff *skb;
0422     int ret = -EINVAL;
0423 
0424     if (!ksmbd_tools_pid)
0425         return ret;
0426 
0427     skb = genlmsg_new(msg->sz, GFP_KERNEL);
0428     if (!skb)
0429         return -ENOMEM;
0430 
0431     nlh = genlmsg_put(skb, 0, 0, &ksmbd_genl_family, 0, msg->type);
0432     if (!nlh)
0433         goto out;
0434 
0435     ret = nla_put(skb, msg->type, msg->sz, msg->payload);
0436     if (ret) {
0437         genlmsg_cancel(skb, nlh);
0438         goto out;
0439     }
0440 
0441     genlmsg_end(skb, nlh);
0442     ret = genlmsg_unicast(&init_net, skb, ksmbd_tools_pid);
0443     if (!ret)
0444         ipc_update_last_active();
0445     return ret;
0446 
0447 out:
0448     nlmsg_free(skb);
0449     return ret;
0450 }
0451 
0452 static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle)
0453 {
0454     struct ipc_msg_table_entry entry;
0455     int ret;
0456 
0457     if ((int)handle < 0)
0458         return NULL;
0459 
0460     entry.type = msg->type;
0461     entry.response = NULL;
0462     init_waitqueue_head(&entry.wait);
0463 
0464     down_write(&ipc_msg_table_lock);
0465     entry.handle = handle;
0466     hash_add(ipc_msg_table, &entry.ipc_table_hlist, entry.handle);
0467     up_write(&ipc_msg_table_lock);
0468 
0469     ret = ipc_msg_send(msg);
0470     if (ret)
0471         goto out;
0472 
0473     ret = wait_event_interruptible_timeout(entry.wait,
0474                            entry.response != NULL,
0475                            IPC_WAIT_TIMEOUT);
0476 out:
0477     down_write(&ipc_msg_table_lock);
0478     hash_del(&entry.ipc_table_hlist);
0479     up_write(&ipc_msg_table_lock);
0480     return entry.response;
0481 }
0482 
0483 static int ksmbd_ipc_heartbeat_request(void)
0484 {
0485     struct ksmbd_ipc_msg *msg;
0486     int ret;
0487 
0488     msg = ipc_msg_alloc(sizeof(struct ksmbd_heartbeat));
0489     if (!msg)
0490         return -EINVAL;
0491 
0492     msg->type = KSMBD_EVENT_HEARTBEAT_REQUEST;
0493     ret = ipc_msg_send(msg);
0494     ipc_msg_free(msg);
0495     return ret;
0496 }
0497 
0498 struct ksmbd_login_response *ksmbd_ipc_login_request(const char *account)
0499 {
0500     struct ksmbd_ipc_msg *msg;
0501     struct ksmbd_login_request *req;
0502     struct ksmbd_login_response *resp;
0503 
0504     if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
0505         return NULL;
0506 
0507     msg = ipc_msg_alloc(sizeof(struct ksmbd_login_request));
0508     if (!msg)
0509         return NULL;
0510 
0511     msg->type = KSMBD_EVENT_LOGIN_REQUEST;
0512     req = (struct ksmbd_login_request *)msg->payload;
0513     req->handle = ksmbd_acquire_id(&ipc_ida);
0514     strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
0515 
0516     resp = ipc_msg_send_request(msg, req->handle);
0517     ipc_msg_handle_free(req->handle);
0518     ipc_msg_free(msg);
0519     return resp;
0520 }
0521 
0522 struct ksmbd_spnego_authen_response *
0523 ksmbd_ipc_spnego_authen_request(const char *spnego_blob, int blob_len)
0524 {
0525     struct ksmbd_ipc_msg *msg;
0526     struct ksmbd_spnego_authen_request *req;
0527     struct ksmbd_spnego_authen_response *resp;
0528 
0529     msg = ipc_msg_alloc(sizeof(struct ksmbd_spnego_authen_request) +
0530             blob_len + 1);
0531     if (!msg)
0532         return NULL;
0533 
0534     msg->type = KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST;
0535     req = (struct ksmbd_spnego_authen_request *)msg->payload;
0536     req->handle = ksmbd_acquire_id(&ipc_ida);
0537     req->spnego_blob_len = blob_len;
0538     memcpy(req->spnego_blob, spnego_blob, blob_len);
0539 
0540     resp = ipc_msg_send_request(msg, req->handle);
0541     ipc_msg_handle_free(req->handle);
0542     ipc_msg_free(msg);
0543     return resp;
0544 }
0545 
0546 struct ksmbd_tree_connect_response *
0547 ksmbd_ipc_tree_connect_request(struct ksmbd_session *sess,
0548                    struct ksmbd_share_config *share,
0549                    struct ksmbd_tree_connect *tree_conn,
0550                    struct sockaddr *peer_addr)
0551 {
0552     struct ksmbd_ipc_msg *msg;
0553     struct ksmbd_tree_connect_request *req;
0554     struct ksmbd_tree_connect_response *resp;
0555 
0556     if (strlen(user_name(sess->user)) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
0557         return NULL;
0558 
0559     if (strlen(share->name) >= KSMBD_REQ_MAX_SHARE_NAME)
0560         return NULL;
0561 
0562     msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_connect_request));
0563     if (!msg)
0564         return NULL;
0565 
0566     msg->type = KSMBD_EVENT_TREE_CONNECT_REQUEST;
0567     req = (struct ksmbd_tree_connect_request *)msg->payload;
0568 
0569     req->handle = ksmbd_acquire_id(&ipc_ida);
0570     req->account_flags = sess->user->flags;
0571     req->session_id = sess->id;
0572     req->connect_id = tree_conn->id;
0573     strscpy(req->account, user_name(sess->user), KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
0574     strscpy(req->share, share->name, KSMBD_REQ_MAX_SHARE_NAME);
0575     snprintf(req->peer_addr, sizeof(req->peer_addr), "%pIS", peer_addr);
0576 
0577     if (peer_addr->sa_family == AF_INET6)
0578         req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_IPV6;
0579     if (test_session_flag(sess, CIFDS_SESSION_FLAG_SMB2))
0580         req->flags |= KSMBD_TREE_CONN_FLAG_REQUEST_SMB2;
0581 
0582     resp = ipc_msg_send_request(msg, req->handle);
0583     ipc_msg_handle_free(req->handle);
0584     ipc_msg_free(msg);
0585     return resp;
0586 }
0587 
0588 int ksmbd_ipc_tree_disconnect_request(unsigned long long session_id,
0589                       unsigned long long connect_id)
0590 {
0591     struct ksmbd_ipc_msg *msg;
0592     struct ksmbd_tree_disconnect_request *req;
0593     int ret;
0594 
0595     msg = ipc_msg_alloc(sizeof(struct ksmbd_tree_disconnect_request));
0596     if (!msg)
0597         return -ENOMEM;
0598 
0599     msg->type = KSMBD_EVENT_TREE_DISCONNECT_REQUEST;
0600     req = (struct ksmbd_tree_disconnect_request *)msg->payload;
0601     req->session_id = session_id;
0602     req->connect_id = connect_id;
0603 
0604     ret = ipc_msg_send(msg);
0605     ipc_msg_free(msg);
0606     return ret;
0607 }
0608 
0609 int ksmbd_ipc_logout_request(const char *account, int flags)
0610 {
0611     struct ksmbd_ipc_msg *msg;
0612     struct ksmbd_logout_request *req;
0613     int ret;
0614 
0615     if (strlen(account) >= KSMBD_REQ_MAX_ACCOUNT_NAME_SZ)
0616         return -EINVAL;
0617 
0618     msg = ipc_msg_alloc(sizeof(struct ksmbd_logout_request));
0619     if (!msg)
0620         return -ENOMEM;
0621 
0622     msg->type = KSMBD_EVENT_LOGOUT_REQUEST;
0623     req = (struct ksmbd_logout_request *)msg->payload;
0624     req->account_flags = flags;
0625     strscpy(req->account, account, KSMBD_REQ_MAX_ACCOUNT_NAME_SZ);
0626 
0627     ret = ipc_msg_send(msg);
0628     ipc_msg_free(msg);
0629     return ret;
0630 }
0631 
0632 struct ksmbd_share_config_response *
0633 ksmbd_ipc_share_config_request(const char *name)
0634 {
0635     struct ksmbd_ipc_msg *msg;
0636     struct ksmbd_share_config_request *req;
0637     struct ksmbd_share_config_response *resp;
0638 
0639     if (strlen(name) >= KSMBD_REQ_MAX_SHARE_NAME)
0640         return NULL;
0641 
0642     msg = ipc_msg_alloc(sizeof(struct ksmbd_share_config_request));
0643     if (!msg)
0644         return NULL;
0645 
0646     msg->type = KSMBD_EVENT_SHARE_CONFIG_REQUEST;
0647     req = (struct ksmbd_share_config_request *)msg->payload;
0648     req->handle = ksmbd_acquire_id(&ipc_ida);
0649     strscpy(req->share_name, name, KSMBD_REQ_MAX_SHARE_NAME);
0650 
0651     resp = ipc_msg_send_request(msg, req->handle);
0652     ipc_msg_handle_free(req->handle);
0653     ipc_msg_free(msg);
0654     return resp;
0655 }
0656 
0657 struct ksmbd_rpc_command *ksmbd_rpc_open(struct ksmbd_session *sess, int handle)
0658 {
0659     struct ksmbd_ipc_msg *msg;
0660     struct ksmbd_rpc_command *req;
0661     struct ksmbd_rpc_command *resp;
0662 
0663     msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
0664     if (!msg)
0665         return NULL;
0666 
0667     msg->type = KSMBD_EVENT_RPC_REQUEST;
0668     req = (struct ksmbd_rpc_command *)msg->payload;
0669     req->handle = handle;
0670     req->flags = ksmbd_session_rpc_method(sess, handle);
0671     req->flags |= KSMBD_RPC_OPEN_METHOD;
0672     req->payload_sz = 0;
0673 
0674     resp = ipc_msg_send_request(msg, req->handle);
0675     ipc_msg_free(msg);
0676     return resp;
0677 }
0678 
0679 struct ksmbd_rpc_command *ksmbd_rpc_close(struct ksmbd_session *sess, int handle)
0680 {
0681     struct ksmbd_ipc_msg *msg;
0682     struct ksmbd_rpc_command *req;
0683     struct ksmbd_rpc_command *resp;
0684 
0685     msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
0686     if (!msg)
0687         return NULL;
0688 
0689     msg->type = KSMBD_EVENT_RPC_REQUEST;
0690     req = (struct ksmbd_rpc_command *)msg->payload;
0691     req->handle = handle;
0692     req->flags = ksmbd_session_rpc_method(sess, handle);
0693     req->flags |= KSMBD_RPC_CLOSE_METHOD;
0694     req->payload_sz = 0;
0695 
0696     resp = ipc_msg_send_request(msg, req->handle);
0697     ipc_msg_free(msg);
0698     return resp;
0699 }
0700 
0701 struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle,
0702                       void *payload, size_t payload_sz)
0703 {
0704     struct ksmbd_ipc_msg *msg;
0705     struct ksmbd_rpc_command *req;
0706     struct ksmbd_rpc_command *resp;
0707 
0708     msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
0709     if (!msg)
0710         return NULL;
0711 
0712     msg->type = KSMBD_EVENT_RPC_REQUEST;
0713     req = (struct ksmbd_rpc_command *)msg->payload;
0714     req->handle = handle;
0715     req->flags = ksmbd_session_rpc_method(sess, handle);
0716     req->flags |= rpc_context_flags(sess);
0717     req->flags |= KSMBD_RPC_WRITE_METHOD;
0718     req->payload_sz = payload_sz;
0719     memcpy(req->payload, payload, payload_sz);
0720 
0721     resp = ipc_msg_send_request(msg, req->handle);
0722     ipc_msg_free(msg);
0723     return resp;
0724 }
0725 
0726 struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)
0727 {
0728     struct ksmbd_ipc_msg *msg;
0729     struct ksmbd_rpc_command *req;
0730     struct ksmbd_rpc_command *resp;
0731 
0732     msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command));
0733     if (!msg)
0734         return NULL;
0735 
0736     msg->type = KSMBD_EVENT_RPC_REQUEST;
0737     req = (struct ksmbd_rpc_command *)msg->payload;
0738     req->handle = handle;
0739     req->flags = ksmbd_session_rpc_method(sess, handle);
0740     req->flags |= rpc_context_flags(sess);
0741     req->flags |= KSMBD_RPC_READ_METHOD;
0742     req->payload_sz = 0;
0743 
0744     resp = ipc_msg_send_request(msg, req->handle);
0745     ipc_msg_free(msg);
0746     return resp;
0747 }
0748 
0749 struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle,
0750                       void *payload, size_t payload_sz)
0751 {
0752     struct ksmbd_ipc_msg *msg;
0753     struct ksmbd_rpc_command *req;
0754     struct ksmbd_rpc_command *resp;
0755 
0756     msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
0757     if (!msg)
0758         return NULL;
0759 
0760     msg->type = KSMBD_EVENT_RPC_REQUEST;
0761     req = (struct ksmbd_rpc_command *)msg->payload;
0762     req->handle = handle;
0763     req->flags = ksmbd_session_rpc_method(sess, handle);
0764     req->flags |= rpc_context_flags(sess);
0765     req->flags |= KSMBD_RPC_IOCTL_METHOD;
0766     req->payload_sz = payload_sz;
0767     memcpy(req->payload, payload, payload_sz);
0768 
0769     resp = ipc_msg_send_request(msg, req->handle);
0770     ipc_msg_free(msg);
0771     return resp;
0772 }
0773 
0774 struct ksmbd_rpc_command *ksmbd_rpc_rap(struct ksmbd_session *sess, void *payload,
0775                     size_t payload_sz)
0776 {
0777     struct ksmbd_ipc_msg *msg;
0778     struct ksmbd_rpc_command *req;
0779     struct ksmbd_rpc_command *resp;
0780 
0781     msg = ipc_msg_alloc(sizeof(struct ksmbd_rpc_command) + payload_sz + 1);
0782     if (!msg)
0783         return NULL;
0784 
0785     msg->type = KSMBD_EVENT_RPC_REQUEST;
0786     req = (struct ksmbd_rpc_command *)msg->payload;
0787     req->handle = ksmbd_acquire_id(&ipc_ida);
0788     req->flags = rpc_context_flags(sess);
0789     req->flags |= KSMBD_RPC_RAP_METHOD;
0790     req->payload_sz = payload_sz;
0791     memcpy(req->payload, payload, payload_sz);
0792 
0793     resp = ipc_msg_send_request(msg, req->handle);
0794     ipc_msg_handle_free(req->handle);
0795     ipc_msg_free(msg);
0796     return resp;
0797 }
0798 
0799 static int __ipc_heartbeat(void)
0800 {
0801     unsigned long delta;
0802 
0803     if (!ksmbd_server_running())
0804         return 0;
0805 
0806     if (time_after(jiffies, server_conf.ipc_last_active)) {
0807         delta = (jiffies - server_conf.ipc_last_active);
0808     } else {
0809         ipc_update_last_active();
0810         schedule_delayed_work(&ipc_timer_work,
0811                       server_conf.ipc_timeout);
0812         return 0;
0813     }
0814 
0815     if (delta < server_conf.ipc_timeout) {
0816         schedule_delayed_work(&ipc_timer_work,
0817                       server_conf.ipc_timeout - delta);
0818         return 0;
0819     }
0820 
0821     if (ksmbd_ipc_heartbeat_request() == 0) {
0822         schedule_delayed_work(&ipc_timer_work,
0823                       server_conf.ipc_timeout);
0824         return 0;
0825     }
0826 
0827     mutex_lock(&startup_lock);
0828     WRITE_ONCE(server_conf.state, SERVER_STATE_RESETTING);
0829     server_conf.ipc_last_active = 0;
0830     ksmbd_tools_pid = 0;
0831     pr_err("No IPC daemon response for %lus\n", delta / HZ);
0832     mutex_unlock(&startup_lock);
0833     return -EINVAL;
0834 }
0835 
0836 static void ipc_timer_heartbeat(struct work_struct *w)
0837 {
0838     if (__ipc_heartbeat())
0839         server_queue_ctrl_reset_work();
0840 }
0841 
0842 int ksmbd_ipc_id_alloc(void)
0843 {
0844     return ksmbd_acquire_id(&ipc_ida);
0845 }
0846 
0847 void ksmbd_rpc_id_free(int handle)
0848 {
0849     ksmbd_release_id(&ipc_ida, handle);
0850 }
0851 
0852 void ksmbd_ipc_release(void)
0853 {
0854     cancel_delayed_work_sync(&ipc_timer_work);
0855     genl_unregister_family(&ksmbd_genl_family);
0856 }
0857 
0858 void ksmbd_ipc_soft_reset(void)
0859 {
0860     mutex_lock(&startup_lock);
0861     ksmbd_tools_pid = 0;
0862     cancel_delayed_work_sync(&ipc_timer_work);
0863     mutex_unlock(&startup_lock);
0864 }
0865 
0866 int ksmbd_ipc_init(void)
0867 {
0868     int ret = 0;
0869 
0870     ksmbd_nl_init_fixup();
0871     INIT_DELAYED_WORK(&ipc_timer_work, ipc_timer_heartbeat);
0872 
0873     ret = genl_register_family(&ksmbd_genl_family);
0874     if (ret) {
0875         pr_err("Failed to register KSMBD netlink interface %d\n", ret);
0876         cancel_delayed_work_sync(&ipc_timer_work);
0877     }
0878 
0879     return ret;
0880 }