OSDN Git Service

drm/amdgpu: fix user fence handling once more
authorChristian König <christian.koenig@amd.com>
Wed, 29 Jun 2016 11:26:41 +0000 (13:26 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 7 Jul 2016 19:06:09 +0000 (15:06 -0400)
Same problem as with the VM page tables. The user fence address must be
determined before the job is scheduled, not when the IB is executed.

This fixes a security problem where user fences could be used to overwrite
any part of VRAM.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Chunming Zhou <david1.zhou@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c

index cd7d159..4fc879e 100644 (file)
@@ -1278,8 +1278,7 @@ struct amdgpu_job {
        uint32_t                oa_base, oa_size;
 
        /* user fence handling */
-       struct amdgpu_bo        *uf_bo;
-       uint32_t                uf_offset;
+       uint64_t                uf_addr;
        uint64_t                uf_sequence;
 
 };
index 95b2481..475c95f 100644 (file)
@@ -216,11 +216,8 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
        if (ret)
                goto free_all_kdata;
 
-       if (p->uf_entry.robj) {
-               p->job->uf_bo = amdgpu_bo_ref(p->uf_entry.robj);
-               p->job->uf_offset = uf_offset;
-       }
-
+       if (p->uf_entry.robj)
+               p->job->uf_addr = uf_offset;
        kfree(chunk_array);
        return 0;
 
@@ -502,6 +499,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
                }
        }
 
+       if (p->uf_entry.robj)
+               p->job->uf_addr += amdgpu_bo_gpu_offset(p->uf_entry.robj);
+
 error_validate:
        if (r) {
                amdgpu_vm_move_pt_bos_in_lru(p->adev, &fpriv->vm);
@@ -767,7 +767,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
        }
 
        /* UVD & VCE fw doesn't support user fences */
-       if (parser->job->uf_bo && (
+       if (parser->job->uf_addr && (
            parser->job->ring->type == AMDGPU_RING_TYPE_UVD ||
            parser->job->ring->type == AMDGPU_RING_TYPE_VCE))
                return -EINVAL;
index 34e3542..0bf6c1b 100644 (file)
@@ -203,11 +203,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
        }
 
        /* wrap the last IB with fence */
-       if (job && job->uf_bo) {
-               uint64_t addr = amdgpu_bo_gpu_offset(job->uf_bo);
-
-               addr += job->uf_offset;
-               amdgpu_ring_emit_fence(ring, addr, job->uf_sequence,
+       if (job && job->uf_addr) {
+               amdgpu_ring_emit_fence(ring, job->uf_addr, job->uf_sequence,
                                       AMDGPU_FENCE_FLAG_64BIT);
        }
 
index b50a845..87b75d7 100644 (file)
@@ -91,7 +91,6 @@ static void amdgpu_job_free_resources(struct amdgpu_job *job)
                amdgpu_ib_free(job->adev, &job->ibs[i], f);
        fence_put(job->fence);
 
-       amdgpu_bo_unref(&job->uf_bo);
        amdgpu_sync_free(&job->sync);
 }