From 29854ac2bb0f6e5b2095155f2b596f62c4be8f5b Mon Sep 17 00:00:00 2001 From: Jeya R Date: Mon, 27 Jul 2020 14:15:20 +0530 Subject: [PATCH] msm: adsprpc: Put upper limit on IOMMU mapping size Place appropriate validation checks for IOMMU mapping size. Without these checks, a mapping in an invalid kernel space could be created and fail during access. Change-Id: I995c8c2a9ef8d746b8fc2433d6510dfa92596adc Signed-off-by: Jeya R --- drivers/char/adsprpc.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 7458205e9a10..e1b1784860ab 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -460,6 +460,7 @@ struct fastrpc_apps { struct wakeup_source *wake_source; uint32_t duplicate_rsp_err_cnt; struct qos_cores silvercores; + uint32_t max_size_limit; }; struct fastrpc_mmap { @@ -1280,8 +1281,12 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, } trace_fastrpc_dma_map(fl->cid, fd, map->phys, map->size, len, mflags, map->attach->dma_map_attrs); - if (map->size < len) { + + VERIFY(err, map->size >= len && map->size < me->max_size_limit); + if (err) { err = -EFAULT; + pr_err("adsprpc: %s: invalid map size 0x%zx len 0x%zx\n", + __func__, map->size, len); goto bail; } @@ -1384,8 +1389,17 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, int buf_type, struct fastrpc_buf **obuf) { int err = 0, vmid; + struct fastrpc_apps *me = &gfa; struct fastrpc_buf *buf = NULL; + VERIFY(err, size > 0 && size < me->max_size_limit); + if (err) { + err = -EFAULT; + pr_err("adsprpc: %s: invalid allocation size 0x%zx\n", + __func__, size); + goto bail; + } + VERIFY(err, fl->sctx != NULL); if (err) { err = -EBADR; @@ -5925,9 +5939,11 @@ static int fastrpc_cb_probe(struct device *dev) struct fastrpc_channel_ctx *chan; struct fastrpc_session_ctx *sess; struct of_phandle_args iommuspec; + struct fastrpc_apps *me = &gfa; const char *name; int err = 0, cid = -1, i = 0; u32 sharedcb_count = 0, j = 0; + uint32_t dma_addr_pool[2] = {0, 0}; VERIFY(err, NULL != (name = of_get_property(dev->of_node, "label", NULL))); @@ -5983,6 +5999,11 @@ static int fastrpc_cb_probe(struct device *dev) dma_set_max_seg_size(sess->smmu.dev, DMA_BIT_MASK(32)); dma_set_seg_boundary(sess->smmu.dev, (unsigned long)DMA_BIT_MASK(64)); + of_property_read_u32_array(dev->of_node, "qcom,iommu-dma-addr-pool", + dma_addr_pool, 2); + me->max_size_limit = (dma_addr_pool[1] == 0 ? 0x78000000 : + dma_addr_pool[1]); + if (of_get_property(dev->of_node, "shared-cb", NULL) != NULL) { err = of_property_read_u32(dev->of_node, "shared-cb", &sharedcb_count);