cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

smb2misc.c (13434B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
      4 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
      5 */
      6
      7#include "glob.h"
      8#include "nterr.h"
      9#include "smb_common.h"
     10#include "smbstatus.h"
     11#include "mgmt/user_session.h"
     12#include "connection.h"
     13
     14static int check_smb2_hdr(struct smb2_hdr *hdr)
     15{
     16	/*
     17	 * Make sure that this really is an SMB, that it is a response.
     18	 */
     19	if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
     20		return 1;
     21	return 0;
     22}
     23
     24/*
     25 *  The following table defines the expected "StructureSize" of SMB2 requests
     26 *  in order by SMB2 command.  This is similar to "wct" in SMB/CIFS requests.
     27 *
     28 *  Note that commands are defined in smb2pdu.h in le16 but the array below is
     29 *  indexed by command in host byte order
     30 */
     31static const __le16 smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
     32	/* SMB2_NEGOTIATE */ cpu_to_le16(36),
     33	/* SMB2_SESSION_SETUP */ cpu_to_le16(25),
     34	/* SMB2_LOGOFF */ cpu_to_le16(4),
     35	/* SMB2_TREE_CONNECT */ cpu_to_le16(9),
     36	/* SMB2_TREE_DISCONNECT */ cpu_to_le16(4),
     37	/* SMB2_CREATE */ cpu_to_le16(57),
     38	/* SMB2_CLOSE */ cpu_to_le16(24),
     39	/* SMB2_FLUSH */ cpu_to_le16(24),
     40	/* SMB2_READ */ cpu_to_le16(49),
     41	/* SMB2_WRITE */ cpu_to_le16(49),
     42	/* SMB2_LOCK */ cpu_to_le16(48),
     43	/* SMB2_IOCTL */ cpu_to_le16(57),
     44	/* SMB2_CANCEL */ cpu_to_le16(4),
     45	/* SMB2_ECHO */ cpu_to_le16(4),
     46	/* SMB2_QUERY_DIRECTORY */ cpu_to_le16(33),
     47	/* SMB2_CHANGE_NOTIFY */ cpu_to_le16(32),
     48	/* SMB2_QUERY_INFO */ cpu_to_le16(41),
     49	/* SMB2_SET_INFO */ cpu_to_le16(33),
     50	/* use 44 for lease break */
     51	/* SMB2_OPLOCK_BREAK */ cpu_to_le16(36)
     52};
     53
     54/*
     55 * The size of the variable area depends on the offset and length fields
     56 * located in different fields for various SMB2 requests. SMB2 requests
     57 * with no variable length info, show an offset of zero for the offset field.
     58 */
     59static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
     60	/* SMB2_NEGOTIATE */ true,
     61	/* SMB2_SESSION_SETUP */ true,
     62	/* SMB2_LOGOFF */ false,
     63	/* SMB2_TREE_CONNECT */	true,
     64	/* SMB2_TREE_DISCONNECT */ false,
     65	/* SMB2_CREATE */ true,
     66	/* SMB2_CLOSE */ false,
     67	/* SMB2_FLUSH */ false,
     68	/* SMB2_READ */	true,
     69	/* SMB2_WRITE */ true,
     70	/* SMB2_LOCK */	true,
     71	/* SMB2_IOCTL */ true,
     72	/* SMB2_CANCEL */ false, /* BB CHECK this not listed in documentation */
     73	/* SMB2_ECHO */ false,
     74	/* SMB2_QUERY_DIRECTORY */ true,
     75	/* SMB2_CHANGE_NOTIFY */ false,
     76	/* SMB2_QUERY_INFO */ true,
     77	/* SMB2_SET_INFO */ true,
     78	/* SMB2_OPLOCK_BREAK */ false
     79};
     80
     81/*
     82 * Set length of the data area and the offset to arguments.
     83 * if they are invalid, return error.
     84 */
     85static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
     86				  struct smb2_hdr *hdr)
     87{
     88	int ret = 0;
     89
     90	*off = 0;
     91	*len = 0;
     92
     93	/* error reqeusts do not have data area */
     94	if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
     95	    (((struct smb2_err_rsp *)hdr)->StructureSize) == SMB2_ERROR_STRUCTURE_SIZE2_LE)
     96		return ret;
     97
     98	/*
     99	 * Following commands have data areas so we have to get the location
    100	 * of the data buffer offset and data buffer length for the particular
    101	 * command.
    102	 */
    103	switch (hdr->Command) {
    104	case SMB2_SESSION_SETUP:
    105		*off = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferOffset);
    106		*len = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferLength);
    107		break;
    108	case SMB2_TREE_CONNECT:
    109		*off = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset);
    110		*len = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength);
    111		break;
    112	case SMB2_CREATE:
    113	{
    114		if (((struct smb2_create_req *)hdr)->CreateContextsLength) {
    115			*off = le32_to_cpu(((struct smb2_create_req *)
    116				hdr)->CreateContextsOffset);
    117			*len = le32_to_cpu(((struct smb2_create_req *)
    118				hdr)->CreateContextsLength);
    119			break;
    120		}
    121
    122		*off = le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset);
    123		*len = le16_to_cpu(((struct smb2_create_req *)hdr)->NameLength);
    124		break;
    125	}
    126	case SMB2_QUERY_INFO:
    127		*off = le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset);
    128		*len = le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLength);
    129		break;
    130	case SMB2_SET_INFO:
    131		*off = le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset);
    132		*len = le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength);
    133		break;
    134	case SMB2_READ:
    135		*off = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoOffset);
    136		*len = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoLength);
    137		break;
    138	case SMB2_WRITE:
    139		if (((struct smb2_write_req *)hdr)->DataOffset) {
    140			*off = le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset);
    141			*len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length);
    142			break;
    143		}
    144
    145		*off = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoOffset);
    146		*len = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLength);
    147		break;
    148	case SMB2_QUERY_DIRECTORY:
    149		*off = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset);
    150		*len = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameLength);
    151		break;
    152	case SMB2_LOCK:
    153	{
    154		int lock_count;
    155
    156		/*
    157		 * smb2_lock request size is 48 included single
    158		 * smb2_lock_element structure size.
    159		 */
    160		lock_count = le16_to_cpu(((struct smb2_lock_req *)hdr)->LockCount) - 1;
    161		if (lock_count > 0) {
    162			*off = __SMB2_HEADER_STRUCTURE_SIZE + 48;
    163			*len = sizeof(struct smb2_lock_element) * lock_count;
    164		}
    165		break;
    166	}
    167	case SMB2_IOCTL:
    168		*off = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset);
    169		*len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount);
    170		break;
    171	default:
    172		ksmbd_debug(SMB, "no length check for command\n");
    173		break;
    174	}
    175
    176	if (*off > 4096) {
    177		ksmbd_debug(SMB, "offset %d too large\n", *off);
    178		ret = -EINVAL;
    179	} else if ((u64)*off + *len > MAX_STREAM_PROT_LEN) {
    180		ksmbd_debug(SMB, "Request is larger than maximum stream protocol length(%u): %llu\n",
    181			    MAX_STREAM_PROT_LEN, (u64)*off + *len);
    182		ret = -EINVAL;
    183	}
    184
    185	return ret;
    186}
    187
    188/*
    189 * Calculate the size of the SMB message based on the fixed header
    190 * portion, the number of word parameters and the data portion of the message.
    191 */
    192static int smb2_calc_size(void *buf, unsigned int *len)
    193{
    194	struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
    195	struct smb2_hdr *hdr = &pdu->hdr;
    196	unsigned int offset; /* the offset from the beginning of SMB to data area */
    197	unsigned int data_length; /* the length of the variable length data area */
    198	int ret;
    199
    200	/* Structure Size has already been checked to make sure it is 64 */
    201	*len = le16_to_cpu(hdr->StructureSize);
    202
    203	/*
    204	 * StructureSize2, ie length of fixed parameter area has already
    205	 * been checked to make sure it is the correct length.
    206	 */
    207	*len += le16_to_cpu(pdu->StructureSize2);
    208	/*
    209	 * StructureSize2 of smb2_lock pdu is set to 48, indicating
    210	 * the size of smb2 lock request with single smb2_lock_element
    211	 * regardless of number of locks. Subtract single
    212	 * smb2_lock_element for correct buffer size check.
    213	 */
    214	if (hdr->Command == SMB2_LOCK)
    215		*len -= sizeof(struct smb2_lock_element);
    216
    217	if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false)
    218		goto calc_size_exit;
    219
    220	ret = smb2_get_data_area_len(&offset, &data_length, hdr);
    221	if (ret)
    222		return ret;
    223	ksmbd_debug(SMB, "SMB2 data length %u offset %u\n", data_length,
    224		    offset);
    225
    226	if (data_length > 0) {
    227		/*
    228		 * Check to make sure that data area begins after fixed area,
    229		 * Note that last byte of the fixed area is part of data area
    230		 * for some commands, typically those with odd StructureSize,
    231		 * so we must add one to the calculation.
    232		 */
    233		if (offset + 1 < *len) {
    234			ksmbd_debug(SMB,
    235				    "data area offset %d overlaps SMB2 header %u\n",
    236				    offset + 1, *len);
    237			return -EINVAL;
    238		}
    239
    240		*len = offset + data_length;
    241	}
    242
    243calc_size_exit:
    244	ksmbd_debug(SMB, "SMB2 len %u\n", *len);
    245	return 0;
    246}
    247
    248static inline int smb2_query_info_req_len(struct smb2_query_info_req *h)
    249{
    250	return le32_to_cpu(h->InputBufferLength) +
    251		le32_to_cpu(h->OutputBufferLength);
    252}
    253
    254static inline int smb2_set_info_req_len(struct smb2_set_info_req *h)
    255{
    256	return le32_to_cpu(h->BufferLength);
    257}
    258
    259static inline int smb2_read_req_len(struct smb2_read_req *h)
    260{
    261	return le32_to_cpu(h->Length);
    262}
    263
    264static inline int smb2_write_req_len(struct smb2_write_req *h)
    265{
    266	return le32_to_cpu(h->Length);
    267}
    268
    269static inline int smb2_query_dir_req_len(struct smb2_query_directory_req *h)
    270{
    271	return le32_to_cpu(h->OutputBufferLength);
    272}
    273
    274static inline int smb2_ioctl_req_len(struct smb2_ioctl_req *h)
    275{
    276	return le32_to_cpu(h->InputCount) +
    277		le32_to_cpu(h->OutputCount);
    278}
    279
    280static inline int smb2_ioctl_resp_len(struct smb2_ioctl_req *h)
    281{
    282	return le32_to_cpu(h->MaxInputResponse) +
    283		le32_to_cpu(h->MaxOutputResponse);
    284}
    285
    286static int smb2_validate_credit_charge(struct ksmbd_conn *conn,
    287				       struct smb2_hdr *hdr)
    288{
    289	unsigned int req_len = 0, expect_resp_len = 0, calc_credit_num, max_len;
    290	unsigned short credit_charge = le16_to_cpu(hdr->CreditCharge);
    291	void *__hdr = hdr;
    292	int ret = 0;
    293
    294	switch (hdr->Command) {
    295	case SMB2_QUERY_INFO:
    296		req_len = smb2_query_info_req_len(__hdr);
    297		break;
    298	case SMB2_SET_INFO:
    299		req_len = smb2_set_info_req_len(__hdr);
    300		break;
    301	case SMB2_READ:
    302		req_len = smb2_read_req_len(__hdr);
    303		break;
    304	case SMB2_WRITE:
    305		req_len = smb2_write_req_len(__hdr);
    306		break;
    307	case SMB2_QUERY_DIRECTORY:
    308		req_len = smb2_query_dir_req_len(__hdr);
    309		break;
    310	case SMB2_IOCTL:
    311		req_len = smb2_ioctl_req_len(__hdr);
    312		expect_resp_len = smb2_ioctl_resp_len(__hdr);
    313		break;
    314	case SMB2_CANCEL:
    315		return 0;
    316	default:
    317		req_len = 1;
    318		break;
    319	}
    320
    321	credit_charge = max_t(unsigned short, credit_charge, 1);
    322	max_len = max_t(unsigned int, req_len, expect_resp_len);
    323	calc_credit_num = DIV_ROUND_UP(max_len, SMB2_MAX_BUFFER_SIZE);
    324
    325	if (credit_charge < calc_credit_num) {
    326		ksmbd_debug(SMB, "Insufficient credit charge, given: %d, needed: %d\n",
    327			    credit_charge, calc_credit_num);
    328		return 1;
    329	} else if (credit_charge > conn->vals->max_credits) {
    330		ksmbd_debug(SMB, "Too large credit charge: %d\n", credit_charge);
    331		return 1;
    332	}
    333
    334	spin_lock(&conn->credits_lock);
    335	if (credit_charge > conn->total_credits) {
    336		ksmbd_debug(SMB, "Insufficient credits granted, given: %u, granted: %u\n",
    337			    credit_charge, conn->total_credits);
    338		ret = 1;
    339	}
    340
    341	if ((u64)conn->outstanding_credits + credit_charge > conn->total_credits) {
    342		ksmbd_debug(SMB, "Limits exceeding the maximum allowable outstanding requests, given : %u, pending : %u\n",
    343			    credit_charge, conn->outstanding_credits);
    344		ret = 1;
    345	} else
    346		conn->outstanding_credits += credit_charge;
    347
    348	spin_unlock(&conn->credits_lock);
    349
    350	return ret;
    351}
    352
    353int ksmbd_smb2_check_message(struct ksmbd_work *work)
    354{
    355	struct smb2_pdu *pdu = ksmbd_req_buf_next(work);
    356	struct smb2_hdr *hdr = &pdu->hdr;
    357	int command;
    358	__u32 clc_len;  /* calculated length */
    359	__u32 len = get_rfc1002_len(work->request_buf);
    360
    361	if (le32_to_cpu(hdr->NextCommand) > 0)
    362		len = le32_to_cpu(hdr->NextCommand);
    363	else if (work->next_smb2_rcv_hdr_off)
    364		len -= work->next_smb2_rcv_hdr_off;
    365
    366	if (check_smb2_hdr(hdr))
    367		return 1;
    368
    369	if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
    370		ksmbd_debug(SMB, "Illegal structure size %u\n",
    371			    le16_to_cpu(hdr->StructureSize));
    372		return 1;
    373	}
    374
    375	command = le16_to_cpu(hdr->Command);
    376	if (command >= NUMBER_OF_SMB2_COMMANDS) {
    377		ksmbd_debug(SMB, "Illegal SMB2 command %d\n", command);
    378		return 1;
    379	}
    380
    381	if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
    382		if (command != SMB2_OPLOCK_BREAK_HE &&
    383		    (hdr->Status == 0 || pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2_LE)) {
    384			/* error packets have 9 byte structure size */
    385			ksmbd_debug(SMB,
    386				    "Illegal request size %u for command %d\n",
    387				    le16_to_cpu(pdu->StructureSize2), command);
    388			return 1;
    389		} else if (command == SMB2_OPLOCK_BREAK_HE &&
    390			   hdr->Status == 0 &&
    391			   le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 &&
    392			   le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) {
    393			/* special case for SMB2.1 lease break message */
    394			ksmbd_debug(SMB,
    395				    "Illegal request size %d for oplock break\n",
    396				    le16_to_cpu(pdu->StructureSize2));
    397			return 1;
    398		}
    399	}
    400
    401	if (smb2_calc_size(hdr, &clc_len))
    402		return 1;
    403
    404	if (len != clc_len) {
    405		/* client can return one byte more due to implied bcc[0] */
    406		if (clc_len == len + 1)
    407			goto validate_credit;
    408
    409		/*
    410		 * Some windows servers (win2016) will pad also the final
    411		 * PDU in a compound to 8 bytes.
    412		 */
    413		if (ALIGN(clc_len, 8) == len)
    414			goto validate_credit;
    415
    416		/*
    417		 * windows client also pad up to 8 bytes when compounding.
    418		 * If pad is longer than eight bytes, log the server behavior
    419		 * (once), since may indicate a problem but allow it and
    420		 * continue since the frame is parseable.
    421		 */
    422		if (clc_len < len) {
    423			ksmbd_debug(SMB,
    424				    "cli req padded more than expected. Length %d not %d for cmd:%d mid:%llu\n",
    425				    len, clc_len, command,
    426				    le64_to_cpu(hdr->MessageId));
    427			goto validate_credit;
    428		}
    429
    430		ksmbd_debug(SMB,
    431			    "cli req too short, len %d not %d. cmd:%d mid:%llu\n",
    432			    len, clc_len, command,
    433			    le64_to_cpu(hdr->MessageId));
    434
    435		return 1;
    436	}
    437
    438validate_credit:
    439	if ((work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) &&
    440	    smb2_validate_credit_charge(work->conn, hdr)) {
    441		work->conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
    442		return 1;
    443	}
    444
    445	return 0;
    446}
    447
    448int smb2_negotiate_request(struct ksmbd_work *work)
    449{
    450	return ksmbd_smb_negotiate_common(work, SMB2_NEGOTIATE_HE);
    451}