From e22d743a2077a17ed0dc8c2fedba8f5852c9e724 Mon Sep 17 00:00:00 2001 From: Seema Khowala Date: Fri, 16 Aug 2019 10:39:18 -0700 Subject: [PATCH] gpu: nvgpu: fix race for channel sync read/write CTS test dEQP-VK.api.object_management.max_concurrent.device_group crashes with invalid userspace memory access. Currently, nvgpu_submit_prepare_syncs() races with nvgpu_channel_clean_up_jobs() and this race condition is exposed when aggressive_sync_destroy_thresh is set to non-zero value. nvgpu_submit_prepare_syncs() gets ref for c->sync to submit job and releases channel sync_lock. Meanwhile, nvgpu_worker_poll_work() triggers nvgpu_channel_clean_up_jobs(), which destroys ref'd c->sync pointer. This patch protects channel's sync pointer by holding channel sync_lock during complete execution of nvgpu_submit_prepare_syncs(). Bug 2613870 Change-Id: I6f3d48aff361d1cb38c30d2ce5de276d0c55fb6f Signed-off-by: Seema Khowala Reviewed-on: https://git-master.nvidia.com/r/2176929 Reviewed-by: Vedashree Vidwans Reviewed-by: Debarshi Dutta GVS: Gerrit_Virtual_Submit Tested-by: Vedashree Vidwans Reviewed-by: Alex Waterman Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/fifo/channel.c | 5 +++-- drivers/gpu/nvgpu/common/fifo/submit.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/nvgpu/common/fifo/channel.c b/drivers/gpu/nvgpu/common/fifo/channel.c index c55c8ed9e..477813d8c 100644 --- a/drivers/gpu/nvgpu/common/fifo/channel.c +++ b/drivers/gpu/nvgpu/common/fifo/channel.c @@ -1357,6 +1357,8 @@ void nvgpu_channel_clean_up_jobs(struct nvgpu_channel *c, break; } + nvgpu_mutex_acquire(&c->sync_lock); + WARN_ON(c->sync == NULL); if (c->sync != NULL) { @@ -1366,16 +1368,15 @@ void nvgpu_channel_clean_up_jobs(struct nvgpu_channel *c, } if (g->aggressive_sync_destroy_thresh != 0U) { - nvgpu_mutex_acquire(&c->sync_lock); if (nvgpu_channel_sync_put_ref_and_check(c->sync) && g->aggressive_sync_destroy) { nvgpu_channel_sync_destroy(c->sync, false); c->sync = NULL; } - nvgpu_mutex_release(&c->sync_lock); } } + nvgpu_mutex_release(&c->sync_lock); if (job->num_mapped_buffers != 0U) { nvgpu_vm_put_buffers(vm, job->mapped_buffers, diff --git a/drivers/gpu/nvgpu/common/fifo/submit.c b/drivers/gpu/nvgpu/common/fifo/submit.c index 76397d3eb..6a43fe799 100644 --- a/drivers/gpu/nvgpu/common/fifo/submit.c +++ b/drivers/gpu/nvgpu/common/fifo/submit.c @@ -59,19 +59,17 @@ static int nvgpu_submit_prepare_syncs(struct nvgpu_channel *c, bool flag_sync_fence = (flags & NVGPU_SUBMIT_FLAGS_SYNC_FENCE) != 0U; bool flag_fence_wait = (flags & NVGPU_SUBMIT_FLAGS_FENCE_WAIT) != 0U; + nvgpu_mutex_acquire(&c->sync_lock); if (g->aggressive_sync_destroy_thresh != 0U) { - nvgpu_mutex_acquire(&c->sync_lock); if (c->sync == NULL) { c->sync = nvgpu_channel_sync_create(c, false); if (c->sync == NULL) { err = -ENOMEM; - nvgpu_mutex_release(&c->sync_lock); goto fail; } new_sync_created = true; } nvgpu_channel_sync_get_ref(c->sync); - nvgpu_mutex_release(&c->sync_lock); } if ((g->ops.channel.set_syncpt != NULL) && new_sync_created) { @@ -163,6 +161,7 @@ static int nvgpu_submit_prepare_syncs(struct nvgpu_channel *c, goto clean_up_incr_cmd; } + nvgpu_mutex_release(&c->sync_lock); return 0; clean_up_incr_cmd: @@ -181,6 +180,7 @@ clean_up_wait_cmd: job->wait_cmd = NULL; } fail: + nvgpu_mutex_release(&c->sync_lock); *wait_cmd = NULL; return err; }