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

Commit 9b56bb11 authored by Felix Kuehling's avatar Felix Kuehling Committed by Oded Gabbay
Browse files

drm/amdkfd: Don't dereference kfd_process.mm



The kfd_process doesn't own a reference to the mm_struct, so it can
disappear without warning even while the kfd_process still exists.

Therefore, avoid dereferencing the kfd_process.mm pointer and make
it opaque. Use get_task_mm to get a temporary reference to the mm
when it's needed.

v2: removed unnecessary WARN_ON

Signed-off-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent 66b783b4
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -24,8 +24,8 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/sched/signal.h>
#include <linux/sched/mm.h>
#include <linux/uaccess.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/memory.h>
#include "kfd_priv.h"
@@ -904,14 +904,24 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
	 * running so the lookup function returns a locked process.
	 */
	struct kfd_process *p = kfd_lookup_process_by_pasid(pasid);
	struct mm_struct *mm;

	if (!p)
		return; /* Presumably process exited. */

	/* Take a safe reference to the mm_struct, which may otherwise
	 * disappear even while the kfd_process is still referenced.
	 */
	mm = get_task_mm(p->lead_thread);
	if (!mm) {
		mutex_unlock(&p->mutex);
		return; /* Process is exiting */
	}

	memset(&memory_exception_data, 0, sizeof(memory_exception_data));

	down_read(&p->mm->mmap_sem);
	vma = find_vma(p->mm, address);
	down_read(&mm->mmap_sem);
	vma = find_vma(mm, address);

	memory_exception_data.gpu_id = dev->id;
	memory_exception_data.va = address;
@@ -937,7 +947,8 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,
		}
	}

	up_read(&p->mm->mmap_sem);
	up_read(&mm->mmap_sem);
	mmput(mm);

	mutex_lock(&p->event_mutex);

+6 −1
Original line number Diff line number Diff line
@@ -494,7 +494,12 @@ struct kfd_process {
	 */
	struct hlist_node kfd_processes;

	struct mm_struct *mm;
	/*
	 * Opaque pointer to mm_struct. We don't hold a reference to
	 * it so it should never be dereferenced from here. This is
	 * only used for looking up processes by their mm.
	 */
	void *mm;

	struct mutex mutex;

+0 −1
Original line number Diff line number Diff line
@@ -200,7 +200,6 @@ static void kfd_process_destroy_delayed(struct rcu_head *rcu)
	struct kfd_process *p;

	p = container_of(rcu, struct kfd_process, rcu);
	WARN_ON(atomic_read(&p->mm->mm_count) <= 0);

	mmdrop(p->mm);