From fd3c49bb7885ff2d27ad8eaa71e0a568044fa047 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 28 Oct 2020 19:47:15 +0100 Subject: [PATCH] etnaviv: drm: fix BO refcount race There is a race where the BO refcount might drop to 0 before the dmabuf/name import paths had a chance to grab a reference for a BO found in the handle_table. The easiest solution is to keep the refcount stable as long as the table_lock is held. While a more involved scheme of rechecking the refcount before actually destroying the BO might also work, the bo_del path isn't called very often, so micro-optimizing a single mutex_lock seems to be over-engineered, so go for the easy solution. Cc: Signed-off-by: Lucas Stach Reviewed-by: Christian Gmeiner Part-of: (cherry picked from commit 866bb22d6b91d7a12e62803bacf7d8bc912d3216) --- .pick_status.json | 2 +- src/etnaviv/drm/etnaviv_bo.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 774670e039c..196691780ff 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -625,7 +625,7 @@ "description": "etnaviv: drm: fix BO refcount race", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "master_sha": null, "because_sha": null }, diff --git a/src/etnaviv/drm/etnaviv_bo.c b/src/etnaviv/drm/etnaviv_bo.c index 0ec64b780f5..7fde304ed3b 100644 --- a/src/etnaviv/drm/etnaviv_bo.c +++ b/src/etnaviv/drm/etnaviv_bo.c @@ -257,11 +257,15 @@ void etna_bo_del(struct etna_bo *bo) struct etna_device *dev = bo->dev; - if (!p_atomic_dec_zero(&bo->refcnt)) - return; - pthread_mutex_lock(&etna_drm_table_lock); + /* Must test under table lock to avoid racing with the from_dmabuf/name + * paths, which rely on the BO refcount to be stable over the lookup, so + * they can grab a reference when the BO is found in the hash. + */ + if (!p_atomic_dec_zero(&bo->refcnt)) + goto out; + if (bo->reuse && (etna_bo_cache_free(&dev->bo_cache, bo) == 0)) goto out;