[PATCH libdrm] etnaviv: Fix double-free in etna_bo_cache_free()

Wladimir J. van der Laan laanwj at gmail.com
Thu Jun 27 14:48:49 UTC 2019


On Sun, Jun 02, 2019 at 01:36:27AM +0200, Marek Vasut wrote:
> The following situation can happen in a multithreaded OpenGL application.
> A BO is submitted from etna_cmd_stream #1 with flags set for read.
> A BO is submitted from etna_cmd_stream #2 with flags set for write.
> This triggers a flush on stream #1 and clears the BO's current_stream
> pointer. If at this point, stream #2 attempts to queue BO again, which
> does happen, the BO will be added to the submit list twice. The Linux
> kernel driver correctly detects this and warns about it with "BO at
> index %u already on submit list" kernel message.
> 
> However, when cleaning the BO cache in etna_bo_cache_free(), the BO
> which was submitted twice will also be free()d twice, this triggering
> a glibc double free detector.
> 
> The fix is easy, even if the BO does not have current_stream set,
> iterate over current streams' list of BOs before adding the BO to it
> and verify that the BO is not yet there.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Christian Gmeiner <christian.gmeiner at gmail.com>
> Cc: Lucas Stach <l.stach at pengutronix.de>
> ---
>  etnaviv/etnaviv_cmd_stream.c | 8 +++-----
>  1 file changed, 3 insertions(+), 5 deletions(-)

Thanks for catching this.

Reviewed-by: Wladimir J. van der Laan <laanwj at gmail.com>

> diff --git a/etnaviv/etnaviv_cmd_stream.c b/etnaviv/etnaviv_cmd_stream.c
> index 7139c324..261777b0 100644
> --- a/etnaviv/etnaviv_cmd_stream.c
> +++ b/etnaviv/etnaviv_cmd_stream.c
> @@ -150,11 +150,7 @@ static uint32_t bo2idx(struct etna_cmd_stream *stream, struct etna_bo *bo,
>  
>  	pthread_mutex_lock(&idx_lock);
>  
> -	if (!bo->current_stream) {
> -		idx = append_bo(stream, bo);
> -		bo->current_stream = stream;
> -		bo->idx = idx;
> -	} else if (bo->current_stream == stream) {
> +	if (bo->current_stream == stream) {
>  		idx = bo->idx;
>  	} else {
>  		/* slow-path: */
> @@ -165,6 +161,8 @@ static uint32_t bo2idx(struct etna_cmd_stream *stream, struct etna_bo *bo,
>  			/* not found */
>  			idx = append_bo(stream, bo);
>  		}
> +		bo->current_stream = stream;
> +		bo->idx = idx;
>  	}
>  	pthread_mutex_unlock(&idx_lock);
>  
> -- 
> 2.20.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list