Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5f5acbc authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/amdgpu: fix user fence handling once more



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: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarChunming Zhou <david1.zhou@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 56628159
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -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;

};
+6 −6
Original line number Diff line number Diff line
@@ -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;
+2 −5
Original line number Diff line number Diff line
@@ -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);
	}

+0 −1
Original line number Diff line number Diff line
@@ -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);
}