From 49017aa9e80dbdb44cbfe8f4aa3b5edd9466705c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20Fjellv=C3=A6r=20Olsen?= Date: Tue, 8 Jan 2013 21:30:59 +0100 Subject: Update to the exynos-mem security issue from Samsung I9300 Update7 p2: includes the secmem changes as well as Andreis MFC addition as well Change-Id: I144c2b42586f07b737fba09742315683cbab36ef --- drivers/media/video/samsung/fimc/fimc_output.c | 145 ++++++++++++++++++++- .../video/samsung/fimg2d3x-exynos4/fimg2d_core.c | 12 ++ .../video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c | 76 ++++++++++- 3 files changed, 231 insertions(+), 2 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/video/samsung/fimc/fimc_output.c b/drivers/media/video/samsung/fimc/fimc_output.c index 57611e5..da651c5 100644 --- a/drivers/media/video/samsung/fimc/fimc_output.c +++ b/drivers/media/video/samsung/fimc/fimc_output.c @@ -2726,13 +2726,21 @@ static int fimc_update_in_queue_addr(struct fimc_control *ctrl, int fimc_qbuf_output(void *fh, struct v4l2_buffer *b) { - struct fimc_buf *buf; + struct fimc_buf *buf = (struct fimc_buf *)b->m.userptr; struct fimc_ctx *ctx; struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl; int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id; int idx, ctx_num; int ret = -1; + u32 width; + u32 height; + u32 format; + u32 y_size = 0; + u32 cb_size = 0; + u32 cr_size = 0; + u32 size; + ctx = &ctrl->out->ctx[ctx_id]; fimc_info2("ctx(%d) queued idx = %d\n", ctx->ctx_num, b->index); if (ctx->status == FIMC_STREAMOFF) { @@ -2758,6 +2766,69 @@ int fimc_qbuf_output(void *fh, struct v4l2_buffer *b) return -EINVAL; } + /* Check input buffer for CMA region */ + width = ctx->pix.width; + height = ctx->pix.height; + format = ctx->pix.pixelformat; + y_size = width * height; + + switch (format) { + case V4L2_PIX_FMT_RGB32: + y_size = y_size << 2; + size = PAGE_ALIGN(y_size); + break; + case V4L2_PIX_FMT_RGB565: /* fall through */ + case V4L2_PIX_FMT_UYVY: /* fall through */ + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_VYUY: + y_size = y_size << 1; + size = PAGE_ALIGN(y_size); + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_NV12M: + cb_size = y_size >> 2; + cr_size = y_size >> 2; + size = PAGE_ALIGN(y_size + cb_size + cr_size); + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + cb_size = y_size >> 1; + size = PAGE_ALIGN(y_size + cb_size); + break; + case V4L2_PIX_FMT_NV12T: + fimc_get_nv12t_size(width, height, &y_size, &cb_size); + size = PAGE_ALIGN(y_size + cb_size); + break; + default: + fimc_err("%s: Invalid pixelformt : %d\n", __func__, format); + return -EINVAL; + } + + if (buf->base[FIMC_ADDR_Y] != 0 && y_size != 0 && + !cma_is_registered_region(buf->base[FIMC_ADDR_Y], y_size)) { + fimc_err("%s: Y address is not CMA region 0x%x, %d \n", + __func__, buf->base[FIMC_ADDR_Y], y_size); + return -EINVAL; + } + if (buf->base[FIMC_ADDR_CB] != 0 && cb_size != 0 && + !cma_is_registered_region(buf->base[FIMC_ADDR_CB], cb_size)) { + fimc_err("%s: CB address is not CMA region 0x%x, %d \n", + __func__, buf->base[FIMC_ADDR_CB], cb_size); + return -EINVAL; + } + if (buf->base[FIMC_ADDR_CR] != 0 && cr_size != 0 && + !cma_is_registered_region(buf->base[FIMC_ADDR_CR], cr_size)) { + fimc_err("%s: CR address is not CMA region 0x%x, %d \n", + __func__, buf->base[FIMC_ADDR_CR], cr_size); + return -EINVAL; + } + /* End check CMA region */ + if ((ctrl->status == FIMC_READY_ON) || (ctrl->status == FIMC_STREAMON) || (ctrl->status == FIMC_STREAMON_IDLE)) { @@ -2850,6 +2921,78 @@ int fimc_qbuf_output(void *fh, struct v4l2_buffer *b) } } + /* Check output buffer for CMA region */ + width = ctx->fbuf.fmt.width; + height = ctx->fbuf.fmt.height; + format = ctx->fbuf.fmt.pixelformat; + y_size = width * height; + cb_size = 0; + cr_size = 0; + + switch (format) { + case V4L2_PIX_FMT_RGB32: + y_size = y_size << 2; + size = PAGE_ALIGN(y_size); + break; + case V4L2_PIX_FMT_RGB565: /* fall through */ + case V4L2_PIX_FMT_UYVY: /* fall through */ + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_VYUY: + y_size = y_size << 1; + size = PAGE_ALIGN(y_size); + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_NV12M: + cb_size = y_size >> 2; + cr_size = y_size >> 2; + size = PAGE_ALIGN(y_size + cb_size + cr_size); + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + cb_size = y_size >> 1; + size = PAGE_ALIGN(y_size + cb_size); + break; + case V4L2_PIX_FMT_NV12T: + fimc_get_nv12t_size(width, height, &y_size, &cb_size); + size = PAGE_ALIGN(y_size + cb_size); + break; + default: + fimc_err("%s: Invalid pixelformt : %d\n", __func__, format); + ret = -EINVAL; + goto err_routine; + } + + if (ctx->dst[idx].base[FIMC_ADDR_Y] != 0 && y_size != 0 && + !cma_is_registered_region((dma_addr_t)ctx->dst[idx].base[FIMC_ADDR_Y], + y_size)) { + fimc_err("%s: Y address is not CMA region 0x%x, %d \n", + __func__, ctx->dst[idx].base[FIMC_ADDR_Y], y_size); + ret = -EINVAL; + goto err_routine; + } + if (ctx->dst[idx].base[FIMC_ADDR_CB] != 0 && cb_size != 0 && + !cma_is_registered_region((dma_addr_t)ctx->dst[idx].base[FIMC_ADDR_CB], + cb_size)) { + fimc_err("%s: CB address is not CMA region 0x%x, %d \n", + __func__, ctx->dst[idx].base[FIMC_ADDR_CB], cb_size); + ret = -EINVAL; + goto err_routine; + } + if (ctx->dst[idx].base[FIMC_ADDR_CR] != 0 && cr_size != 0 && + !cma_is_registered_region((dma_addr_t)ctx->dst[idx].base[FIMC_ADDR_CR], + cr_size)) { + fimc_err("%s: CR address is not CMA region 0x%x, %d \n", + __func__, ctx->dst[idx].base[FIMC_ADDR_CR], cr_size); + ret = -EINVAL; + goto err_routine; + } + /* End check CMA region */ + switch (ctx->overlay.mode) { case FIMC_OVLY_FIFO: ret = fimc_qbuf_output_fifo(ctrl, ctx, idx); diff --git a/drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_core.c b/drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_core.c index 40508d5..6fa0e31 100644 --- a/drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_core.c +++ b/drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_core.c @@ -178,6 +178,18 @@ int g2d_do_blit(struct g2d_global *g2d_dev, g2d_params *params) } if (params->flag.memory_type == G2D_MEMORY_KERNEL) { +#if defined(CONFIG_S5P_MEM_CMA) + if (!cma_is_registered_region((unsigned int)params->src_rect.addr, + GET_RECT_SIZE(params->src_rect))) { + printk(KERN_ERR "[%s] SRC Surface is not included in CMA region\n", __func__); + return -1; + } + if (!cma_is_registered_region((unsigned int)params->dst_rect.addr, + GET_RECT_SIZE(params->dst_rect))) { + printk(KERN_ERR "[%s] DST Surface is not included in CMA region\n", __func__); + return -1; + } +#endif params->src_rect.addr = (unsigned char *)phys_to_virt((unsigned long)params->src_rect.addr); params->dst_rect.addr = (unsigned char *)phys_to_virt((unsigned long)params->dst_rect.addr); pgd = (unsigned long)init_mm.pgd; diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c index 0c6c590..52160d6 100644 --- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c +++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c @@ -18,10 +18,54 @@ #include "fimg2d_ctx.h" #include "fimg2d_cache.h" #include "fimg2d_helper.h" +#if defined(CONFIG_CMA) +#include +#endif + +static inline int is_yuvfmt(enum color_format fmt) +{ + switch (fmt) { + case CF_YCBCR_420: + case CF_YCBCR_422: + case CF_YCBCR_444: + return 1; + default: + return 0; + } +} + +/** + * @plane: 0 for 1st plane, 1 for 2nd plane + */ +static int yuv_stride(int width, enum color_format cf, enum pixel_order order, + int plane) +{ + int bpp; + + switch (cf) { + case CF_YCBCR_420: + bpp = (!plane) ? 8 : 4; + break; + case CF_YCBCR_422: + if (order == P2_CRCB || order == P2_CBCR) + bpp = 8; + else + bpp = (!plane) ? 16 : 0; + break; + case CF_YCBCR_444: + bpp = (!plane) ? 8 : 16; + break; + default: + bpp = 0; + break; + } + + return width * bpp >> 3; +} static int fimg2d_check_params(struct fimg2d_bltcmd *cmd) { - int w, h, i; + int w, h, i, bw; struct fimg2d_param *p = &cmd->param; struct fimg2d_image *img; struct fimg2d_scale *scl; @@ -53,6 +97,36 @@ static int fimg2d_check_params(struct fimg2d_bltcmd *cmd) r->x1 >= w || r->y1 >= h || r->x1 >= r->x2 || r->y1 >= r->y2) return -1; +#if defined(CONFIG_CMA) +#if 0 + if (img->addr.type == ADDR_PHYS) { + if (!cma_is_registered_region(img->addr.start, (h * img->stride))) { + printk(KERN_ERR "[%s] Surface[%d] is not included in CMA region\n", __func__, i); + return -1; + } + } +#else + if (img->addr.type == ADDR_PHYS) { + if (is_yuvfmt(img->fmt)) + bw = yuv_stride(img->width, img->fmt, img->order, 0); + else + bw = img->stride; + + if (!cma_is_registered_region(img->addr.start, (h * bw))) { + printk(KERN_ERR "[%s] Surface[%d] is not included in CMA region\n", __func__, i); + return -1; + } + + if (img->order == P2_CRCB || img->order == P2_CBCR) { + bw = yuv_stride(img->width, img->fmt, img->order, 1); + if (!cma_is_registered_region(img->plane2.start, (h * bw))) { + printk(KERN_ERR "[%s] plane2[%d] is not included in CMA region\n", __func__, i); + return -1; + } + } + } +#endif +#endif } clp = &p->clipping; -- cgit v1.1