[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