Commit a1e6fff3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull ksmbd server fixes from Steve French:
 "Four fixes, three for stable:

   - slab out of bounds fix

   - lock cancellation fix

   - minor cleanup to address clang warning

   - fix for xfstest 551 (wrong parms passed to kvmalloc)"

* tag '6.3-rc5-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: fix slab-out-of-bounds in init_smb2_rsp_hdr
  ksmbd: delete asynchronous work from list
  ksmbd: remove unused is_char_allowed function
  ksmbd: do not call kvmalloc() with __GFP_NORETRY | __GFP_NO_WARN
parents f2afccfe dc8289f9
Loading
Loading
Loading
Loading
+6 −11
Original line number Diff line number Diff line
@@ -112,10 +112,8 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
	struct ksmbd_conn *conn = work->conn;
	struct list_head *requests_queue = NULL;

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

	if (requests_queue) {
		atomic_inc(&conn->req_running);
@@ -136,14 +134,14 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)

	if (!work->multiRsp)
		atomic_dec(&conn->req_running);
	spin_lock(&conn->request_lock);
	if (!work->multiRsp) {
		spin_lock(&conn->request_lock);
		list_del_init(&work->request_entry);
		if (!work->synchronous)
			list_del_init(&work->async_request_entry);
		spin_unlock(&conn->request_lock);
		if (work->asynchronous)
			release_async_work(work);
		ret = 0;
	}
	spin_unlock(&conn->request_lock);

	wake_up_all(&conn->req_running_q);
	return ret;
@@ -326,10 +324,7 @@ int ksmbd_conn_handler_loop(void *p)

		/* 4 for rfc1002 length field */
		size = pdu_size + 4;
		conn->request_buf = kvmalloc(size,
					     GFP_KERNEL |
					     __GFP_NOWARN |
					     __GFP_NORETRY);
		conn->request_buf = kvmalloc(size, GFP_KERNEL);
		if (!conn->request_buf)
			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                            synchronous:1;
	bool                            asynchronous:1;
	bool                            need_invalidate_rkey:1;

	unsigned int                    remote_key;
+1 −4
Original line number Diff line number Diff line
@@ -289,10 +289,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
	work->request_buf = conn->request_buf;
	conn->request_buf = NULL;

	if (ksmbd_init_smb_server(work)) {
		ksmbd_free_work_struct(work);
		return -EINVAL;
	}
	ksmbd_init_smb_server(work);

	ksmbd_conn_enqueue_request(work);
	atomic_inc(&conn->r_count);
+21 −15
Original line number Diff line number Diff line
@@ -229,9 +229,6 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
	struct smb2_negotiate_rsp *rsp;
	struct ksmbd_conn *conn = work->conn;

	if (conn->need_neg == false)
		return -EINVAL;

	*(__be32 *)work->response_buf =
		cpu_to_be32(conn->vals->header_size);

@@ -498,12 +495,6 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
	rsp_hdr->SessionId = rcv_hdr->SessionId;
	memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);

	work->synchronous = true;
	if (work->async_id) {
		ksmbd_release_id(&conn->async_ida, work->async_id);
		work->async_id = 0;
	}

	return 0;
}

@@ -644,7 +635,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
		pr_err("Failed to alloc async message id\n");
		return id;
	}
	work->synchronous = false;
	work->asynchronous = true;
	work->async_id = id;
	rsp_hdr->Id.AsyncId = cpu_to_le64(id);

@@ -664,6 +655,24 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
	return 0;
}

void release_async_work(struct ksmbd_work *work)
{
	struct ksmbd_conn *conn = work->conn;

	spin_lock(&conn->request_lock);
	list_del_init(&work->async_request_entry);
	spin_unlock(&conn->request_lock);

	work->asynchronous = 0;
	work->cancel_fn = NULL;
	kfree(work->cancel_argv);
	work->cancel_argv = NULL;
	if (work->async_id) {
		ksmbd_release_id(&conn->async_ida, work->async_id);
		work->async_id = 0;
	}
}

void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
{
	struct smb2_hdr *rsp_hdr;
@@ -7045,13 +7054,9 @@ int smb2_lock(struct ksmbd_work *work)

				ksmbd_vfs_posix_lock_wait(flock);

				spin_lock(&work->conn->request_lock);
				spin_lock(&fp->f_lock);
				list_del(&work->fp_entry);
				work->cancel_fn = NULL;
				kfree(argv);
				spin_unlock(&fp->f_lock);
				spin_unlock(&work->conn->request_lock);

				if (work->state != KSMBD_WORK_ACTIVE) {
					list_del(&smb_lock->llist);
@@ -7069,6 +7074,7 @@ int smb2_lock(struct ksmbd_work *work)
						work->send_no_response = 1;
						goto out;
					}

					init_smb2_rsp_hdr(work);
					smb2_set_err_rsp(work);
					rsp->hdr.Status =
@@ -7081,7 +7087,7 @@ int smb2_lock(struct ksmbd_work *work)
				spin_lock(&work->conn->llist_lock);
				list_del(&smb_lock->clist);
				spin_unlock(&work->conn->llist_lock);

				release_async_work(work);
				goto retry;
			} else if (!rc) {
				spin_lock(&work->conn->llist_lock);
+1 −0
Original line number Diff line number Diff line
@@ -486,6 +486,7 @@ int find_matching_smb2_dialect(int start_index, __le16 *cli_dialects,
struct file_lock *smb_flock_init(struct file *f);
int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
		     void **arg);
void release_async_work(struct ksmbd_work *work);
void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
struct channel *lookup_chann_list(struct ksmbd_session *sess,
				  struct ksmbd_conn *conn);
Loading