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

Commit 4071a525 authored by stephen.wong's avatar stephen.wong
Browse files

[ALPS05433311] jpegenc: jpeg security issue



 get mva via buffer fd and check valid value of dst offset

MTK-Commit-Id: 7549c2fa1a97ac276652ef2310c0a35de234258a

Change-Id: I64b0ff1058c72020cdae5f23049667ddd274be33
CR-Id: ALPS05433311
Feature: JPEG (Joint Photographic Expert Group) Codec
Signed-off-by: default avatarstephen.wong <stephen.wong@mediatek.com>
parent 8a1ed64a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ endif
ccflags-y += -I$(srctree)/drivers/misc/mediatek/smi/
ccflags-y += -I$(srctree)/drivers/misc/mediatek/smi/$(MTK_PLATFORM)
ccflags-y += -I$(srctree)/drivers/misc/mediatek/mmdvfs

ccflags-y += -I$(srctree)/drivers/staging/android/mtk_ion
ccflags-y += -I$(srctree)/drivers/staging/android/mtk_ion/mtk
#obj-$(CONFIG_MTK_JPEG) += jpeg_driver.o
obj-y += jpeg_driver.o

+29 −8
Original line number Diff line number Diff line
@@ -125,6 +125,8 @@
#include "mmdvfs_pmqos.h"
#endif

#include <ion_drv.h>

/* -------------------------------------------------------------------------- */
/*  */
/* -------------------------------------------------------------------------- */
@@ -200,6 +202,9 @@ static unsigned int cshot_spec_dts;
/* Support QoS */
struct mtk_pm_qos_request jpgenc_qos_request;

static struct ion_client *g_jpeg_ion_client;


/* ========================================== */
/* CMDQ */

@@ -1048,18 +1053,22 @@ static int jpeg_enc_ioctl(unsigned int cmd, unsigned long arg,
		}

		/* 2. set src buffer info */
		JPEG_MSG("[JPEGDRV]SRC_BUF: addr %x, %x, stride %x, %x!!\n",
		JPEG_MSG("[JPEGDRV]SRC_BUF: addr %x, %x, stride %x, %x fd %d %d!!\n",
			 cfgEnc.srcBufferAddr,
			 cfgEnc.srcChromaAddr,
			 cfgEnc.imgStride,
			 cfgEnc.memStride);
			 cfgEnc.memStride,
			 cfgEnc.srcFd,
			 cfgEnc.srcFd2);

		ret =
		    jpeg_drv_enc_set_src_buf(cfgEnc.encFormat,
		    jpeg_drv_enc_set_src_buf(g_jpeg_ion_client,
						 cfgEnc.encFormat,
					     cfgEnc.imgStride,
					     cfgEnc.memStride,
					     cfgEnc.srcBufferAddr,
					     cfgEnc.srcChromaAddr);
					     cfgEnc.memHeight,
					     cfgEnc.srcFd,
					     cfgEnc.srcFd2);
		if (ret == 0) {
			JPEG_MSG("[JPGDRV]Enc set srouce buffer failed\n");
			return -EFAULT;
@@ -1072,14 +1081,17 @@ static int jpeg_enc_ioctl(unsigned int cmd, unsigned long arg,
		/* } */

		/* 3. set dst buffer info */
		JPEG_MSG("[JPGDRV]DST_BUF: addr:%x, size:%x, ofs:%x, mask:%x\n",
		JPEG_MSG("[JPGDRV]DST_BUF: addr:%x, size:%x, ofs:%x, mask:%x Fd 0x%x\n",
			 cfgEnc.dstBufferAddr,
			 cfgEnc.dstBufferSize,
			 cfgEnc.dstBufAddrOffset,
			 cfgEnc.dstBufAddrOffsetMask);
			 cfgEnc.dstBufAddrOffsetMask,
			 cfgEnc.dstFd);


		ret =
		    jpeg_drv_enc_set_dst_buff(cfgEnc.dstBufferAddr,
		    jpeg_drv_enc_set_dst_buff(g_jpeg_ion_client,
						  cfgEnc.dstFd,
					      cfgEnc.dstBufferSize,
					      cfgEnc.dstBufAddrOffset,
					      cfgEnc.dstBufAddrOffsetMask);
@@ -1898,6 +1910,11 @@ static int __init jpeg_init(void)
	Driver_Open_Count = 0;
	jpeg_drv_enc_prepare_bw_request();

	if (!g_jpeg_ion_client && g_ion_device) {
		JPEG_MSG("create ion client\n");
		g_jpeg_ion_client = ion_client_create(g_ion_device, "jpegenc");
	}

	return 0;
}

@@ -1932,6 +1949,10 @@ static void __exit jpeg_exit(void)
	JPEG_MSG("%s jdec remove\n", __func__);
#endif
	jpegenc_drv_enc_remove_bw_request();

	if (g_jpeg_ion_client)
		ion_client_destroy(g_jpeg_ion_client);
	g_jpeg_ion_client = NULL;
	JPEG_MSG("%s -\n", __func__);
}
module_init(jpeg_init);
+4 −1
Original line number Diff line number Diff line
@@ -569,7 +569,10 @@ struct JPEG_ENC_DRV_IN {
	unsigned int totalEncDU;
	unsigned int dstBufAddrOffset;
	unsigned int dstBufAddrOffsetMask;

	int srcFd;
	int srcFd2;
	int dstFd;
	unsigned int memHeight;
};


+9 −5
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
/* #include <mach/typedefs.h> */

#include "jpeg_drv.h"
#include <ion_drv.h>



@@ -123,8 +124,8 @@ void jpeg_drv_enc_start(void);
unsigned int jpeg_drv_enc_set_quality(unsigned int quality);
unsigned int jpeg_drv_enc_set_img_size(unsigned int width, unsigned int height);
unsigned int jpeg_drv_enc_set_blk_num(unsigned int blk_num);
unsigned int jpeg_drv_enc_set_luma_addr(unsigned int src_luma_addr);
unsigned int jpeg_drv_enc_set_chroma_addr(unsigned int src_luma_addr);
unsigned int jpeg_drv_enc_set_luma_addr(dma_addr_t src_luma_addr);
unsigned int jpeg_drv_enc_set_chroma_addr(dma_addr_t src_luma_addr);
unsigned int jpeg_drv_enc_set_memory_stride(unsigned int mem_stride);
unsigned int jpeg_drv_enc_set_image_stride(unsigned int img_stride);
void jpeg_drv_enc_set_restart_interval(unsigned int restart_interval);
@@ -133,7 +134,8 @@ unsigned int jpeg_drv_enc_set_offset_addr(unsigned int offset);
void jpeg_drv_enc_set_EncodeMode(unsigned int exif_en);
void jpeg_drv_enc_set_burst_type(unsigned int burst_type);
unsigned int jpeg_drv_enc_set_dst_buff(
	unsigned int dst_addr,
	struct ion_client *pIonClient,
	int dstFd,
	 unsigned int stall_size,
	 unsigned int init_offset,
	 unsigned int offset_mask);
@@ -169,11 +171,13 @@ unsigned int jpeg_drv_enc_set_src_image(
	 unsigned int totalEncDU);

unsigned int jpeg_drv_enc_set_src_buf(
		struct ion_client *pIonClient,
		unsigned int yuv_format,
		 unsigned int img_stride,
		 unsigned int mem_stride,
		 unsigned int srcAddr,
		 unsigned int srcAddr_C);
		 unsigned int mem_height,
		 int srcFd,
		 int srcFd2);
unsigned int jpeg_drv_enc_set_encFormat(unsigned int encFormat);

#endif
+162 −7
Original line number Diff line number Diff line
@@ -31,7 +31,84 @@

unsigned int _jpeg_enc_int_status;

static struct ion_handle *jpeg_ion_import_handle(struct ion_client *client, int fd)
{
	struct ion_handle *handle = NULL;
	struct ion_mm_data mm_data;

	/* If no need Ion support, do nothing! */
	if (fd < 0) {
		JPEG_MSG("NO NEED ion support, fd %d\n", fd);
		return handle;
	}

	if (!client) {
		JPEG_MSG("invalid ion client!\n");
		return handle;
	}

	handle = ion_import_dma_buf_fd(client, fd);
	if (IS_ERR(handle)) {
		JPEG_MSG("import ion handle failed!\n");
		return NULL;
	}
	mm_data.mm_cmd = ION_MM_CONFIG_BUFFER;
	mm_data.config_buffer_param.kernel_handle = handle;
	mm_data.config_buffer_param.module_id = 0;
	mm_data.config_buffer_param.security = 0;
	mm_data.config_buffer_param.coherent = 0;

	if (ion_kernel_ioctl(client, ION_CMD_MULTIMEDIA,
		(unsigned long)&mm_data))
		JPEG_MSG("configure ion buffer failed!\n");

	JPEG_MSG("import ion handle fd=%d,hnd=0x%p\n", fd, handle);

	return handle;
}

static int jpeg_ion_get_mva(struct ion_client *client, struct ion_handle *handle,
		     dma_addr_t *mva, unsigned int *size, int port)
{
	struct ion_mm_data mm_data;
	size_t mva_size;
	ion_phys_addr_t phy_addr = 0;

	memset((void *)&mm_data, 0, sizeof(struct ion_mm_data));
	mm_data.config_buffer_param.module_id = port;
	mm_data.config_buffer_param.kernel_handle = handle;
	mm_data.mm_cmd = ION_MM_CONFIG_BUFFER;
	if (ion_kernel_ioctl(client, ION_CMD_MULTIMEDIA,
		(unsigned long)&mm_data) < 0) {

		JPEG_MSG("config buffer failed.%p -%p\n",
			client, handle);
		ion_free(client, handle);
		return -1;
	}

	ion_phys(client, handle, &phy_addr, &mva_size);
	*mva = phy_addr;
	*size = mva_size;
	JPEG_MSG("alloc mmu addr hnd=0x%p,mva=0x%p size %d\n",
		   handle, *mva, *size);

	return 0;
}

static void jpeg_ion_free_handle(struct ion_client *client, struct ion_handle *handle)
{
	if (!client) {
		JPEG_MSG("invalid ion client!\n");
		return;
	}
	if (!handle)
		return;

	ion_free(client, handle);

	JPEG_MSG("free ion handle 0x%p\n", handle);
}
int jpeg_isr_enc_lisr(void)
{
	unsigned int tmp, tmp1;
@@ -78,11 +155,16 @@ unsigned int jpeg_drv_enc_set_src_image(



unsigned int jpeg_drv_enc_set_src_buf(
unsigned int jpeg_drv_enc_set_src_buf(struct ion_client *pIonClient,
	unsigned int yuv_format, unsigned int img_stride,
	 unsigned int mem_stride, unsigned int srcAddr, unsigned int srcAddr_C)
	 unsigned int mem_stride, unsigned int mem_height,
	 int srcFd, int srcFd2)
{
	unsigned int ret = 1;
	dma_addr_t srcAddr = 0;
	dma_addr_t srcAddr_C = 0;
	unsigned int bufSize = 0;
	struct ion_handle *handle = NULL;

	if (yuv_format == 0x00 || yuv_format == 0x01) {
		if ((mem_stride & 0x1f) || (img_stride & 0x1f)) {
@@ -93,6 +175,55 @@ unsigned int jpeg_drv_enc_set_src_buf(
		}
	}

	if (yuv_format == YUYV || yuv_format == YVYU) {
		handle = jpeg_ion_import_handle(pIonClient, srcFd);
		if (handle == NULL) {
			JPEG_MSG("import handle fail line %d\n", __LINE__);
			return 0;
		}
		if (jpeg_ion_get_mva(pIonClient, handle, &srcAddr, &bufSize, 0) != 0)
			return 0;

		jpeg_ion_free_handle(pIonClient, handle);
		srcAddr_C = 0;

		JPEG_MSG("srcAddr 0x%p srcAddr_C 0x%p line %d\n", srcAddr, srcAddr_C, __LINE__);
	} else if (srcFd == srcFd2) {
		handle = jpeg_ion_import_handle(pIonClient, srcFd);
		if (handle == NULL) {
			JPEG_MSG("import handle fail line %d\n", __LINE__);
			return 0;
		}
		if (jpeg_ion_get_mva(pIonClient, handle, &srcAddr, &bufSize, 0) != 0)
			return 0;

		jpeg_ion_free_handle(pIonClient, handle);
		srcAddr_C = srcAddr + mem_stride*mem_height;
		JPEG_MSG("srcAddr 0x%p srcAddr_C 0x%p line %d\n", srcAddr, srcAddr_C, __LINE__);
	} else {
		handle = jpeg_ion_import_handle(pIonClient, srcFd);
		if (handle == NULL) {
			JPEG_MSG("import handle fail line %d\n", __LINE__);
			return 0;
		}
		if (jpeg_ion_get_mva(pIonClient, handle, &srcAddr, &bufSize, 0) != 0)
			return 0;

		jpeg_ion_free_handle(pIonClient, handle);

		handle = jpeg_ion_import_handle(pIonClient, srcFd2);
		if (handle == NULL) {
			JPEG_MSG("import handle fail line %d\n", __LINE__);
			return 0;
		}
		if (jpeg_ion_get_mva(pIonClient, handle, &srcAddr_C, &bufSize, 0) != 0)
			return 0;

		jpeg_ion_free_handle(pIonClient, handle);

		JPEG_MSG("srcAddr 0x%p srcAddr_C 0x%p line %d\n", srcAddr, srcAddr_C, __LINE__);
	}

	ret &= jpeg_drv_enc_set_image_stride(img_stride);

	ret &= jpeg_drv_enc_set_memory_stride(mem_stride);
@@ -291,7 +422,7 @@ unsigned int jpeg_drv_enc_set_blk_num(unsigned int blk_num) /* NO_USE */
}


unsigned int jpeg_drv_enc_set_luma_addr(unsigned int src_luma_addr)
unsigned int jpeg_drv_enc_set_luma_addr(dma_addr_t src_luma_addr)
{
	if (src_luma_addr & 0x0F)
		JPEG_MSG("JPGENC: set LUMA addr not align (%x)\n",
@@ -303,7 +434,7 @@ unsigned int jpeg_drv_enc_set_luma_addr(unsigned int src_luma_addr)
}


unsigned int jpeg_drv_enc_set_chroma_addr(unsigned int src_chroma_addr)
unsigned int jpeg_drv_enc_set_chroma_addr(dma_addr_t src_chroma_addr)
{
	if (src_chroma_addr & 0x0F)
		JPEG_MSG("JPGENC: set CHROMA addr not align (%x)\n",
@@ -372,10 +503,14 @@ unsigned int jpeg_drv_enc_set_offset_addr(unsigned int offset)
	return 1;
}

unsigned int jpeg_drv_enc_set_dst_buff(
		unsigned int dst_addr, unsigned int stall_size,
unsigned int jpeg_drv_enc_set_dst_buff(struct ion_client *pIonClient,
		 int dstFd, unsigned int stall_size,
		 unsigned int init_offset, unsigned int offset_mask)
{
	struct ion_handle *handle = NULL;
	dma_addr_t dst_addr = 0;
	unsigned int bufSize = 0;

	if (stall_size < 624) {
		JPEG_MSG("JPGENC:stall size less than 624 to write %d\n",
		 stall_size);
@@ -387,7 +522,27 @@ unsigned int jpeg_drv_enc_set_dst_buff(
		/* return 0; */
	}

	IMG_REG_WRITE((init_offset & (~0xF)), REG_ADDR_JPEG_ENC_OFFSET_ADDR);
	handle = jpeg_ion_import_handle(pIonClient, dstFd);
	if (handle == NULL) {
		JPEG_MSG("import handle fail line %d\n", __LINE__);
		return 0;
	}
	if (jpeg_ion_get_mva(pIonClient, handle, &dst_addr, &bufSize, 0) != 0)
		return 0;

	jpeg_ion_free_handle(pIonClient, handle);

	if (init_offset >= bufSize) {
		JPEG_MSG("invalid offset %d bufsize %d line %d\n", init_offset, bufSize, __LINE__);
		return 0;
	}

	dst_addr += init_offset;
	JPEG_MSG("dst_addr 0x%p  offset 0x%x line %d\n", dst_addr, init_offset, __LINE__);



	IMG_REG_WRITE((0 & (~0xF)), REG_ADDR_JPEG_ENC_OFFSET_ADDR);

	IMG_REG_WRITE((offset_mask & 0xF), REG_ADDR_JPEG_ENC_BYTE_OFFSET_MASK);