⬢ DragonFlyBSD Kernel Audit
DF-3862 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/amdgpu/amdgpu_device.c
+++ b/sys/dev/drm/amd/amdgpu/amdgpu_device.c
@@ -3389,6 +3389,14 @@
 			      struct amdgpu_job *job)
 {
 	int i, r, resched;
+	/* DF-3862: the timed-out job carries no reference held by the TDR
+	 * path (drm_sched_job_timedout drops job_list_lock before calling
+	 * us).  Fence completions during the reset can schedule
+	 * drm_sched_job_finish -> amdgpu_job_free_cb and kfree(job).
+	 * Snapshot the scheduler pointer once and stop dereferencing @job
+	 * after hw_job_reset/force_completion.
+	 */
+	struct drm_gpu_scheduler *job_sched = job ? job->base.sched : NULL;
 
 	dev_info(adev->dev, "GPU reset begin!\n");
 
@@ -3411,7 +3419,7 @@
 
 		kthread_park(ring->sched.thread);
 
-		if (job && job->base.sched != &ring->sched)
+		if (job_sched && job_sched != &ring->sched)
 			continue;
 
 		drm_sched_hw_job_reset(&ring->sched, job ? &job->base : NULL);
@@ -3435,7 +3443,7 @@
 		 * or all rings (in the case @job is NULL)
 		 * after above amdgpu_reset accomplished
 		 */
-		if ((!job || job->base.sched == &ring->sched) && !r)
+		if ((!job_sched || job_sched == &ring->sched) && !r)
 			drm_sched_job_recovery(&ring->sched);
 
 		kthread_unpark(ring->sched.thread);