Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61a69296 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mhi: core: fix potential buffer overflow"

parents f07b6516 aa318b65
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -82,12 +82,6 @@ struct bhie_vec_table {

struct bhi_ctxt_t {
	void __iomem *bhi_base;
	void *unaligned_image_loc;
	dma_addr_t dma_handle;
	size_t alloc_size;
	void *image_loc;
	dma_addr_t phy_image_loc;
	size_t image_size;
	dev_t bhi_dev;
	struct cdev cdev;
	struct device *dev;
+36 −49
Original line number Diff line number Diff line
@@ -109,30 +109,29 @@ alloc_bhi_mem_info_error:
}

static int bhi_alloc_pbl_xfer(struct mhi_device_ctxt *mhi_dev_ctxt,
			      struct bhie_mem_info *const mem_info,
			      size_t size)
{
	struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt;
	const phys_addr_t align_len = bhi_ctxt->alignment;
	size_t alloc_size = size + (align_len - 1);
	struct device *dev = &mhi_dev_ctxt->plat_dev->dev;

	bhi_ctxt->unaligned_image_loc =
		dma_alloc_coherent(dev, alloc_size, &bhi_ctxt->dma_handle,
				   GFP_KERNEL);
	if (bhi_ctxt->unaligned_image_loc == NULL)
	mem_info->size = size;
	mem_info->alloc_size = size + (align_len - 1);
	mem_info->pre_aligned =
		dma_alloc_coherent(dev, mem_info->alloc_size,
				   &mem_info->dma_handle, GFP_KERNEL);
	if (mem_info->pre_aligned == NULL)
		return -ENOMEM;

	bhi_ctxt->alloc_size = alloc_size;
	bhi_ctxt->phy_image_loc = (bhi_ctxt->dma_handle + (align_len - 1)) &
	mem_info->phys_addr = (mem_info->dma_handle + (align_len - 1)) &
		~(align_len - 1);
	bhi_ctxt->image_loc = bhi_ctxt->unaligned_image_loc +
		(bhi_ctxt->phy_image_loc - bhi_ctxt->dma_handle);
	bhi_ctxt->image_size = size;

	mem_info->aligned = mem_info->pre_aligned + (mem_info->phys_addr -
						     mem_info->dma_handle);
	mhi_log(mhi_dev_ctxt, MHI_MSG_INFO,
		"alloc_size:%lu image_size:%lu unal_addr:0x%llx0x al_addr:0x%llx\n",
		bhi_ctxt->alloc_size, bhi_ctxt->image_size,
		bhi_ctxt->dma_handle, bhi_ctxt->phy_image_loc);
		mem_info->alloc_size, mem_info->size,
		mem_info->dma_handle, mem_info->phys_addr);

	return 0;
}
@@ -264,7 +263,8 @@ int bhi_rddm(struct mhi_device_ctxt *mhi_dev_ctxt, bool in_panic)
	return -EINVAL;
}

static int bhi_load_firmware(struct mhi_device_ctxt *mhi_dev_ctxt)
static int bhi_load_firmware(struct mhi_device_ctxt *mhi_dev_ctxt,
			     const struct bhie_mem_info  *const mem_info)
{
	struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt;
	u32 pcie_word_val = 0;
@@ -278,22 +278,15 @@ static int bhi_load_firmware(struct mhi_device_ctxt *mhi_dev_ctxt)
		read_unlock_bh(pm_xfer_lock);
		return -EIO;
	}
	pcie_word_val = HIGH_WORD(bhi_ctxt->phy_image_loc);
	mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base,
				BHI_IMGADDR_HIGH,
				0xFFFFFFFF,
				0,
				pcie_word_val);

	pcie_word_val = LOW_WORD(bhi_ctxt->phy_image_loc);
	pcie_word_val = HIGH_WORD(mem_info->phys_addr);
	mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGADDR_HIGH,
			    0xFFFFFFFF, 0, pcie_word_val);

	mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base,
				BHI_IMGADDR_LOW,
				0xFFFFFFFF,
				0,
				pcie_word_val);
	pcie_word_val = LOW_WORD(mem_info->phys_addr);
	mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGADDR_LOW,
			    0xFFFFFFFF, 0, pcie_word_val);

	pcie_word_val = bhi_ctxt->image_size;
	pcie_word_val = mem_info->size;
	mhi_reg_write_field(mhi_dev_ctxt, bhi_ctxt->bhi_base, BHI_IMGSIZE,
			    0xFFFFFFFF, 0, pcie_word_val);

@@ -342,6 +335,7 @@ static ssize_t bhi_write(struct file *file,
	int ret_val = 0;
	struct mhi_device_ctxt *mhi_dev_ctxt = file->private_data;
	struct bhi_ctxt_t *bhi_ctxt = &mhi_dev_ctxt->bhi_ctxt;
	struct bhie_mem_info mem_info;
	long timeout;

	if (buf == NULL || 0 == count)
@@ -350,11 +344,11 @@ static ssize_t bhi_write(struct file *file,
	if (count > BHI_MAX_IMAGE_SIZE)
		return -ENOMEM;

	ret_val = bhi_alloc_pbl_xfer(mhi_dev_ctxt, count);
	ret_val = bhi_alloc_pbl_xfer(mhi_dev_ctxt, &mem_info, count);
	if (ret_val)
		return -ENOMEM;

	if (0 != copy_from_user(bhi_ctxt->image_loc, buf, count)) {
	if (copy_from_user(mem_info.aligned, buf, count)) {
		ret_val = -ENOMEM;
		goto bhi_copy_error;
	}
@@ -370,15 +364,13 @@ static ssize_t bhi_write(struct file *file,
		goto bhi_copy_error;
	}

	ret_val = bhi_load_firmware(mhi_dev_ctxt);
	ret_val = bhi_load_firmware(mhi_dev_ctxt, &mem_info);
	if (ret_val) {
		mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR,
			"Failed to load bhi image\n");
	}
	dma_free_coherent(&mhi_dev_ctxt->plat_dev->dev,
			  bhi_ctxt->alloc_size,
			  bhi_ctxt->unaligned_image_loc,
			  bhi_ctxt->dma_handle);
	dma_free_coherent(&mhi_dev_ctxt->plat_dev->dev, mem_info.alloc_size,
			  mem_info.pre_aligned, mem_info.dma_handle);

	/* Regardless of failure set to RESET state */
	ret_val = mhi_init_state_transition(mhi_dev_ctxt,
@@ -390,10 +382,8 @@ static ssize_t bhi_write(struct file *file,
	return count;

bhi_copy_error:
	dma_free_coherent(&mhi_dev_ctxt->plat_dev->dev,
			  bhi_ctxt->alloc_size,
			  bhi_ctxt->unaligned_image_loc,
			  bhi_ctxt->dma_handle);
	dma_free_coherent(&mhi_dev_ctxt->plat_dev->dev, mem_info.alloc_size,
			  mem_info.pre_aligned, mem_info.dma_handle);

	return ret_val;
}
@@ -447,6 +437,7 @@ void bhi_firmware_download(struct work_struct *work)
{
	struct mhi_device_ctxt *mhi_dev_ctxt;
	struct bhi_ctxt_t *bhi_ctxt;
	struct bhie_mem_info mem_info;
	int ret;
	long timeout;

@@ -459,7 +450,10 @@ void bhi_firmware_download(struct work_struct *work)
	wait_event_interruptible(*mhi_dev_ctxt->mhi_ev_wq.bhi_event,
			mhi_dev_ctxt->mhi_state == MHI_STATE_BHI);

	ret = bhi_load_firmware(mhi_dev_ctxt);
	/* PBL image is the first segment in firmware vector table */
	mem_info = *bhi_ctxt->fw_table.bhie_mem_info;
	mem_info.size = bhi_ctxt->firmware_info.max_sbl_len;
	ret = bhi_load_firmware(mhi_dev_ctxt, &mem_info);
	if (ret) {
		mhi_log(mhi_dev_ctxt, MHI_MSG_ERROR,
			"Failed to Load sbl firmware\n");
@@ -547,13 +541,6 @@ int bhi_probe(struct mhi_device_ctxt *mhi_dev_ctxt)
		image += to_copy;
	}

	/*
	 * Re-use BHI/E pointer for BHI since we guranteed BHI/E segment
	 * is >= to SBL image.
	 */
	bhi_ctxt->phy_image_loc = sg_dma_address(&fw_table->sg_list[1]);
	bhi_ctxt->image_size = fw_info->max_sbl_len;

	fw_table->sequence++;
	release_firmware(firmware);