On 25-06-2026 13:38, Jianping Li wrote:
> fastrpc_create_maps() performs map lookup only for buffer
> arguments (i < ctx->nbufs) via fastrpc_map_create(). For
> arguments beyond this range, no lookup is performed, which
> can result in duplicate DMA mappings for the same file
> descriptor.
> 
> Additionally, if the same file descriptor is passed multiple
> times within a single invocation, performing lookups with
> reference counting would increment the reference multiple
> times, while fastrpc_put_args() would release it only once,
> leading to an imbalanced reference count.
> 
> Fix this by allowing fastrpc_map_create() to control whether
> the lookup should take a reference. For arguments beyond
> ctx->nbufs, the lookup is performed without taking a
> reference, ensuring that existing mappings are reused
> without introducing duplicate DMA mappings or reference
> count imbalance.
> 
> Fixes: 10df039834f84 ("misc: fastrpc: Skip reference for DMA handles")
> Cc: [email protected]
> Signed-off-by: Jianping Li <[email protected]>
> ---
>  drivers/misc/fastrpc.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index a9b2ae44c06f..2622a1360a65 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -924,9 +924,9 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, 
> int fd,
>  }
>  
>  static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
> -                           u64 len, u32 attr, struct fastrpc_map **ppmap)
> +                           u64 len, u32 attr, struct fastrpc_map **ppmap, 
> bool take_ref)
>  {
> -     if (!fastrpc_map_lookup(fl, fd, ppmap, true))
> +     if (!fastrpc_map_lookup(fl, fd, ppmap, take_ref))
>               return 0;
>  
>       return fastrpc_map_attach(fl, fd, len, attr, ppmap);
> @@ -999,23 +999,23 @@ static int fastrpc_create_maps(struct 
> fastrpc_invoke_ctx *ctx)
>       int i, err;
>  
>       for (i = 0; i < ctx->nscalars; ++i) {
> +             bool take_ref = true;
bool take_ref = i < ctx->nbufs, also add a comment stating why reference
should be skipped for DMA handles.>
>               if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1 ||
>                   ctx->args[i].length == 0)
>                       continue;
>  
> -             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 (i >= ctx->nbufs)
> +                     take_ref = false;
> +
> +             err = fastrpc_map_create(ctx->fl, ctx->args[i].fd, 
> ctx->args[i].length,
> +                      ctx->args[i].attr, &ctx->maps[i], take_ref);
>               if (err) {
>                       dev_err(dev, "Error Creating map %d\n", err);
>                       return -EINVAL;
>               }
> -
>       }
> +
>       return 0;
>  }
>  
> @@ -1508,7 +1508,7 @@ static int fastrpc_init_create_process(struct 
> fastrpc_user *fl,
>       fl->pd = USER_PD;
>  
>       if (init.filelen && init.filefd) {
> -             err = fastrpc_map_create(fl, init.filefd, init.filelen, 0, 
> &map);
> +             err = fastrpc_map_create(fl, init.filefd, init.filelen, 0, 
> &map, true);
>               if (err)
>                       goto err;
>       }
> @@ -2100,7 +2100,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, 
> char __user *argp)
>               return -EFAULT;
>  
>       /* create SMMU mapping */
> -     err = fastrpc_map_create(fl, req.fd, req.length, 0, &map);
> +     err = fastrpc_map_create(fl, req.fd, req.length, 0, &map, true);
>       if (err) {
>               dev_err(dev, "failed to map buffer, fd = %d\n", req.fd);
>               return err;

Reply via email to