Unverified Commit 1b973c5f authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!14935 Two CVE fixes for ksmbd

Merge Pull Request from: @ci-robot 
 
PR sync from: Wang Zhaolong <wangzhaolong1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/QZONKRE4UUF7CZ54XU77KIYSHBP7P4AB/ 
Namjae Jeon (2):
  ksmbd: fix slab-out-of-bounds in smb_strndup_from_utf16()
  ksmbd: fix potencial out-of-bounds when buffer offset is invalid


-- 
2.34.3
 
https://gitee.com/src-openeuler/kernel/issues/I9L5E3
https://gitee.com/src-openeuler/kernel/issues/I9L5L1 
 
Link:https://gitee.com/openeuler/kernel/pulls/14935

 

Reviewed-by: default avatarZhang Peng <zhangpeng362@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 4f125e10 969190c7
Loading
Loading
Loading
Loading
+19 −7
Original line number Diff line number Diff line
@@ -101,13 +101,17 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
		*len = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferLength);
		break;
	case SMB2_TREE_CONNECT:
		*off = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset);
		*off = max_t(unsigned short int,
			     le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset),
			     offsetof(struct smb2_tree_connect_req, Buffer));
		*len = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength);
		break;
	case SMB2_CREATE:
	{
		unsigned short int name_off =
			le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset);
			max_t(unsigned short int,
			      le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset),
			      offsetof(struct smb2_create_req, Buffer));
		unsigned short int name_len =
			le16_to_cpu(((struct smb2_create_req *)hdr)->NameLength);

@@ -128,11 +132,15 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
		break;
	}
	case SMB2_QUERY_INFO:
		*off = le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset);
		*off = max_t(unsigned int,
			     le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset),
			     offsetof(struct smb2_query_info_req, Buffer));
		*len = le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLength);
		break;
	case SMB2_SET_INFO:
		*off = le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset);
		*off = max_t(unsigned int,
			     le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset),
			     offsetof(struct smb2_set_info_req, Buffer));
		*len = le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength);
		break;
	case SMB2_READ:
@@ -142,7 +150,7 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
	case SMB2_WRITE:
		if (((struct smb2_write_req *)hdr)->DataOffset ||
		    ((struct smb2_write_req *)hdr)->Length) {
			*off = max_t(unsigned int,
			*off = max_t(unsigned short int,
				     le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset),
				     offsetof(struct smb2_write_req, Buffer));
			*len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length);
@@ -153,7 +161,9 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
		*len = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLength);
		break;
	case SMB2_QUERY_DIRECTORY:
		*off = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset);
		*off = max_t(unsigned short int,
			     le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset),
			     offsetof(struct smb2_query_directory_req, Buffer));
		*len = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameLength);
		break;
	case SMB2_LOCK:
@@ -168,7 +178,9 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
		break;
	}
	case SMB2_IOCTL:
		*off = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset);
		*off = max_t(unsigned int,
			     le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset),
			     offsetof(struct smb2_ioctl_req, Buffer));
		*len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount);
		break;
	default:
+26 −22
Original line number Diff line number Diff line
@@ -1939,7 +1939,7 @@ int smb2_tree_connect(struct ksmbd_work *work)

	WORK_BUFFERS(work, req, rsp);

	treename = smb_strndup_from_utf16(req->Buffer,
	treename = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->PathOffset),
					  le16_to_cpu(req->PathLength), true,
					  conn->local_nls);
	if (IS_ERR(treename)) {
@@ -2867,7 +2867,7 @@ int smb2_open(struct ksmbd_work *work)
			goto err_out2;
		}

		name = smb2_get_name(req->Buffer,
		name = smb2_get_name((char *)req + le16_to_cpu(req->NameOffset),
				     le16_to_cpu(req->NameLength),
				     work->conn->local_nls);
		if (IS_ERR(name)) {
@@ -4336,7 +4336,7 @@ int smb2_query_dir(struct ksmbd_work *work)
	}

	srch_flag = req->Flags;
	srch_ptr = smb_strndup_from_utf16(req->Buffer,
	srch_ptr = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->FileNameOffset),
					  le16_to_cpu(req->FileNameLength), 1,
					  conn->local_nls);
	if (IS_ERR(srch_ptr)) {
@@ -4597,7 +4597,8 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
		    sizeof(struct smb2_ea_info_req))
			return -EINVAL;

		ea_req = (struct smb2_ea_info_req *)req->Buffer;
		ea_req = (struct smb2_ea_info_req *)((char *)req +
						     le16_to_cpu(req->InputBufferOffset));
	} else {
		/* need to send all EAs, if no specific EA is requested*/
		if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY)
@@ -6256,6 +6257,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
			      struct ksmbd_share_config *share)
{
	unsigned int buf_len = le32_to_cpu(req->BufferLength);
	char *buffer = (char *)req + le16_to_cpu(req->BufferOffset);

	switch (req->FileInfoClass) {
	case FILE_BASIC_INFORMATION:
@@ -6263,7 +6265,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
		if (buf_len < sizeof(struct smb2_file_basic_info))
			return -EINVAL;

		return set_file_basic_info(fp, (struct smb2_file_basic_info *)req->Buffer, share);
		return set_file_basic_info(fp, (struct smb2_file_basic_info *)buffer, share);
	}
	case FILE_ALLOCATION_INFORMATION:
	{
@@ -6271,7 +6273,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
			return -EINVAL;

		return set_file_allocation_info(work, fp,
						(struct smb2_file_alloc_info *)req->Buffer);
						(struct smb2_file_alloc_info *)buffer);
	}
	case FILE_END_OF_FILE_INFORMATION:
	{
@@ -6279,7 +6281,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
			return -EINVAL;

		return set_end_of_file_info(work, fp,
					    (struct smb2_file_eof_info *)req->Buffer);
					    (struct smb2_file_eof_info *)buffer);
	}
	case FILE_RENAME_INFORMATION:
	{
@@ -6287,7 +6289,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
			return -EINVAL;

		return set_rename_info(work, fp,
				       (struct smb2_file_rename_info *)req->Buffer,
				       (struct smb2_file_rename_info *)buffer,
				       buf_len);
	}
	case FILE_LINK_INFORMATION:
@@ -6296,7 +6298,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
			return -EINVAL;

		return smb2_create_link(work, work->tcon->share_conf,
					(struct smb2_file_link_info *)req->Buffer,
					(struct smb2_file_link_info *)buffer,
					buf_len, fp->filp,
					work->conn->local_nls);
	}
@@ -6306,7 +6308,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
			return -EINVAL;

		return set_file_disposition_info(fp,
						 (struct smb2_file_disposition_info *)req->Buffer);
						 (struct smb2_file_disposition_info *)buffer);
	}
	case FILE_FULL_EA_INFORMATION:
	{
@@ -6319,7 +6321,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
		if (buf_len < sizeof(struct smb2_ea_info))
			return -EINVAL;

		return smb2_set_ea((struct smb2_ea_info *)req->Buffer,
		return smb2_set_ea((struct smb2_ea_info *)buffer,
				   buf_len, &fp->filp->f_path, true);
	}
	case FILE_POSITION_INFORMATION:
@@ -6327,14 +6329,14 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
		if (buf_len < sizeof(struct smb2_file_pos_info))
			return -EINVAL;

		return set_file_position_info(fp, (struct smb2_file_pos_info *)req->Buffer);
		return set_file_position_info(fp, (struct smb2_file_pos_info *)buffer);
	}
	case FILE_MODE_INFORMATION:
	{
		if (buf_len < sizeof(struct smb2_file_mode_info))
			return -EINVAL;

		return set_file_mode_info(fp, (struct smb2_file_mode_info *)req->Buffer);
		return set_file_mode_info(fp, (struct smb2_file_mode_info *)buffer);
	}
	}

@@ -6415,7 +6417,7 @@ int smb2_set_info(struct ksmbd_work *work)
		}
		rc = smb2_set_info_sec(fp,
				       le32_to_cpu(req->AdditionalInformation),
				       req->Buffer,
				       (char *)req + le16_to_cpu(req->BufferOffset),
				       le32_to_cpu(req->BufferLength));
		ksmbd_revert_fsids(work);
		break;
@@ -7867,7 +7869,7 @@ static int fsctl_pipe_transceive(struct ksmbd_work *work, u64 id,
				 struct smb2_ioctl_rsp *rsp)
{
	struct ksmbd_rpc_command *rpc_resp;
	char *data_buf = (char *)&req->Buffer[0];
	char *data_buf = (char *)req + le32_to_cpu(req->InputOffset);
	int nbytes = 0;

	rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf,
@@ -7980,6 +7982,7 @@ int smb2_ioctl(struct ksmbd_work *work)
	u64 id = KSMBD_NO_FID;
	struct ksmbd_conn *conn = work->conn;
	int ret = 0;
	char *buffer;

	if (work->next_smb2_rcv_hdr_off) {
		req = ksmbd_req_buf_next(work);
@@ -8002,6 +8005,8 @@ int smb2_ioctl(struct ksmbd_work *work)
		goto out;
	}

	buffer = (char *)req + le32_to_cpu(req->InputOffset);

	cnt_code = le32_to_cpu(req->CtlCode);
	ret = smb2_calc_max_out_buf_len(work, 48,
					le32_to_cpu(req->MaxOutputResponse));
@@ -8059,7 +8064,7 @@ int smb2_ioctl(struct ksmbd_work *work)
		}

		ret = fsctl_validate_negotiate_info(conn,
			(struct validate_negotiate_info_req *)&req->Buffer[0],
			(struct validate_negotiate_info_req *)buffer,
			(struct validate_negotiate_info_rsp *)&rsp->Buffer[0],
			in_buf_len);
		if (ret < 0)
@@ -8112,7 +8117,7 @@ int smb2_ioctl(struct ksmbd_work *work)
		rsp->VolatileFileId = req->VolatileFileId;
		rsp->PersistentFileId = req->PersistentFileId;
		fsctl_copychunk(work,
				(struct copychunk_ioctl_req *)&req->Buffer[0],
				(struct copychunk_ioctl_req *)buffer,
				le32_to_cpu(req->CtlCode),
				le32_to_cpu(req->InputCount),
				req->VolatileFileId,
@@ -8125,8 +8130,7 @@ int smb2_ioctl(struct ksmbd_work *work)
			goto out;
		}

		ret = fsctl_set_sparse(work, id,
				       (struct file_sparse *)&req->Buffer[0]);
		ret = fsctl_set_sparse(work, id, (struct file_sparse *)buffer);
		if (ret < 0)
			goto out;
		break;
@@ -8149,7 +8153,7 @@ int smb2_ioctl(struct ksmbd_work *work)
		}

		zero_data =
			(struct file_zero_data_information *)&req->Buffer[0];
			(struct file_zero_data_information *)buffer;

		off = le64_to_cpu(zero_data->FileOffset);
		bfz = le64_to_cpu(zero_data->BeyondFinalZero);
@@ -8180,7 +8184,7 @@ int smb2_ioctl(struct ksmbd_work *work)
		}

		ret = fsctl_query_allocated_ranges(work, id,
			(struct file_allocated_range_buffer *)&req->Buffer[0],
			(struct file_allocated_range_buffer *)buffer,
			(struct file_allocated_range_buffer *)&rsp->Buffer[0],
			out_buf_len /
			sizeof(struct file_allocated_range_buffer), &nbytes);
@@ -8224,7 +8228,7 @@ int smb2_ioctl(struct ksmbd_work *work)
			goto out;
		}

		dup_ext = (struct duplicate_extents_to_file *)&req->Buffer[0];
		dup_ext = (struct duplicate_extents_to_file *)buffer;

		fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle,
					     dup_ext->PersistentFileHandle);