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

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

Merge "msm: mdss: validate buffer size is enough for intended use"

parents 0e8f2d55 69a0892b
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -1228,11 +1228,12 @@ void mdss_mdp_get_v_h_subsample_rate(u8 chroma_samp,
	u8 *v_sample, u8 *h_sample);
struct mult_factor *mdss_mdp_get_comp_factor(u32 format,
	bool rt_factor);
int mdss_mdp_data_get(struct mdss_mdp_data *data, struct msmfb_data *planes,
		int num_planes, u32 flags, struct device *dev, bool rotator,
		int dir);
int mdss_mdp_data_map(struct mdss_mdp_data *data, bool rotator, int dir);
void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir);
int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data,
	struct msmfb_data *planes, int num_planes, u32 flags,
	struct device *dev, bool rotator, int dir,
	struct mdp_layer_buffer *buffer);
u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase);

+11 −8
Original line number Diff line number Diff line
@@ -856,15 +856,18 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd,

	image.memory_id = buffer->planes[0].fd;
	image.offset = buffer->planes[0].offset;
	ret = mdss_mdp_data_get(src_data, &image, 1, flags,
			&mfd->pdev->dev, false, DMA_TO_DEVICE);
	if (ret) {
		mdss_mdp_overlay_buf_free(mfd, src_data);
		src_data = ERR_PTR(ret);
	} else {
	ret = mdss_mdp_data_get_and_validate_size(src_data, &image, 1,
			flags, &mfd->pdev->dev, false, DMA_TO_DEVICE,
			buffer);
	if (ret)
		goto end_buf_free;

	src_data->num_planes = 1;
	}
	return src_data;

end_buf_free:
	mdss_mdp_overlay_buf_free(mfd, src_data);
	src_data = ERR_PTR(ret);
end:
	return src_data;
}
+7 −2
Original line number Diff line number Diff line
@@ -2177,6 +2177,7 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	struct mdss_mdp_pipe *pipe;
	struct mdss_mdp_data *src_data;
	struct mdp_layer_buffer buffer;
	int ret;
	u32 flags;

@@ -2212,8 +2213,12 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
		pr_err("unable to allocate source buffer\n");
		ret = -ENOMEM;
	} else {
		ret = mdss_mdp_data_get(src_data, &req->data, 1, flags,
			&mfd->pdev->dev, false, DMA_TO_DEVICE);
		buffer.width = pipe->img_width;
		buffer.height = pipe->img_height;
		buffer.format = pipe->src_fmt->format;
		ret = mdss_mdp_data_get_and_validate_size(src_data, &req->data,
			1, flags, &mfd->pdev->dev, false, DMA_TO_DEVICE,
			&buffer);
		if (IS_ERR_VALUE(ret)) {
			mdss_mdp_overlay_buf_free(mfd, src_data);
			pr_err("src_data pmem error\n");
+15 −4
Original line number Diff line number Diff line
@@ -1004,6 +1004,7 @@ int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
			    struct msmfb_overlay_data *req)
{
	struct mdss_mdp_rotator_session *rot;
	struct mdp_layer_buffer buffer;
	int ret;
	u32 flgs;
	struct mdss_mdp_data src_buf;
@@ -1023,8 +1024,12 @@ int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
	mdss_iommu_ctrl(1);
	mutex_lock(&rot->lock);

	ret = mdss_mdp_data_get(&src_buf, &req->data, 1, flgs,
		&mfd->pdev->dev, true, DMA_TO_DEVICE);
	buffer.width = rot->src_rect.w;
	buffer.height = rot->src_rect.h;
	buffer.format = rot->format;
	ret = mdss_mdp_data_get_and_validate_size(&src_buf,
		&req->data, 1, flgs, &mfd->pdev->dev, true,
		DMA_TO_DEVICE, &buffer);
	if (ret) {
		pr_err("src_data pmem error\n");
		goto dst_buf_fail;
@@ -1040,8 +1045,14 @@ int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
	memcpy(&rot->src_buf, &src_buf, sizeof(struct mdss_mdp_data));

	mdss_mdp_data_free(&rot->dst_buf, true, DMA_FROM_DEVICE);
	ret = mdss_mdp_data_get(&rot->dst_buf, &req->dst_data, 1, flgs,
		&mfd->pdev->dev, true, DMA_FROM_DEVICE);
	buffer.width = rot->dst.w;
	buffer.height = rot->dst.h;
	buffer.format = mdss_mdp_get_rotator_dst_format(rot->format,
		rot->flags & MDP_ROT_90, rot->bwc_mode);

	ret = mdss_mdp_data_get_and_validate_size(&rot->dst_buf,
		&req->dst_data, 1, flgs, &mfd->pdev->dev, true,
		DMA_FROM_DEVICE, &buffer);
	if (ret) {
		pr_err("dst_data pmem error\n");
		mdss_mdp_data_free(&rot->src_buf, true, DMA_TO_DEVICE);
+52 −3
Original line number Diff line number Diff line
@@ -1238,9 +1238,9 @@ err_unmap:
	return ret;
}

int mdss_mdp_data_get(struct mdss_mdp_data *data, struct msmfb_data *planes,
		int num_planes, u32 flags, struct device *dev, bool rotator,
		int dir)
static int mdss_mdp_data_get(struct mdss_mdp_data *data,
		struct msmfb_data *planes, int num_planes, u32 flags,
		struct device *dev, bool rotator, int dir)
{
	int i, rc = 0;

@@ -1300,6 +1300,55 @@ void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir)
	data->num_planes = 0;
}

int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data,
	struct msmfb_data *planes, int num_planes, u32 flags,
	struct device *dev, bool rotator, int dir,
	struct mdp_layer_buffer *buffer)
{
	struct mdss_mdp_format_params *fmt;
	struct mdss_mdp_plane_sizes ps;
	int ret, i;
	unsigned long total_buf_len = 0;

	fmt = mdss_mdp_get_format_params(buffer->format);
	if (!fmt) {
		pr_err("Format %d not supported\n", buffer->format);
		return -EINVAL;
	}

	ret = mdss_mdp_data_get(data, planes, num_planes,
		flags, dev, rotator, dir);
	if (ret)
		return ret;

	mdss_mdp_get_plane_sizes(fmt, buffer->width, buffer->height, &ps, 0, 0);

	for (i = 0; i < num_planes ; i++) {
		unsigned long plane_len = (data->p[i].srcp_dma_buf) ?
				data->p[i].srcp_dma_buf->size : data->p[i].len;

		if (plane_len < planes[i].offset) {
			pr_err("Offset=%d larger than buffer size=%lu\n",
				planes[i].offset, plane_len);
			ret = -EINVAL;
			goto buf_too_small;
		}
		total_buf_len += plane_len - planes[i].offset;
	}

	if (total_buf_len < ps.total_size) {
		pr_err("Buffer size=%lu, expected size=%d\n", total_buf_len,
			ps.total_size);
		ret = -EINVAL;
		goto buf_too_small;
	}
	return 0;

buf_too_small:
	mdss_mdp_data_free(data, rotator, dir);
	return ret;
}

int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
Loading