DF-5033 / fix.diff
--- a/sys/dev/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/sys/dev/drm/amd/amdgpu/amdgpu_bo_list.c @@ -164,15 +164,22 @@ int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, struct amdgpu_bo_list **result) { - rcu_read_lock(); + /* + * The DragonFly idr (sys/libkern/linux_idr.c) is not RCU-safe for + * lookups: idr_find() takes no lock, and idr_grow() swaps in a new + * node array and kfree()s the old one synchronously. Serialize + * against idr_alloc()/idr_remove()/idr_replace() with bo_list_lock + * instead of rcu_read_lock(). + */ + mutex_lock(&fpriv->bo_list_lock); *result = idr_find(&fpriv->bo_list_handles, id); if (*result && kref_get_unless_zero(&(*result)->refcount)) { - rcu_read_unlock(); + mutex_unlock(&fpriv->bo_list_lock); return 0; } - rcu_read_unlock(); + mutex_unlock(&fpriv->bo_list_lock); return -ENOENT; } |