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