brintos

brintos / linux-shallow public Read only

0
0
Text · 10.7 KiB · e6a72f7 Raw
478 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   Copyright (C) 2016 Namjae Jeon <namjae.jeon@protocolfreedom.org>4 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.5 */6 7#include <linux/mutex.h>8#include <linux/freezer.h>9#include <linux/module.h>10 11#include "server.h"12#include "smb_common.h"13#include "mgmt/ksmbd_ida.h"14#include "connection.h"15#include "transport_tcp.h"16#include "transport_rdma.h"17 18static DEFINE_MUTEX(init_lock);19 20static struct ksmbd_conn_ops default_conn_ops;21 22LIST_HEAD(conn_list);23DECLARE_RWSEM(conn_list_lock);24 25/**26 * ksmbd_conn_free() - free resources of the connection instance27 *28 * @conn:	connection instance to be cleaned up29 *30 * During the thread termination, the corresponding conn instance31 * resources(sock/memory) are released and finally the conn object is freed.32 */33void ksmbd_conn_free(struct ksmbd_conn *conn)34{35	down_write(&conn_list_lock);36	list_del(&conn->conns_list);37	up_write(&conn_list_lock);38 39	xa_destroy(&conn->sessions);40	kvfree(conn->request_buf);41	kfree(conn->preauth_info);42	if (atomic_dec_and_test(&conn->refcnt))43		kfree(conn);44}45 46/**47 * ksmbd_conn_alloc() - initialize a new connection instance48 *49 * Return:	ksmbd_conn struct on success, otherwise NULL50 */51struct ksmbd_conn *ksmbd_conn_alloc(void)52{53	struct ksmbd_conn *conn;54 55	conn = kzalloc(sizeof(struct ksmbd_conn), GFP_KERNEL);56	if (!conn)57		return NULL;58 59	conn->need_neg = true;60	ksmbd_conn_set_new(conn);61	conn->local_nls = load_nls("utf8");62	if (!conn->local_nls)63		conn->local_nls = load_nls_default();64	if (IS_ENABLED(CONFIG_UNICODE))65		conn->um = utf8_load(UNICODE_AGE(12, 1, 0));66	else67		conn->um = ERR_PTR(-EOPNOTSUPP);68	if (IS_ERR(conn->um))69		conn->um = NULL;70	atomic_set(&conn->req_running, 0);71	atomic_set(&conn->r_count, 0);72	atomic_set(&conn->refcnt, 1);73	atomic_set(&conn->mux_smb_requests, 0);74	conn->total_credits = 1;75	conn->outstanding_credits = 0;76 77	init_waitqueue_head(&conn->req_running_q);78	init_waitqueue_head(&conn->r_count_q);79	INIT_LIST_HEAD(&conn->conns_list);80	INIT_LIST_HEAD(&conn->requests);81	INIT_LIST_HEAD(&conn->async_requests);82	spin_lock_init(&conn->request_lock);83	spin_lock_init(&conn->credits_lock);84	ida_init(&conn->async_ida);85	xa_init(&conn->sessions);86 87	spin_lock_init(&conn->llist_lock);88	INIT_LIST_HEAD(&conn->lock_list);89 90	init_rwsem(&conn->session_lock);91 92	down_write(&conn_list_lock);93	list_add(&conn->conns_list, &conn_list);94	up_write(&conn_list_lock);95	return conn;96}97 98bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)99{100	struct ksmbd_conn *t;101	bool ret = false;102 103	down_read(&conn_list_lock);104	list_for_each_entry(t, &conn_list, conns_list) {105		if (memcmp(t->ClientGUID, c->ClientGUID, SMB2_CLIENT_GUID_SIZE))106			continue;107 108		ret = true;109		break;110	}111	up_read(&conn_list_lock);112	return ret;113}114 115void ksmbd_conn_enqueue_request(struct ksmbd_work *work)116{117	struct ksmbd_conn *conn = work->conn;118	struct list_head *requests_queue = NULL;119 120	if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE)121		requests_queue = &conn->requests;122 123	if (requests_queue) {124		atomic_inc(&conn->req_running);125		spin_lock(&conn->request_lock);126		list_add_tail(&work->request_entry, requests_queue);127		spin_unlock(&conn->request_lock);128	}129}130 131void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)132{133	struct ksmbd_conn *conn = work->conn;134 135	if (list_empty(&work->request_entry) &&136	    list_empty(&work->async_request_entry))137		return;138 139	atomic_dec(&conn->req_running);140	spin_lock(&conn->request_lock);141	list_del_init(&work->request_entry);142	spin_unlock(&conn->request_lock);143	if (work->asynchronous)144		release_async_work(work);145 146	wake_up_all(&conn->req_running_q);147}148 149void ksmbd_conn_lock(struct ksmbd_conn *conn)150{151	mutex_lock(&conn->srv_mutex);152}153 154void ksmbd_conn_unlock(struct ksmbd_conn *conn)155{156	mutex_unlock(&conn->srv_mutex);157}158 159void ksmbd_all_conn_set_status(u64 sess_id, u32 status)160{161	struct ksmbd_conn *conn;162 163	down_read(&conn_list_lock);164	list_for_each_entry(conn, &conn_list, conns_list) {165		if (conn->binding || xa_load(&conn->sessions, sess_id))166			WRITE_ONCE(conn->status, status);167	}168	up_read(&conn_list_lock);169}170 171void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)172{173	wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);174}175 176int ksmbd_conn_wait_idle_sess_id(struct ksmbd_conn *curr_conn, u64 sess_id)177{178	struct ksmbd_conn *conn;179	int rc, retry_count = 0, max_timeout = 120;180	int rcount = 1;181 182retry_idle:183	if (retry_count >= max_timeout)184		return -EIO;185 186	down_read(&conn_list_lock);187	list_for_each_entry(conn, &conn_list, conns_list) {188		if (conn->binding || xa_load(&conn->sessions, sess_id)) {189			if (conn == curr_conn)190				rcount = 2;191			if (atomic_read(&conn->req_running) >= rcount) {192				rc = wait_event_timeout(conn->req_running_q,193					atomic_read(&conn->req_running) < rcount,194					HZ);195				if (!rc) {196					up_read(&conn_list_lock);197					retry_count++;198					goto retry_idle;199				}200			}201		}202	}203	up_read(&conn_list_lock);204 205	return 0;206}207 208int ksmbd_conn_write(struct ksmbd_work *work)209{210	struct ksmbd_conn *conn = work->conn;211	int sent;212 213	if (!work->response_buf) {214		pr_err("NULL response header\n");215		return -EINVAL;216	}217 218	if (work->send_no_response)219		return 0;220 221	if (!work->iov_idx)222		return -EINVAL;223 224	ksmbd_conn_lock(conn);225	sent = conn->transport->ops->writev(conn->transport, work->iov,226			work->iov_cnt,227			get_rfc1002_len(work->iov[0].iov_base) + 4,228			work->need_invalidate_rkey,229			work->remote_key);230	ksmbd_conn_unlock(conn);231 232	if (sent < 0) {233		pr_err("Failed to send message: %d\n", sent);234		return sent;235	}236 237	return 0;238}239 240int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,241			 void *buf, unsigned int buflen,242			 struct smb2_buffer_desc_v1 *desc,243			 unsigned int desc_len)244{245	int ret = -EINVAL;246 247	if (conn->transport->ops->rdma_read)248		ret = conn->transport->ops->rdma_read(conn->transport,249						      buf, buflen,250						      desc, desc_len);251	return ret;252}253 254int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,255			  void *buf, unsigned int buflen,256			  struct smb2_buffer_desc_v1 *desc,257			  unsigned int desc_len)258{259	int ret = -EINVAL;260 261	if (conn->transport->ops->rdma_write)262		ret = conn->transport->ops->rdma_write(conn->transport,263						       buf, buflen,264						       desc, desc_len);265	return ret;266}267 268bool ksmbd_conn_alive(struct ksmbd_conn *conn)269{270	if (!ksmbd_server_running())271		return false;272 273	if (ksmbd_conn_exiting(conn))274		return false;275 276	if (kthread_should_stop())277		return false;278 279	if (atomic_read(&conn->stats.open_files_count) > 0)280		return true;281 282	/*283	 * Stop current session if the time that get last request from client284	 * is bigger than deadtime user configured and opening file count is285	 * zero.286	 */287	if (server_conf.deadtime > 0 &&288	    time_after(jiffies, conn->last_active + server_conf.deadtime)) {289		ksmbd_debug(CONN, "No response from client in %lu minutes\n",290			    server_conf.deadtime / SMB_ECHO_INTERVAL);291		return false;292	}293	return true;294}295 296#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))297#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)298 299/**300 * ksmbd_conn_handler_loop() - session thread to listen on new smb requests301 * @p:		connection instance302 *303 * One thread each per connection304 *305 * Return:	0 on success306 */307int ksmbd_conn_handler_loop(void *p)308{309	struct ksmbd_conn *conn = (struct ksmbd_conn *)p;310	struct ksmbd_transport *t = conn->transport;311	unsigned int pdu_size, max_allowed_pdu_size;312	char hdr_buf[4] = {0,};313	int size;314 315	mutex_init(&conn->srv_mutex);316	__module_get(THIS_MODULE);317 318	if (t->ops->prepare && t->ops->prepare(t))319		goto out;320 321	conn->last_active = jiffies;322	set_freezable();323	while (ksmbd_conn_alive(conn)) {324		if (try_to_freeze())325			continue;326 327		kvfree(conn->request_buf);328		conn->request_buf = NULL;329 330		size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);331		if (size != sizeof(hdr_buf))332			break;333 334		pdu_size = get_rfc1002_len(hdr_buf);335		ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);336 337		if (ksmbd_conn_good(conn))338			max_allowed_pdu_size =339				SMB3_MAX_MSGSIZE + conn->vals->max_write_size;340		else341			max_allowed_pdu_size = SMB3_MAX_MSGSIZE;342 343		if (pdu_size > max_allowed_pdu_size) {344			pr_err_ratelimited("PDU length(%u) exceeded maximum allowed pdu size(%u) on connection(%d)\n",345					pdu_size, max_allowed_pdu_size,346					READ_ONCE(conn->status));347			break;348		}349 350		/*351		 * Check maximum pdu size(0x00FFFFFF).352		 */353		if (pdu_size > MAX_STREAM_PROT_LEN)354			break;355 356		if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)357			break;358 359		/* 4 for rfc1002 length field */360		/* 1 for implied bcc[0] */361		size = pdu_size + 4 + 1;362		conn->request_buf = kvmalloc(size, GFP_KERNEL);363		if (!conn->request_buf)364			break;365 366		memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));367 368		/*369		 * We already read 4 bytes to find out PDU size, now370		 * read in PDU371		 */372		size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);373		if (size < 0) {374			pr_err("sock_read failed: %d\n", size);375			break;376		}377 378		if (size != pdu_size) {379			pr_err("PDU error. Read: %d, Expected: %d\n",380			       size, pdu_size);381			continue;382		}383 384		if (!ksmbd_smb_request(conn))385			break;386 387		if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==388		    SMB2_PROTO_NUMBER) {389			if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)390				break;391		}392 393		if (!default_conn_ops.process_fn) {394			pr_err("No connection request callback\n");395			break;396		}397 398		if (default_conn_ops.process_fn(conn)) {399			pr_err("Cannot handle request\n");400			break;401		}402	}403 404out:405	ksmbd_conn_set_releasing(conn);406	/* Wait till all reference dropped to the Server object*/407	wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);408 409	if (IS_ENABLED(CONFIG_UNICODE))410		utf8_unload(conn->um);411	unload_nls(conn->local_nls);412	if (default_conn_ops.terminate_fn)413		default_conn_ops.terminate_fn(conn);414	t->ops->disconnect(t);415	module_put(THIS_MODULE);416	return 0;417}418 419void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops)420{421	default_conn_ops.process_fn = ops->process_fn;422	default_conn_ops.terminate_fn = ops->terminate_fn;423}424 425int ksmbd_conn_transport_init(void)426{427	int ret;428 429	mutex_lock(&init_lock);430	ret = ksmbd_tcp_init();431	if (ret) {432		pr_err("Failed to init TCP subsystem: %d\n", ret);433		goto out;434	}435 436	ret = ksmbd_rdma_init();437	if (ret) {438		pr_err("Failed to init RDMA subsystem: %d\n", ret);439		goto out;440	}441out:442	mutex_unlock(&init_lock);443	return ret;444}445 446static void stop_sessions(void)447{448	struct ksmbd_conn *conn;449	struct ksmbd_transport *t;450 451again:452	down_read(&conn_list_lock);453	list_for_each_entry(conn, &conn_list, conns_list) {454		t = conn->transport;455		ksmbd_conn_set_exiting(conn);456		if (t->ops->shutdown) {457			up_read(&conn_list_lock);458			t->ops->shutdown(t);459			down_read(&conn_list_lock);460		}461	}462	up_read(&conn_list_lock);463 464	if (!list_empty(&conn_list)) {465		schedule_timeout_interruptible(HZ / 10); /* 100ms */466		goto again;467	}468}469 470void ksmbd_conn_transport_destroy(void)471{472	mutex_lock(&init_lock);473	ksmbd_tcp_destroy();474	ksmbd_rdma_destroy();475	stop_sessions();476	mutex_unlock(&init_lock);477}478