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

Merge tag 'v6.19-rc2-smb3-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

 - Fix parsing of SMB1 negotiate request by adjusting offsets affected
   by the removal of the RFC1002 length field from the SMB header

 - Update minimum PDU size macros for both SMB1 and SMB2

 - Rename smb2_get_msg function to smb_get_msg to better reflect its
   role in handling both SMB1 and SMB2 requests

* tag 'v6.19-rc2-smb3-server-fixes' of git://git.samba.org/ksmbd:
  smb/server: fix minimum SMB2 PDU size
  smb/server: fix minimum SMB1 PDU size
  ksmbd: rename smb2_get_msg to smb_get_msg
  ksmbd: Fix to handle removal of rfc1002 header from smb_hdr
parents ccd1cdca 4c7d8eb9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -714,7 +714,7 @@ void ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
				     __u8 *pi_hash)
{
	struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
	struct smb2_hdr *rcv_hdr = smb_get_msg(buf);
	char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
	int msg_size = get_rfc1002_len(buf);
	struct sha512_ctx sha_ctx;
@@ -841,7 +841,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
			unsigned int nvec, int enc)
{
	struct ksmbd_conn *conn = work->conn;
	struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
	struct smb2_transform_hdr *tr_hdr = smb_get_msg(iov[0].iov_base);
	unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
	int rc;
	struct scatterlist *sg;
+6 −5
Original line number Diff line number Diff line
@@ -295,8 +295,9 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn)
	return true;
}

#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))
#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
/* "+2" for BCC field (ByteCount, 2 bytes) */
#define SMB1_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb_hdr) + 2)
#define SMB2_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb2_pdu))

/**
 * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
@@ -363,7 +364,7 @@ int ksmbd_conn_handler_loop(void *p)
		if (pdu_size > MAX_STREAM_PROT_LEN)
			break;

		if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)
		if (pdu_size < SMB1_MIN_SUPPORTED_PDU_SIZE)
			break;

		/* 4 for rfc1002 length field */
@@ -394,9 +395,9 @@ int ksmbd_conn_handler_loop(void *p)
		if (!ksmbd_smb_request(conn))
			break;

		if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
		if (((struct smb2_hdr *)smb_get_msg(conn->request_buf))->ProtocolId ==
		    SMB2_PROTO_NUMBER) {
			if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
			if (pdu_size < SMB2_MIN_SUPPORTED_PDU_SIZE)
				break;
		}

+4 −4
Original line number Diff line number Diff line
@@ -637,7 +637,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
		goto out;
	}

	rsp_hdr = smb2_get_msg(work->response_buf);
	rsp_hdr = smb_get_msg(work->response_buf);
	memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
	rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
	rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
@@ -651,7 +651,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
	rsp_hdr->SessionId = 0;
	memset(rsp_hdr->Signature, 0, 16);

	rsp = smb2_get_msg(work->response_buf);
	rsp = smb_get_msg(work->response_buf);

	rsp->StructureSize = cpu_to_le16(24);
	if (!br_info->open_trunc &&
@@ -744,7 +744,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
		goto out;
	}

	rsp_hdr = smb2_get_msg(work->response_buf);
	rsp_hdr = smb_get_msg(work->response_buf);
	memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
	rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
	rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
@@ -758,7 +758,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
	rsp_hdr->SessionId = 0;
	memset(rsp_hdr->Signature, 0, 16);

	rsp = smb2_get_msg(work->response_buf);
	rsp = smb_get_msg(work->response_buf);
	rsp->StructureSize = cpu_to_le16(44);
	rsp->Epoch = br_info->epoch;
	rsp->Flags = 0;
+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ static inline int check_conn_state(struct ksmbd_work *work)

	if (ksmbd_conn_exiting(work->conn) ||
	    ksmbd_conn_need_reconnect(work->conn)) {
		rsp_hdr = work->response_buf;
		rsp_hdr = smb_get_msg(work->response_buf);
		rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED;
		return 1;
	}
+35 −35
Original line number Diff line number Diff line
@@ -47,8 +47,8 @@ static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
		*req = ksmbd_req_buf_next(work);
		*rsp = ksmbd_resp_buf_next(work);
	} else {
		*req = smb2_get_msg(work->request_buf);
		*rsp = smb2_get_msg(work->response_buf);
		*req = smb_get_msg(work->request_buf);
		*rsp = smb_get_msg(work->response_buf);
	}
}

@@ -146,7 +146,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
	if (work->next_smb2_rcv_hdr_off)
		err_rsp = ksmbd_resp_buf_next(work);
	else
		err_rsp = smb2_get_msg(work->response_buf);
		err_rsp = smb_get_msg(work->response_buf);

	if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) {
		int err;
@@ -172,7 +172,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
 */
bool is_smb2_neg_cmd(struct ksmbd_work *work)
{
	struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
	struct smb2_hdr *hdr = smb_get_msg(work->request_buf);

	/* is it SMB2 header ? */
	if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -196,7 +196,7 @@ bool is_smb2_neg_cmd(struct ksmbd_work *work)
 */
bool is_smb2_rsp(struct ksmbd_work *work)
{
	struct smb2_hdr *hdr = smb2_get_msg(work->response_buf);
	struct smb2_hdr *hdr = smb_get_msg(work->response_buf);

	/* is it SMB2 header ? */
	if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -222,7 +222,7 @@ u16 get_smb2_cmd_val(struct ksmbd_work *work)
	if (work->next_smb2_rcv_hdr_off)
		rcv_hdr = ksmbd_req_buf_next(work);
	else
		rcv_hdr = smb2_get_msg(work->request_buf);
		rcv_hdr = smb_get_msg(work->request_buf);
	return le16_to_cpu(rcv_hdr->Command);
}

@@ -235,7 +235,7 @@ void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
{
	struct smb2_hdr *rsp_hdr;

	rsp_hdr = smb2_get_msg(work->response_buf);
	rsp_hdr = smb_get_msg(work->response_buf);
	rsp_hdr->Status = err;

	work->iov_idx = 0;
@@ -258,7 +258,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
	struct ksmbd_conn *conn = work->conn;
	int err;

	rsp_hdr = smb2_get_msg(work->response_buf);
	rsp_hdr = smb_get_msg(work->response_buf);
	memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
	rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
	rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
@@ -272,7 +272,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
	rsp_hdr->SessionId = 0;
	memset(rsp_hdr->Signature, 0, 16);

	rsp = smb2_get_msg(work->response_buf);
	rsp = smb_get_msg(work->response_buf);

	WARN_ON(ksmbd_conn_good(conn));

@@ -446,7 +446,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
 */
bool is_chained_smb2_message(struct ksmbd_work *work)
{
	struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
	struct smb2_hdr *hdr = smb_get_msg(work->request_buf);
	unsigned int len, next_cmd;

	if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
@@ -497,8 +497,8 @@ bool is_chained_smb2_message(struct ksmbd_work *work)
 */
int init_smb2_rsp_hdr(struct ksmbd_work *work)
{
	struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf);
	struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf);
	struct smb2_hdr *rsp_hdr = smb_get_msg(work->response_buf);
	struct smb2_hdr *rcv_hdr = smb_get_msg(work->request_buf);

	memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
	rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
@@ -527,7 +527,7 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
 */
int smb2_allocate_rsp_buf(struct ksmbd_work *work)
{
	struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
	struct smb2_hdr *hdr = smb_get_msg(work->request_buf);
	size_t small_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
	size_t large_sz = small_sz + work->conn->vals->max_trans_size;
	size_t sz = small_sz;
@@ -543,7 +543,7 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
		    offsetof(struct smb2_query_info_req, OutputBufferLength))
			return -EINVAL;

		req = smb2_get_msg(work->request_buf);
		req = smb_get_msg(work->request_buf);
		if ((req->InfoType == SMB2_O_INFO_FILE &&
		     (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
		     req->FileInfoClass == FILE_ALL_INFORMATION)) ||
@@ -712,10 +712,10 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
	}

	in_work->conn = work->conn;
	memcpy(smb2_get_msg(in_work->response_buf), ksmbd_resp_buf_next(work),
	memcpy(smb_get_msg(in_work->response_buf), ksmbd_resp_buf_next(work),
	       __SMB2_HEADER_STRUCTURE_SIZE);

	rsp_hdr = smb2_get_msg(in_work->response_buf);
	rsp_hdr = smb_get_msg(in_work->response_buf);
	rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
	rsp_hdr->Id.AsyncId = cpu_to_le64(work->async_id);
	smb2_set_err_rsp(in_work);
@@ -1093,8 +1093,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
int smb2_handle_negotiate(struct ksmbd_work *work)
{
	struct ksmbd_conn *conn = work->conn;
	struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf);
	struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf);
	struct smb2_negotiate_req *req = smb_get_msg(work->request_buf);
	struct smb2_negotiate_rsp *rsp = smb_get_msg(work->response_buf);
	int rc = 0;
	unsigned int smb2_buf_len, smb2_neg_size, neg_ctxt_len = 0;
	__le32 status;
@@ -5967,7 +5967,7 @@ int smb2_close(struct ksmbd_work *work)
 */
int smb2_echo(struct ksmbd_work *work)
{
	struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
	struct smb2_echo_rsp *rsp = smb_get_msg(work->response_buf);

	ksmbd_debug(SMB, "Received smb2 echo request\n");

@@ -6520,8 +6520,8 @@ int smb2_set_info(struct ksmbd_work *work)
			pid = work->compound_pfid;
		}
	} else {
		req = smb2_get_msg(work->request_buf);
		rsp = smb2_get_msg(work->response_buf);
		req = smb_get_msg(work->request_buf);
		rsp = smb_get_msg(work->response_buf);
	}

	if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
@@ -6754,8 +6754,8 @@ int smb2_read(struct ksmbd_work *work)
			pid = work->compound_pfid;
		}
	} else {
		req = smb2_get_msg(work->request_buf);
		rsp = smb2_get_msg(work->response_buf);
		req = smb_get_msg(work->request_buf);
		rsp = smb_get_msg(work->response_buf);
	}

	if (!has_file_id(id)) {
@@ -7183,7 +7183,7 @@ int smb2_flush(struct ksmbd_work *work)
int smb2_cancel(struct ksmbd_work *work)
{
	struct ksmbd_conn *conn = work->conn;
	struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
	struct smb2_hdr *hdr = smb_get_msg(work->request_buf);
	struct smb2_hdr *chdr;
	struct ksmbd_work *iter;
	struct list_head *command_list;
@@ -7200,7 +7200,7 @@ int smb2_cancel(struct ksmbd_work *work)
		spin_lock(&conn->request_lock);
		list_for_each_entry(iter, command_list,
				    async_request_entry) {
			chdr = smb2_get_msg(iter->request_buf);
			chdr = smb_get_msg(iter->request_buf);

			if (iter->async_id !=
			    le64_to_cpu(hdr->Id.AsyncId))
@@ -7221,7 +7221,7 @@ int smb2_cancel(struct ksmbd_work *work)

		spin_lock(&conn->request_lock);
		list_for_each_entry(iter, command_list, request_entry) {
			chdr = smb2_get_msg(iter->request_buf);
			chdr = smb_get_msg(iter->request_buf);

			if (chdr->MessageId != hdr->MessageId ||
			    iter == work)
@@ -8151,8 +8151,8 @@ int smb2_ioctl(struct ksmbd_work *work)
			id = work->compound_fid;
		}
	} else {
		req = smb2_get_msg(work->request_buf);
		rsp = smb2_get_msg(work->response_buf);
		req = smb_get_msg(work->request_buf);
		rsp = smb_get_msg(work->response_buf);
	}

	if (!has_file_id(id))
@@ -8817,7 +8817,7 @@ int smb2_notify(struct ksmbd_work *work)
 */
bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
{
	struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf);
	struct smb2_hdr *rcv_hdr2 = smb_get_msg(work->request_buf);

	if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) &&
	    command != SMB2_NEGOTIATE_HE &&
@@ -8842,7 +8842,7 @@ int smb2_check_sign_req(struct ksmbd_work *work)
	struct kvec iov[1];
	size_t len;

	hdr = smb2_get_msg(work->request_buf);
	hdr = smb_get_msg(work->request_buf);
	if (work->next_smb2_rcv_hdr_off)
		hdr = ksmbd_req_buf_next(work);

@@ -8916,7 +8916,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
	struct kvec iov[1];
	size_t len;

	hdr = smb2_get_msg(work->request_buf);
	hdr = smb_get_msg(work->request_buf);
	if (work->next_smb2_rcv_hdr_off)
		hdr = ksmbd_req_buf_next(work);

@@ -9049,7 +9049,7 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
{
	struct smb2_transform_hdr *tr_hdr = tr_buf + 4;
	struct smb2_hdr *hdr = smb2_get_msg(old_buf);
	struct smb2_hdr *hdr = smb_get_msg(old_buf);
	unsigned int orig_len = get_rfc1002_len(old_buf);

	/* tr_buf must be cleared by the caller */
@@ -9088,7 +9088,7 @@ int smb3_encrypt_resp(struct ksmbd_work *work)

bool smb3_is_transform_hdr(void *buf)
{
	struct smb2_transform_hdr *trhdr = smb2_get_msg(buf);
	struct smb2_transform_hdr *trhdr = smb_get_msg(buf);

	return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
}
@@ -9100,7 +9100,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
	unsigned int pdu_length = get_rfc1002_len(buf);
	struct kvec iov[2];
	int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr);
	struct smb2_transform_hdr *tr_hdr = smb2_get_msg(buf);
	struct smb2_transform_hdr *tr_hdr = smb_get_msg(buf);
	int rc = 0;

	if (pdu_length < sizeof(struct smb2_transform_hdr) ||
@@ -9141,7 +9141,7 @@ bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
{
	struct ksmbd_conn *conn = work->conn;
	struct ksmbd_session *sess = work->sess;
	struct smb2_hdr *rsp = smb2_get_msg(work->response_buf);
	struct smb2_hdr *rsp = smb_get_msg(work->response_buf);

	if (conn->dialect < SMB30_PROT_ID)
		return false;
Loading