aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorEspen Fjellvær Olsen <espen@mrfjo.org>2013-01-08 21:30:59 +0100
committerEspen Fjellvær Olsen <espen@mrfjo.org>2013-01-09 18:46:56 +0100
commit49017aa9e80dbdb44cbfe8f4aa3b5edd9466705c (patch)
tree8a22b8d121d4ce41c2f4a590eb9fbf186af5f368 /drivers/media
parent5528b5d5c43f0c38903db0e672581ec4176ae523 (diff)
downloadkernel_samsung_smdk4412-49017aa9e80dbdb44cbfe8f4aa3b5edd9466705c.zip
kernel_samsung_smdk4412-49017aa9e80dbdb44cbfe8f4aa3b5edd9466705c.tar.gz
kernel_samsung_smdk4412-49017aa9e80dbdb44cbfe8f4aa3b5edd9466705c.tar.bz2
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
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/samsung/fimc/fimc_output.c145
-rw-r--r--drivers/media/video/samsung/fimg2d3x-exynos4/fimg2d_core.c12
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c76
3 files changed, 231 insertions, 2 deletions
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 <linux/cma.h>
+#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;