BACKPORT: kgsl: hwsched: Don't cross dereference kgsl_mem_entry pointer

The passed in pointer in kgsl_count_hw_fences() can be a
kgsl_mem_entry pointer. This gets cross dereferenced to
a kgsl_drawobj_sync_event pointer and causes a NULL pointer
dereference. To avoid this cross dereference, decouple the two
paths and call kgsl_count_hw_fences() only in the appropriate
path.

Change-Id: I1088a0b67f1f82a20ddc94c94cbdd31a44b18da6
Signed-off-by: Harshdeep Dhatt <quic_hdhatt@quicinc.com>
This commit is contained in:
Harshdeep Dhatt 2023-09-01 12:27:10 -06:00 • committed by Michael Bestas
commit e7fe0e2788
No known key found for this signature in database
GPG key ID: CC95044519BE6669
4 changed files with 18 additions and 16 deletions

View file

@ -2378,8 +2378,7 @@ static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv,
return -EINVAL;
}
handle = kgsl_sync_fence_async_wait(event.fd,
gpuobj_free_fence_func, entry, NULL);
handle = kgsl_sync_fence_async_wait(event.fd, gpuobj_free_fence_func, entry);
if (IS_ERR(handle)) {
kgsl_mem_entry_unset_pend(entry);

View file

@ -566,8 +566,7 @@ static int drawobj_add_sync_fence(struct kgsl_device *device,
set_bit(event->id, &syncobj->pending);
event->handle = kgsl_sync_fence_async_wait(sync.fd,
drawobj_sync_fence_func, event, priv);
event->handle = kgsl_sync_fence_async_wait(sync.fd, drawobj_sync_fence_func, event);
event->priv = priv;
@ -589,6 +588,8 @@ static int drawobj_add_sync_fence(struct kgsl_device *device,
return ret;
}
kgsl_get_fence_info(event);
for (i = 0; priv && i < priv->num_fences; i++)
trace_syncpoint_fence(syncobj, priv->fences[i].name);

View file

@ -424,19 +424,20 @@ static void kgsl_sync_fence_callback(struct dma_fence *fence,
}
}
static void kgsl_get_fence_names(struct dma_fence *fence,
struct event_fence_info *info_ptr)
void kgsl_get_fence_info(struct kgsl_drawobj_sync_event *event)
{
unsigned int num_fences;
struct dma_fence **fences;
struct dma_fence *fence, **fences;
struct dma_fence_array *array;
struct event_fence_info *info_ptr = event->priv;
int i;
if (!info_ptr)
return;
array = to_dma_fence_array(fence);
fence = event->handle->fence;
array = to_dma_fence_array(fence);
if (array != NULL) {
num_fences = array->num_fences;
fences = array->fences;
@ -471,7 +472,7 @@ static void kgsl_get_fence_names(struct dma_fence *fence,
}
struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
bool (*func)(void *priv), void *priv, struct event_fence_info *info_ptr)
bool (*func)(void *priv), void *priv)
{
struct kgsl_sync_fence_cb *kcb;
struct dma_fence *fence;
@ -492,8 +493,6 @@ struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
kcb->priv = priv;
kcb->func = func;
kgsl_get_fence_names(fence, info_ptr);
/* if status then error or signaled */
status = dma_fence_add_callback(fence, &kcb->fence_cb,
kgsl_sync_fence_callback);

View file

@ -85,9 +85,9 @@ void kgsl_sync_timeline_detach(struct kgsl_sync_timeline *ktimeline);
void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline);
struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
bool (*func)(void *priv), void *priv,
struct event_fence_info *info_ptr);
struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd, bool (*func)(void *priv), void *priv);
void kgsl_get_fence_info(struct kgsl_drawobj_sync_event *event);
void kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb);
@ -128,9 +128,12 @@ static inline void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline)
}
static inline void kgsl_get_fence_info(struct kgsl_drawobj_sync_event *event)
{
}
static inline struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
bool (*func)(void *priv), void *priv,
struct event_fence_info *info_ptr)
bool (*func)(void *priv), void *priv);
{
return NULL;
}