From: Xiaogang Chen <xiaogang.chen@xxxxxxx> When application is about finish it destroys queues it has created by an ioctl. Driver deletes queue entry(/sys/class/kfd/kfd/proc/pid/queues/queueid/) which is directory including this queue all attributes. Low level kernel code deletes all attributes under this directory. The lock from kernel is on queue entry, not its attributes. At meantime another user space application can read the attributes. There is possibility that the application can hold/read the attributes while kernel is deleting the queue entry, cause the application have invalid memory access, then killed by kernel. Driver changes: explicitly create/destroy each attribute for each queue, let kernel put lock on each attribute too. Signed-off-by: Xiaogang Chen <xiaogang.chen@xxxxxxx> --- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 3 +++ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 33 +++++++----------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 0c3f911e3bf4..045da300749e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -546,6 +546,9 @@ struct queue { /* procfs */ struct kobject kobj; + struct attribute attr_guid; + struct attribute attr_size; + struct attribute attr_type; }; enum KFD_MQD_TYPE { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 9158f9754a24..04a5638f9196 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -73,6 +73,8 @@ static void evict_process_worker(struct work_struct *work); static void restore_process_worker(struct work_struct *work); static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd); +static void kfd_sysfs_create_file(struct kobject *kobj, struct attribute *attr, + char *name); struct kfd_procfs_tree { struct kobject *kobj; @@ -441,35 +443,12 @@ static ssize_t kfd_sysfs_counters_show(struct kobject *kobj, return 0; } -static struct attribute attr_queue_size = { - .name = "size", - .mode = KFD_SYSFS_FILE_MODE -}; - -static struct attribute attr_queue_type = { - .name = "type", - .mode = KFD_SYSFS_FILE_MODE -}; - -static struct attribute attr_queue_gpuid = { - .name = "gpuid", - .mode = KFD_SYSFS_FILE_MODE -}; - -static struct attribute *procfs_queue_attrs[] = { - &attr_queue_size, - &attr_queue_type, - &attr_queue_gpuid, - NULL -}; - static const struct sysfs_ops procfs_queue_ops = { .show = kfd_procfs_queue_show, }; static struct kobj_type procfs_queue_type = { .sysfs_ops = &procfs_queue_ops, - .default_attrs = procfs_queue_attrs, }; static const struct sysfs_ops procfs_stats_ops = { @@ -511,6 +490,10 @@ int kfd_procfs_add_queue(struct queue *q) return ret; } + kfd_sysfs_create_file(&q->kobj, &q->attr_guid, "guid"); + kfd_sysfs_create_file(&q->kobj, &q->attr_size, "size"); + kfd_sysfs_create_file(&q->kobj, &q->attr_type, "type"); + return 0; } @@ -655,6 +638,10 @@ void kfd_procfs_del_queue(struct queue *q) if (!q) return; + sysfs_remove_file(&q->kobj, &q->attr_guid); + sysfs_remove_file(&q->kobj, &q->attr_size); + sysfs_remove_file(&q->kobj, &q->attr_type); + kobject_del(&q->kobj); kobject_put(&q->kobj); } -- 2.25.1