Commit 1e1d3574 authored by Asahi Lina's avatar Asahi Lina Committed by Luben Tuikov

drm/scheduler: Fix UAF race in drm_sched_entity_push_job()

After a job is pushed into the queue, it is owned by the scheduler core
and may be freed at any time, so we can't write nor read the submit
timestamp after that point.

Fixes oopses observed with the drm/asahi driver, found with kASAN.
Signed-off-by: default avatarAsahi Lina <lina@asahilina.net>
Link: https://lore.kernel.org/r/20230406-scheduler-uaf-2-v1-1-972531cf0a81@asahilina.netReviewed-by: default avatarLuben Tuikov <luben.tuikov@amd.com>
Signed-off-by: default avatarLuben Tuikov <luben.tuikov@amd.com>
parent 0ec86718
...@@ -507,12 +507,19 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job) ...@@ -507,12 +507,19 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
{ {
struct drm_sched_entity *entity = sched_job->entity; struct drm_sched_entity *entity = sched_job->entity;
bool first; bool first;
ktime_t submit_ts;
trace_drm_sched_job(sched_job, entity); trace_drm_sched_job(sched_job, entity);
atomic_inc(entity->rq->sched->score); atomic_inc(entity->rq->sched->score);
WRITE_ONCE(entity->last_user, current->group_leader); WRITE_ONCE(entity->last_user, current->group_leader);
/*
* After the sched_job is pushed into the entity queue, it may be
* completed and freed up at any time. We can no longer access it.
* Make sure to set the submit_ts first, to avoid a race.
*/
sched_job->submit_ts = submit_ts = ktime_get();
first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node); first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);
sched_job->submit_ts = ktime_get();
/* first job wakes up scheduler */ /* first job wakes up scheduler */
if (first) { if (first) {
...@@ -529,7 +536,7 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job) ...@@ -529,7 +536,7 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
spin_unlock(&entity->rq_lock); spin_unlock(&entity->rq_lock);
if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
drm_sched_rq_update_fifo(entity, sched_job->submit_ts); drm_sched_rq_update_fifo(entity, submit_ts);
drm_sched_wakeup(entity->rq->sched); drm_sched_wakeup(entity->rq->sched);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment