Commit 25ac8c12 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '6.3-rc-ksmbd-fixes' of git://git.samba.org/ksmbd

Pull ksmbd server updates from Steve French:

 - Fix for memory leak

 - Two important fixes for frame length checks (which are also now
   stricter)

 - four minor cleanup fixes

 - Fix to clarify ksmbd/Kconfig to indent properl

 - Conversion of the channel list and rpc handle list to xarrays

* tag '6.3-rc-ksmbd-fixes' of git://git.samba.org/ksmbd:
  ksmbd: fix possible memory leak in smb2_lock()
  ksmbd: do not allow the actual frame length to be smaller than the rfc1002 length
  ksmbd: fix wrong data area length for smb2 lock request
  ksmbd: Fix parameter name and comment mismatch
  ksmbd: Fix spelling mistake "excceed" -> "exceeded"
  ksmbd: update Kconfig to note Kerberos support and fix indentation
  ksmbd: Remove duplicated codes
  ksmbd: fix typo, syncronous->synchronous
  ksmbd: Implements sess->rpc_handle_list as xarray
  ksmbd: Implements sess->ksmbd_chann_list as xarray
parents 232dd599 d3ca9f7a
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -33,14 +33,16 @@ config SMB_SERVER
	  in ksmbd-tools, available from
	  https://github.com/cifsd-team/ksmbd-tools.
	  More detail about how to run the ksmbd kernel server is
	  available via README file
	  available via the README file
	  (https://github.com/cifsd-team/ksmbd-tools/blob/master/README).

	  ksmbd kernel server includes support for auto-negotiation,
	  Secure negotiate, Pre-authentication integrity, oplock/lease,
	  compound requests, multi-credit, packet signing, RDMA(smbdirect),
	  smb3 encryption, copy-offload, secure per-user session
	  establishment via NTLM or NTLMv2.
	  establishment via Kerberos or NTLMv2.

if SMB_SERVER

config SMB_SERVER_SMBDIRECT
	bool "Support for SMB Direct protocol"
@@ -54,6 +56,8 @@ config SMB_SERVER_SMBDIRECT
	  SMB Direct allows transferring SMB packets over RDMA. If unsure,
	  say N.

endif

config SMB_SERVER_CHECK_CAP_NET_ADMIN
	bool "Enable check network administration capability"
	depends on SMB_SERVER
+11 −12
Original line number Diff line number Diff line
@@ -208,7 +208,7 @@ int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen,
	return 0;
}

int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
static int ksmbd_neg_token_alloc(void *context, size_t hdrlen,
				 unsigned char tag, const void *value,
				 size_t vlen)
{
@@ -223,17 +223,16 @@ int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
	return 0;
}

int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen,
				    unsigned char tag, const void *value,
				    size_t vlen)
{
	struct ksmbd_conn *conn = context;

	conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL);
	if (!conn->mechToken)
		return -ENOMEM;
	return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen);
}

	memcpy(conn->mechToken, value, vlen);
	conn->mechToken[vlen] = '\0';
	return 0;
int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen,
				    unsigned char tag, const void *value,
				    size_t vlen)
{
	return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen);
}
+3 −3
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)

	if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
		requests_queue = &conn->requests;
		work->syncronous = true;
		work->synchronous = true;
	}

	if (requests_queue) {
@@ -139,7 +139,7 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
	spin_lock(&conn->request_lock);
	if (!work->multiRsp) {
		list_del_init(&work->request_entry);
		if (work->syncronous == false)
		if (!work->synchronous)
			list_del_init(&work->async_request_entry);
		ret = 0;
	}
@@ -312,7 +312,7 @@ int ksmbd_conn_handler_loop(void *p)
			max_allowed_pdu_size = SMB3_MAX_MSGSIZE;

		if (pdu_size > max_allowed_pdu_size) {
			pr_err_ratelimited("PDU length(%u) excceed maximum allowed pdu size(%u) on connection(%d)\n",
			pr_err_ratelimited("PDU length(%u) exceeded maximum allowed pdu size(%u) on connection(%d)\n",
					pdu_size, max_allowed_pdu_size,
					conn->status);
			break;
+1 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ struct ksmbd_work {
	/* Request is encrypted */
	bool                            encrypted:1;
	/* Is this SYNC or ASYNC ksmbd_work */
	bool                            syncronous:1;
	bool                            synchronous:1;
	bool                            need_invalidate_rkey:1;

	unsigned int                    remote_key;
+38 −60
Original line number Diff line number Diff line
@@ -25,20 +25,19 @@ static DECLARE_RWSEM(sessions_table_lock);
struct ksmbd_session_rpc {
	int			id;
	unsigned int		method;
	struct list_head	list;
};

static void free_channel_list(struct ksmbd_session *sess)
{
	struct channel *chann, *tmp;
	struct channel *chann;
	unsigned long index;

	write_lock(&sess->chann_lock);
	list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list,
				 chann_list) {
		list_del(&chann->chann_list);
	xa_for_each(&sess->ksmbd_chann_list, index, chann) {
		xa_erase(&sess->ksmbd_chann_list, index);
		kfree(chann);
	}
	write_unlock(&sess->chann_lock);

	xa_destroy(&sess->ksmbd_chann_list);
}

static void __session_rpc_close(struct ksmbd_session *sess,
@@ -58,15 +57,14 @@ static void __session_rpc_close(struct ksmbd_session *sess,
static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
{
	struct ksmbd_session_rpc *entry;
	long index;

	while (!list_empty(&sess->rpc_handle_list)) {
		entry = list_entry(sess->rpc_handle_list.next,
				   struct ksmbd_session_rpc,
				   list);

		list_del(&entry->list);
	xa_for_each(&sess->rpc_handle_list, index, entry) {
		xa_erase(&sess->rpc_handle_list, index);
		__session_rpc_close(sess, entry);
	}

	xa_destroy(&sess->rpc_handle_list);
}

static int __rpc_method(char *rpc_name)
@@ -102,13 +100,13 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)

	entry = kzalloc(sizeof(struct ksmbd_session_rpc), GFP_KERNEL);
	if (!entry)
		return -EINVAL;
		return -ENOMEM;

	list_add(&entry->list, &sess->rpc_handle_list);
	entry->method = method;
	entry->id = ksmbd_ipc_id_alloc();
	if (entry->id < 0)
		goto free_entry;
	xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL);

	resp = ksmbd_rpc_open(sess, entry->id);
	if (!resp)
@@ -117,9 +115,9 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
	kvfree(resp);
	return entry->id;
free_id:
	xa_erase(&sess->rpc_handle_list, entry->id);
	ksmbd_rpc_id_free(entry->id);
free_entry:
	list_del(&entry->list);
	kfree(entry);
	return -EINVAL;
}
@@ -128,24 +126,17 @@ void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
{
	struct ksmbd_session_rpc *entry;

	list_for_each_entry(entry, &sess->rpc_handle_list, list) {
		if (entry->id == id) {
			list_del(&entry->list);
	entry = xa_erase(&sess->rpc_handle_list, id);
	if (entry)
		__session_rpc_close(sess, entry);
			break;
		}
	}
}

int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
{
	struct ksmbd_session_rpc *entry;

	list_for_each_entry(entry, &sess->rpc_handle_list, list) {
		if (entry->id == id)
			return entry->method;
	}
	return 0;
	entry = xa_load(&sess->rpc_handle_list, id);
	return entry ? entry->method : 0;
}

void ksmbd_session_destroy(struct ksmbd_session *sess)
@@ -190,21 +181,15 @@ int ksmbd_session_register(struct ksmbd_conn *conn,

static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
{
	struct channel *chann, *tmp;
	struct channel *chann;

	chann = xa_erase(&sess->ksmbd_chann_list, (long)conn);
	if (!chann)
		return -ENOENT;

	write_lock(&sess->chann_lock);
	list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list,
				 chann_list) {
		if (chann->conn == conn) {
			list_del(&chann->chann_list);
	kfree(chann);
			write_unlock(&sess->chann_lock);
			return 0;
		}
	}
	write_unlock(&sess->chann_lock);

	return -ENOENT;
	return 0;
}

void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
@@ -234,7 +219,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
	return;

sess_destroy:
	if (list_empty(&sess->ksmbd_chann_list)) {
	if (xa_empty(&sess->ksmbd_chann_list)) {
		xa_erase(&conn->sessions, sess->id);
		ksmbd_session_destroy(sess);
	}
@@ -320,6 +305,9 @@ static struct ksmbd_session *__session_create(int protocol)
	struct ksmbd_session *sess;
	int ret;

	if (protocol != CIFDS_SESSION_FLAG_SMB2)
		return NULL;

	sess = kzalloc(sizeof(struct ksmbd_session), GFP_KERNEL);
	if (!sess)
		return NULL;
@@ -329,30 +317,20 @@ static struct ksmbd_session *__session_create(int protocol)

	set_session_flag(sess, protocol);
	xa_init(&sess->tree_conns);
	INIT_LIST_HEAD(&sess->ksmbd_chann_list);
	INIT_LIST_HEAD(&sess->rpc_handle_list);
	xa_init(&sess->ksmbd_chann_list);
	xa_init(&sess->rpc_handle_list);
	sess->sequence_number = 1;
	rwlock_init(&sess->chann_lock);

	switch (protocol) {
	case CIFDS_SESSION_FLAG_SMB2:
	ret = __init_smb2_session(sess);
		break;
	default:
		ret = -EINVAL;
		break;
	}

	if (ret)
		goto error;

	ida_init(&sess->tree_conn_ida);

	if (protocol == CIFDS_SESSION_FLAG_SMB2) {
	down_write(&sessions_table_lock);
	hash_add(sessions_table, &sess->hlist, sess->id);
	up_write(&sessions_table_lock);
	}

	return sess;

error:
Loading