2023-07-24 07:47:31

by Ekansh Gupta

[permalink] [raw]
Subject: [PATCH v2] misc: fastrpc: Fix incorrect DMA mapping unmap request

Scatterlist table is obtained during map create request and the same
table is used for DMA mapping unmap. In case there is any failure
while getting the sg_table, ERR_PTR is returned instead of sg_table.

When the map is getting freed, there is only a non-NULL check of
sg_table which will also be true in case failure was returned instead
of sg_table. This would result in improper unmap request. Add proper
check to avoid bad unmap request.

Fixes: c68cfb718c8f ("misc: fastrpc: Add support for context Invoke method")
Cc: stable <[email protected]>
Tested-by: Ekansh Gupta <[email protected]>
Signed-off-by: Ekansh Gupta <[email protected]>
---
Changes in v2:
- Added fixes information to commit text

drivers/misc/fastrpc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 9666d28..75da69a 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -313,7 +313,7 @@ static void fastrpc_free_map(struct kref *ref)

map = container_of(ref, struct fastrpc_map, refcount);

- if (map->table) {
+ if (map->table && !IS_ERR(map->table)) {
if (map->attr & FASTRPC_ATTR_SECUREMAP) {
struct qcom_scm_vmperm perm;
int vmid = map->fl->cctx->vmperms[0].vmid;
--
2.7.4



2023-07-26 06:44:36

by Bjorn Andersson

[permalink] [raw]
Subject: Re: [PATCH v2] misc: fastrpc: Fix incorrect DMA mapping unmap request

On Mon, Jul 24, 2023 at 12:39:31PM +0530, Ekansh Gupta wrote:
> Scatterlist table is obtained during map create request and the same

I'm guessing that this all happens in fastrpc_map_create() where:

map->table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL);

fails, we jump to map_err, and then call fastrpc_map_put(map), which
then ends up in the code below?

> table is used for DMA mapping unmap. In case there is any failure
> while getting the sg_table, ERR_PTR is returned instead of sg_table.

The problem isn't that ERR_PTR() is being returned, the problem is that
this is being assigned to map->table and you keep running.

>
> When the map is getting freed, there is only a non-NULL check of
> sg_table which will also be true in case failure was returned instead
> of sg_table. This would result in improper unmap request. Add proper
> check to avoid bad unmap request.
>
> Fixes: c68cfb718c8f ("misc: fastrpc: Add support for context Invoke method")
> Cc: stable <[email protected]>
> Tested-by: Ekansh Gupta <[email protected]>

You always test your own patches, so no need to declare this.

> Signed-off-by: Ekansh Gupta <[email protected]>
> ---
> Changes in v2:
> - Added fixes information to commit text
>
> drivers/misc/fastrpc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
> index 9666d28..75da69a 100644
> --- a/drivers/misc/fastrpc.c
> +++ b/drivers/misc/fastrpc.c
> @@ -313,7 +313,7 @@ static void fastrpc_free_map(struct kref *ref)
>
> map = container_of(ref, struct fastrpc_map, refcount);
>
> - if (map->table) {
> + if (map->table && !IS_ERR(map->table)) {

Rather than carrying around an IS_ERR(map->table), I think you should
address this at the originating place. E.g. assign the return value of
the dma_buf_map_attachment_unlocked() to a local variable and only if it
is valid you assign map->table. Or perhaps make it NULL in the error
path.

Regards,
Bjorn

> if (map->attr & FASTRPC_ATTR_SECUREMAP) {
> struct qcom_scm_vmperm perm;
> int vmid = map->fl->cctx->vmperms[0].vmid;
> --
> 2.7.4
>

2023-07-26 08:07:28

by Ekansh Gupta

[permalink] [raw]
Subject: Re: [PATCH v2] misc: fastrpc: Fix incorrect DMA mapping unmap request



On 7/26/2023 12:00 PM, Bjorn Andersson wrote:
> On Mon, Jul 24, 2023 at 12:39:31PM +0530, Ekansh Gupta wrote:
>> Scatterlist table is obtained during map create request and the same
>
> I'm guessing that this all happens in fastrpc_map_create() where:
>
> map->table = dma_buf_map_attachment_unlocked(map->attach, DMA_BIDIRECTIONAL);
>
> fails, we jump to map_err, and then call fastrpc_map_put(map), which
> then ends up in the code below?
>
yes, your understanding is correct.
>> table is used for DMA mapping unmap. In case there is any failure
>> while getting the sg_table, ERR_PTR is returned instead of sg_table.
>
> The problem isn't that ERR_PTR() is being returned, the problem is that
> this is being assigned to map->table and you keep running.
>
>>
>> When the map is getting freed, there is only a non-NULL check of
>> sg_table which will also be true in case failure was returned instead
>> of sg_table. This would result in improper unmap request. Add proper
>> check to avoid bad unmap request.
>>
>> Fixes: c68cfb718c8f ("misc: fastrpc: Add support for context Invoke method")
>> Cc: stable <[email protected]>
>> Tested-by: Ekansh Gupta <[email protected]>
>
> You always test your own patches, so no need to declare this.
>
sure, I'll avoid adding this for future changes.
>> Signed-off-by: Ekansh Gupta <[email protected]>
>> ---
>> Changes in v2:
>> - Added fixes information to commit text
>>
>> drivers/misc/fastrpc.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
>> index 9666d28..75da69a 100644
>> --- a/drivers/misc/fastrpc.c
>> +++ b/drivers/misc/fastrpc.c
>> @@ -313,7 +313,7 @@ static void fastrpc_free_map(struct kref *ref)
>>
>> map = container_of(ref, struct fastrpc_map, refcount);
>>
>> - if (map->table) {
>> + if (map->table && !IS_ERR(map->table)) {
>
> Rather than carrying around an IS_ERR(map->table), I think you should
> address this at the originating place. E.g. assign the return value of
> the dma_buf_map_attachment_unlocked() to a local variable and only if it
> is valid you assign map->table. Or perhaps make it NULL in the error
> path.
>
understood, this looks much cleaner solution. I'll update this in the
next patch. Thanks for taking your time to review this change, Bjorn.
--ekansh

> Regards,
> Bjorn
>
>> if (map->attr & FASTRPC_ATTR_SECUREMAP) {
>> struct qcom_scm_vmperm perm;
>> int vmid = map->fl->cctx->vmperms[0].vmid;
>> --
>> 2.7.4
>>