diff mbox series

[RFC] dma-buf: Fix dma reservation with zero fences

Message ID 20231214120824.655946-1-mika.kuoppala@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series [RFC] dma-buf: Fix dma reservation with zero fences | expand

Commit Message

Mika Kuoppala Dec. 14, 2023, 12:08 p.m. UTC
Driver can initialize without any fences. If so
roundup_power_of_two will overflow as it will try to
subtract one from initial value before shift,
(1 << fls_long(-1)).

Fix this using default (4) if num_fences is zero.

Another more radical option would be to return error on
zero but that would need a callsite comb.

Caught-by: UBSAN
Cc: Christian König <christian.koenig@amd.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/dma-buf/dma-resv.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

Comments

Christian König Dec. 14, 2023, 3:44 p.m. UTC | #1
Am 14.12.23 um 13:08 schrieb Mika Kuoppala:
> Driver can initialize without any fences. If so
> roundup_power_of_two will overflow as it will try to
> subtract one from initial value before shift,
> (1 << fls_long(-1)).

Ah, yes that reminds me that I wanted to take care of this as well.

But solving it like this is the wrong approach. A couple of driver 
calculate the number of fences needed based on userspace input. If that 
results in zero then you certainly have a bug in your driver.

Since calling dma_resv_reserve_fences() with num_fences==0 does make 
much sense we should really just warn about it and just return early 
from the function.

Regards,
Christian.


>
> Fix this using default (4) if num_fences is zero.
>
> Another more radical option would be to return error on
> zero but that would need a callsite comb.
>
> Caught-by: UBSAN
> Cc: Christian König <christian.koenig@amd.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> ---
>   drivers/dma-buf/dma-resv.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
> index 38b4110378de..f5ad3ecd0d4f 100644
> --- a/drivers/dma-buf/dma-resv.c
> +++ b/drivers/dma-buf/dma-resv.c
> @@ -192,7 +192,10 @@ int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences)
>   			return 0;
>   		max = max(old->num_fences + num_fences, old->max_fences * 2);
>   	} else {
> -		max = max(4ul, roundup_pow_of_two(num_fences));
> +		if (num_fences)
> +			max = max(4ul, roundup_pow_of_two(num_fences));
> +		else
> +			max = 4ul;
>   	}
>   
>   	new = dma_resv_list_alloc(max);
Mika Kuoppala Dec. 15, 2023, 10:39 a.m. UTC | #2
Christian König <christian.koenig@amd.com> writes:

> Am 14.12.23 um 13:08 schrieb Mika Kuoppala:
>> Driver can initialize without any fences. If so
>> roundup_power_of_two will overflow as it will try to
>> subtract one from initial value before shift,
>> (1 << fls_long(-1)).
>
> Ah, yes that reminds me that I wanted to take care of this as well.
>
> But solving it like this is the wrong approach. A couple of driver 
> calculate the number of fences needed based on userspace input. If that 
> results in zero then you certainly have a bug in your driver.
>
> Since calling dma_resv_reserve_fences() with num_fences==0 does make 
> much sense we should really just warn about it and just return early 
> from the function.

Sounds like a plan. I will fix our driver to just omit the call
if no fences (yet).

Thanks,
-Mika

> Regards,
> Christian.
>
>
>>
>> Fix this using default (4) if num_fences is zero.
>>
>> Another more radical option would be to return error on
>> zero but that would need a callsite comb.
>>
>> Caught-by: UBSAN
>> Cc: Christian König <christian.koenig@amd.com>
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
>> ---
>>   drivers/dma-buf/dma-resv.c | 5 ++++-
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
>> index 38b4110378de..f5ad3ecd0d4f 100644
>> --- a/drivers/dma-buf/dma-resv.c
>> +++ b/drivers/dma-buf/dma-resv.c
>> @@ -192,7 +192,10 @@ int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences)
>>   			return 0;
>>   		max = max(old->num_fences + num_fences, old->max_fences * 2);
>>   	} else {
>> -		max = max(4ul, roundup_pow_of_two(num_fences));
>> +		if (num_fences)
>> +			max = max(4ul, roundup_pow_of_two(num_fences));
>> +		else
>> +			max = 4ul;
>>   	}
>>   
>>   	new = dma_resv_list_alloc(max);
diff mbox series

Patch

diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 38b4110378de..f5ad3ecd0d4f 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -192,7 +192,10 @@  int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences)
 			return 0;
 		max = max(old->num_fences + num_fences, old->max_fences * 2);
 	} else {
-		max = max(4ul, roundup_pow_of_two(num_fences));
+		if (num_fences)
+			max = max(4ul, roundup_pow_of_two(num_fences));
+		else
+			max = 4ul;
 	}
 
 	new = dma_resv_list_alloc(max);