* [PATCH v2 1/4] misc: fastrpc: Save actual DMA size in fastrpc_map structure
2025-08-06 11:51 [PATCH v2 0/4] Add missing fixes to FastRPC driver Ling Xu
@ 2025-08-06 11:51 ` Ling Xu
2025-08-06 11:51 ` [PATCH v2 2/4] misc: fastrpc: Fix fastrpc_map_lookup operation Ling Xu
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Ling Xu @ 2025-08-06 11:51 UTC (permalink / raw)
To: srini, amahesh, arnd, gregkh, sumit.semwal, christian.koenig,
thierry.escande, quic_vgattupa
Cc: quic_kuiw, ekansh.gupta, dri-devel, linux-arm-msm, linux-media,
linaro-mm-sig, linux-kernel, Ling Xu, stable, Dmitry Baryshkov
For user passed fd buffer, map is created using DMA calls. The
map related information is stored in fastrpc_map structure. The
actual DMA size is not stored in the structure. Store the actual
size of buffer and check it against the user passed size.
Fixes: c68cfb718c8f ("misc: fastrpc: Add support for context Invoke method")
Cc: stable@kernel.org
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Co-developed-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Signed-off-by: Ling Xu <quic_lxu5@quicinc.com>
---
drivers/misc/fastrpc.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 53e88a1bc430..52571916acd4 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -323,11 +323,11 @@ static void fastrpc_free_map(struct kref *ref)
perm.vmid = QCOM_SCM_VMID_HLOS;
perm.perm = QCOM_SCM_PERM_RWX;
- err = qcom_scm_assign_mem(map->phys, map->size,
+ err = qcom_scm_assign_mem(map->phys, map->len,
&src_perms, &perm, 1);
if (err) {
dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n",
- map->phys, map->size, err);
+ map->phys, map->len, err);
return;
}
}
@@ -758,7 +758,8 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
struct fastrpc_session_ctx *sess = fl->sctx;
struct fastrpc_map *map = NULL;
struct sg_table *table;
- int err = 0;
+ struct scatterlist *sgl = NULL;
+ int err = 0, sgl_index = 0;
if (!fastrpc_map_lookup(fl, fd, ppmap, true))
return 0;
@@ -798,7 +799,15 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
map->phys = sg_dma_address(map->table->sgl);
map->phys += ((u64)fl->sctx->sid << 32);
}
- map->size = len;
+ for_each_sg(map->table->sgl, sgl, map->table->nents,
+ sgl_index)
+ map->size += sg_dma_len(sgl);
+ if (len > map->size) {
+ dev_dbg(sess->dev, "Bad size passed len 0x%llx map size 0x%llx\n",
+ len, map->size);
+ err = -EINVAL;
+ goto map_err;
+ }
map->va = sg_virt(map->table->sgl);
map->len = len;
@@ -815,10 +824,10 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
dst_perms[1].vmid = fl->cctx->vmperms[0].vmid;
dst_perms[1].perm = QCOM_SCM_PERM_RWX;
map->attr = attr;
- err = qcom_scm_assign_mem(map->phys, (u64)map->size, &src_perms, dst_perms, 2);
+ err = qcom_scm_assign_mem(map->phys, (u64)map->len, &src_perms, dst_perms, 2);
if (err) {
dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n",
- map->phys, map->size, err);
+ map->phys, map->len, err);
goto map_err;
}
}
@@ -2046,7 +2055,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
args[0].length = sizeof(req_msg);
pages.addr = map->phys;
- pages.size = map->size;
+ pages.size = map->len;
args[1].ptr = (u64) (uintptr_t) &pages;
args[1].length = sizeof(pages);
@@ -2061,7 +2070,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc, &args[0]);
if (err) {
dev_err(dev, "mem mmap error, fd %d, vaddr %llx, size %lld\n",
- req.fd, req.vaddrin, map->size);
+ req.fd, req.vaddrin, map->len);
goto err_invoke;
}
@@ -2074,7 +2083,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
if (copy_to_user((void __user *)argp, &req, sizeof(req))) {
/* unmap the memory and release the buffer */
req_unmap.vaddr = (uintptr_t) rsp_msg.vaddr;
- req_unmap.length = map->size;
+ req_unmap.length = map->len;
fastrpc_req_mem_unmap_impl(fl, &req_unmap);
return -EFAULT;
}
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 2/4] misc: fastrpc: Fix fastrpc_map_lookup operation
2025-08-06 11:51 [PATCH v2 0/4] Add missing fixes to FastRPC driver Ling Xu
2025-08-06 11:51 ` [PATCH v2 1/4] misc: fastrpc: Save actual DMA size in fastrpc_map structure Ling Xu
@ 2025-08-06 11:51 ` Ling Xu
2025-08-06 11:51 ` [PATCH v2 3/4] misc: fastrpc: fix possible map leak in fastrpc_put_args Ling Xu
2025-08-06 11:51 ` [PATCH v2 4/4] misc: fastrpc: Skip reference for DMA handles Ling Xu
3 siblings, 0 replies; 6+ messages in thread
From: Ling Xu @ 2025-08-06 11:51 UTC (permalink / raw)
To: srini, amahesh, arnd, gregkh, sumit.semwal, christian.koenig,
thierry.escande, quic_vgattupa
Cc: quic_kuiw, ekansh.gupta, dri-devel, linux-arm-msm, linux-media,
linaro-mm-sig, linux-kernel, Ling Xu, stable
Fastrpc driver creates maps for user allocated fd buffers. Before
creating a new map, the map list is checked for any already existing
maps using map fd. Checking with just map fd is not sufficient as the
user can pass offsetted buffer with less size when the map is created
and then a larger size the next time which could result in memory
issues. Check for dma_buf object also when looking up for the map.
Fixes: c68cfb718c8f ("misc: fastrpc: Add support for context Invoke method")
Cc: stable@kernel.org
Co-developed-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Signed-off-by: Ling Xu <quic_lxu5@quicinc.com>
---
drivers/misc/fastrpc.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 52571916acd4..1815b1e0c607 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -367,11 +367,16 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
{
struct fastrpc_session_ctx *sess = fl->sctx;
struct fastrpc_map *map = NULL;
+ struct dma_buf *buf;
int ret = -ENOENT;
+ buf = dma_buf_get(fd);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
spin_lock(&fl->lock);
list_for_each_entry(map, &fl->maps, node) {
- if (map->fd != fd)
+ if (map->fd != fd || map->buf != buf)
continue;
if (take_ref) {
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 3/4] misc: fastrpc: fix possible map leak in fastrpc_put_args
2025-08-06 11:51 [PATCH v2 0/4] Add missing fixes to FastRPC driver Ling Xu
2025-08-06 11:51 ` [PATCH v2 1/4] misc: fastrpc: Save actual DMA size in fastrpc_map structure Ling Xu
2025-08-06 11:51 ` [PATCH v2 2/4] misc: fastrpc: Fix fastrpc_map_lookup operation Ling Xu
@ 2025-08-06 11:51 ` Ling Xu
2025-08-06 11:51 ` [PATCH v2 4/4] misc: fastrpc: Skip reference for DMA handles Ling Xu
3 siblings, 0 replies; 6+ messages in thread
From: Ling Xu @ 2025-08-06 11:51 UTC (permalink / raw)
To: srini, amahesh, arnd, gregkh, sumit.semwal, christian.koenig,
thierry.escande, quic_vgattupa
Cc: quic_kuiw, ekansh.gupta, dri-devel, linux-arm-msm, linux-media,
linaro-mm-sig, linux-kernel, Ling Xu, stable
copy_to_user() failure would cause an early return without cleaning up
the fdlist, which has been updated by the DSP. This could lead to map
leak. Fix this by redirecting to a cleanup path on failure, ensuring
that all mapped buffers are properly released before returning.
Fixes: c68cfb718c8f ("misc: fastrpc: Add support for context Invoke method")
Cc: stable@kernel.org
Co-developed-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Signed-off-by: Ling Xu <quic_lxu5@quicinc.com>
---
drivers/misc/fastrpc.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 1815b1e0c607..d950a179bff8 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -1085,6 +1085,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
struct fastrpc_phy_page *pages;
u64 *fdlist;
int i, inbufs, outbufs, handles;
+ int ret = 0;
inbufs = REMOTE_SCALARS_INBUFS(ctx->sc);
outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc);
@@ -1100,14 +1101,17 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
u64 len = rpra[i].buf.len;
if (!kernel) {
- if (copy_to_user((void __user *)dst, src, len))
- return -EFAULT;
+ if (copy_to_user((void __user *)dst, src, len)) {
+ ret = -EFAULT;
+ goto cleanup_fdlist;
+ }
} else {
memcpy(dst, src, len);
}
}
}
+cleanup_fdlist:
/* Clean up fdlist which is updated by DSP */
for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {
if (!fdlist[i])
@@ -1116,7 +1120,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
fastrpc_map_put(mmap);
}
- return 0;
+ return ret;
}
static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx,
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 4/4] misc: fastrpc: Skip reference for DMA handles
2025-08-06 11:51 [PATCH v2 0/4] Add missing fixes to FastRPC driver Ling Xu
` (2 preceding siblings ...)
2025-08-06 11:51 ` [PATCH v2 3/4] misc: fastrpc: fix possible map leak in fastrpc_put_args Ling Xu
@ 2025-08-06 11:51 ` Ling Xu
2025-08-06 23:19 ` kernel test robot
3 siblings, 1 reply; 6+ messages in thread
From: Ling Xu @ 2025-08-06 11:51 UTC (permalink / raw)
To: srini, amahesh, arnd, gregkh, sumit.semwal, christian.koenig,
thierry.escande, quic_vgattupa
Cc: quic_kuiw, ekansh.gupta, dri-devel, linux-arm-msm, linux-media,
linaro-mm-sig, linux-kernel, Ling Xu, stable
If multiple dma handles are passed with same fd over a remote call
the kernel driver takes a reference and expects that put for the
map will be called as many times to free the map. But DSP only
updates the fd one time in the fd list when the DSP refcount
goes to zero and hence kernel make put call only once for the
fd. This can cause SMMU fault issue as the same fd can be used
in future for some other call.
Fixes: 35a82b87135d ("misc: fastrpc: Add dma handle implementation")
Cc: stable@kernel.org
Co-developed-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
Signed-off-by: Ling Xu <quic_lxu5@quicinc.com>
---
drivers/misc/fastrpc.c | 44 ++++++++++++++++++++++++++----------------
1 file changed, 27 insertions(+), 17 deletions(-)
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index d950a179bff8..3b7ad4a043eb 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -363,7 +363,7 @@ static int fastrpc_map_get(struct fastrpc_map *map)
static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
- struct fastrpc_map **ppmap, bool take_ref)
+ struct fastrpc_map **ppmap)
{
struct fastrpc_session_ctx *sess = fl->sctx;
struct fastrpc_map *map = NULL;
@@ -379,15 +379,6 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
if (map->fd != fd || map->buf != buf)
continue;
- if (take_ref) {
- ret = fastrpc_map_get(map);
- if (ret) {
- dev_dbg(sess->dev, "%s: Failed to get map fd=%d ret=%d\n",
- __func__, fd, ret);
- break;
- }
- }
-
*ppmap = map;
ret = 0;
break;
@@ -757,7 +748,7 @@ static const struct dma_buf_ops fastrpc_dma_buf_ops = {
.release = fastrpc_release,
};
-static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
+static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
u64 len, u32 attr, struct fastrpc_map **ppmap)
{
struct fastrpc_session_ctx *sess = fl->sctx;
@@ -766,9 +757,6 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
struct scatterlist *sgl = NULL;
int err = 0, sgl_index = 0;
- if (!fastrpc_map_lookup(fl, fd, ppmap, true))
- return 0;
-
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map)
return -ENOMEM;
@@ -853,6 +841,24 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
return err;
}
+static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
+ u64 len, u32 attr, struct fastrpc_map **ppmap)
+{
+ struct fastrpc_session_ctx *sess = fl->sctx;
+ int err = 0;
+
+ if (!fastrpc_map_lookup(fl, fd, ppmap)) {
+ if (!fastrpc_map_get(*ppmap))
+ return 0;
+ dev_dbg(sess->dev, "%s: Failed to get map fd=%d\n",
+ __func__, fd);
+ }
+
+ err = fastrpc_map_attach(fl, fd, len, attr, ppmap);
+
+ return err;
+}
+
/*
* Fastrpc payload buffer with metadata looks like:
*
@@ -925,8 +931,12 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx)
ctx->args[i].length == 0)
continue;
- err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
- ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
+ if (i < ctx->nbufs)
+ err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
+ ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
+ else
+ err = fastrpc_map_attach(ctx->fl, ctx->args[i].fd,
+ ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
if (err) {
dev_err(dev, "Error Creating map %d\n", err);
return -EINVAL;
@@ -1116,7 +1126,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {
if (!fdlist[i])
break;
- if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false))
+ if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap))
fastrpc_map_put(mmap);
}
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v2 4/4] misc: fastrpc: Skip reference for DMA handles
2025-08-06 11:51 ` [PATCH v2 4/4] misc: fastrpc: Skip reference for DMA handles Ling Xu
@ 2025-08-06 23:19 ` kernel test robot
0 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2025-08-06 23:19 UTC (permalink / raw)
To: Ling Xu, srini, amahesh, arnd, gregkh, sumit.semwal,
christian.koenig, thierry.escande, quic_vgattupa
Cc: llvm, oe-kbuild-all, quic_kuiw, ekansh.gupta, dri-devel,
linux-arm-msm, linux-media, linaro-mm-sig, linux-kernel, Ling Xu,
stable
Hi Ling,
kernel test robot noticed the following build warnings:
[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on char-misc/char-misc-next char-misc/char-misc-linus linus/master v6.16 next-20250806]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Ling-Xu/misc-fastrpc-Save-actual-DMA-size-in-fastrpc_map-structure/20250806-200133
base: char-misc/char-misc-testing
patch link: https://lore.kernel.org/r/20250806115114.688814-5-quic_lxu5%40quicinc.com
patch subject: [PATCH v2 4/4] misc: fastrpc: Skip reference for DMA handles
config: hexagon-randconfig-002-20250807 (https://download.01.org/0day-ci/archive/20250807/202508070731.S30957lV-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 7b8dea265e72c3037b6b1e54d5ab51b7e14f328b)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250807/202508070731.S30957lV-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508070731.S30957lV-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/misc/fastrpc.c:368:30: warning: unused variable 'sess' [-Wunused-variable]
368 | struct fastrpc_session_ctx *sess = fl->sctx;
| ^~~~
1 warning generated.
vim +/sess +368 drivers/misc/fastrpc.c
c68cfb718c8f97 Srinivas Kandagatla 2019-02-08 363
8f6c1d8c4f0cc3 Vamsi Krishna Gattupalli 2022-02-14 364
8f6c1d8c4f0cc3 Vamsi Krishna Gattupalli 2022-02-14 365 static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
1922c68c56c660 Ling Xu 2025-08-06 366 struct fastrpc_map **ppmap)
c68cfb718c8f97 Srinivas Kandagatla 2019-02-08 367 {
9446fa1683a7e3 Abel Vesa 2022-11-24 @368 struct fastrpc_session_ctx *sess = fl->sctx;
c68cfb718c8f97 Srinivas Kandagatla 2019-02-08 369 struct fastrpc_map *map = NULL;
d259063578ed76 Ling Xu 2025-08-06 370 struct dma_buf *buf;
9446fa1683a7e3 Abel Vesa 2022-11-24 371 int ret = -ENOENT;
c68cfb718c8f97 Srinivas Kandagatla 2019-02-08 372
d259063578ed76 Ling Xu 2025-08-06 373 buf = dma_buf_get(fd);
d259063578ed76 Ling Xu 2025-08-06 374 if (IS_ERR(buf))
d259063578ed76 Ling Xu 2025-08-06 375 return PTR_ERR(buf);
d259063578ed76 Ling Xu 2025-08-06 376
9446fa1683a7e3 Abel Vesa 2022-11-24 377 spin_lock(&fl->lock);
c68cfb718c8f97 Srinivas Kandagatla 2019-02-08 378 list_for_each_entry(map, &fl->maps, node) {
d259063578ed76 Ling Xu 2025-08-06 379 if (map->fd != fd || map->buf != buf)
9446fa1683a7e3 Abel Vesa 2022-11-24 380 continue;
9446fa1683a7e3 Abel Vesa 2022-11-24 381
9446fa1683a7e3 Abel Vesa 2022-11-24 382 *ppmap = map;
9446fa1683a7e3 Abel Vesa 2022-11-24 383 ret = 0;
9446fa1683a7e3 Abel Vesa 2022-11-24 384 break;
c68cfb718c8f97 Srinivas Kandagatla 2019-02-08 385 }
9446fa1683a7e3 Abel Vesa 2022-11-24 386 spin_unlock(&fl->lock);
8f6c1d8c4f0cc3 Vamsi Krishna Gattupalli 2022-02-14 387
8f6c1d8c4f0cc3 Vamsi Krishna Gattupalli 2022-02-14 388 return ret;
8f6c1d8c4f0cc3 Vamsi Krishna Gattupalli 2022-02-14 389 }
8f6c1d8c4f0cc3 Vamsi Krishna Gattupalli 2022-02-14 390
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 6+ messages in thread