All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Stanislav Kinsburskii" <skinsburskii@gmail.com>
Cc: linux-hyperv@vger.kernel.org, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v10 8/8] drm/gpusvm: Use hmm_range_fault_unlocked_timeout() for range faults
Date: Wed, 22 Jul 2026 21:59:31 +0000	[thread overview]
Message-ID: <20260722215932.41A591F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260722-hmm-v10-v1-8-606464dd601a@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] TOCTOU race on volatile `jiffies` can result in a 0 timeout, causing an infinite loop.
- [High] The absolute outer deadline in `drm_gpusvm_get_pages()` is defeated by the relative timeout extension semantics of `hmm_range_fault_unlocked_timeout()`.

Pre-existing issues:
- [High] Failure to allocate `pfns` in `drm_gpusvm_range_evict()` leaks the `mm_struct` reference.
--

--- Patch [8]: [PATCH v10 8/8] drm/gpusvm: Use hmm_range_fault_unlocked_timeout() for range faults ---
commit f0577dfbb2f6c27cfd07d3be42e1db31600b9e4d
Author: Stanislav Kinsburskii <skinsburskii@gmail.com>
Subject: drm/gpusvm: Use hmm_range_fault_unlocked_timeout() for range faults

This commit replaces open-coded HMM fault retry loops in the GPU SVM paths
with the new hmm_range_fault_unlocked_timeout() helper. It updates
drm_gpusvm_scan_mm(), drm_gpusvm_range_evict(), and drm_gpusvm_get_pages()
to delegate mmap_lock acquisition and retry logic to the helper.

> diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
> index 958cb605aedd5..b946f920b7a00 100644
> --- a/drivers/gpu/drm/drm_gpusvm.c
> +++ b/drivers/gpu/drm/drm_gpusvm.c
[ ... ]
> @@ -1408,6 +1392,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
>  	void *zdd;
>  	unsigned long timeout =
>  		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
> +	unsigned long remaining;
>  	unsigned long i, j;
>  	unsigned long npages = npages_in_range(pages_start, pages_end);
>  	unsigned long num_dma_mapped;
> @@ -1422,9 +1407,11 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
>  	struct dma_iova_state *state = &svm_pages->state;
>  
>  retry:
> -	if (time_after(jiffies, timeout))
> +	if (time_after_eq(jiffies, timeout))
>  		return -EBUSY;
>  
> +	remaining = timeout - jiffies;

[Severity: High]
Does this double read of jiffies introduce a race condition?

Because jiffies is volatile, it is fetched from memory for the
time_after_eq() check, and then fetched again for the subtraction. If
jiffies increments between these reads, remaining can evaluate to 0
(if jiffies equals timeout) or ULONG_MAX (if jiffies ticks past timeout).

When remaining is 0, hmm_range_fault_unlocked_timeout() disables the
deadline entirely. When it is ULONG_MAX, the timeout is effectively
infinite, which could hang the page-fault worker.

>  	hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
>  	if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
>  		goto set_seqno;
> @@ -1439,21 +1426,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
>  	}
>  
>  	hmm_range.hmm_pfns = pfns;
> -	while (true) {
> -		mmap_read_lock(mm);
> -		err = hmm_range_fault(&hmm_range);
> -		mmap_read_unlock(mm);
> -
> -		if (err == -EBUSY) {
> -			if (time_after(jiffies, timeout))
> -				break;
> -
> -			hmm_range.notifier_seq =
> -				mmu_interval_read_begin(notifier);
> -			continue;
> -		}
> -		break;
> -	}
> +	err = hmm_range_fault_unlocked_timeout(&hmm_range, remaining);

[Severity: High]
Does passing remaining defeat the absolute deadline intended for this path?

The commit message notes that drm_gpusvm_get_pages() keeps an absolute outer
deadline to prevent endless invalidation retry loops from hanging GPU
page-fault workers.

However, hmm_range_fault_unlocked_timeout() treats the passed value as a
relative timeout and recalculates its internal deadline every time the lock
is dropped:

mm/hmm.c:hmm_range_fault_unlocked_timeout() {
    ...
    if (timeout && !locked)
        deadline = jiffies + timeout;
    ...
}

Since remaining is passed as the full timeout budget, the helper will extend
its deadline by the full amount of remaining into the future every time it
drops the lock, which can allow an infinite loop.

>  	mmput(mm);
>  	if (err)
>  		goto err_free;
[ ... ]
> @@ -1736,24 +1708,12 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
>  		return -ENOMEM;

[Severity: High]
This is a pre-existing issue, but does this error path leak the mm_struct
reference?

Earlier in drm_gpusvm_range_evict(), the code acquires an mm reference:

    if (!mmget_not_zero(mm))
        return -EFAULT;

If kvmalloc_array() fails, the function returns -ENOMEM directly, bypassing
the mmput(mm) call at the end of the function. This permanently leaks the mm
reference, preventing the target process's memory structures from being freed
upon exit.

>  
>  	hmm_range.hmm_pfns = pfns;
> -	while (!time_after(jiffies, timeout)) {
> -		hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
> -		if (time_after(jiffies, timeout)) {
> -			err = -ETIME;
> -			break;
> -		}
> -
> -		mmap_read_lock(mm);
> -		err = hmm_range_fault(&hmm_range);
> -		mmap_read_unlock(mm);
> -		if (err != -EBUSY)
> -			break;
> -	}
> +	err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
>  
>  	kvfree(pfns);
>  	mmput(mm);
>  
> -	return err;
> +	return err == -EBUSY ? -ETIME : err;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260722-hmm-v10-v1-0-606464dd601a@gmail.com?part=8

  reply	other threads:[~2026-07-22 21:59 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-22 21:44 [PATCH v10 0/8] mm/hmm: Add mmap lock-drop support for userfaultfd-backed mappings Stanislav Kinsburskii
2026-07-22 21:44 ` [PATCH v10 1/8] mm/hmm: move page fault handling out of walk callbacks Stanislav Kinsburskii
2026-07-22 21:44 ` [PATCH v10 2/8] mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support Stanislav Kinsburskii
2026-07-22 21:44 ` [PATCH v10 3/8] selftests/mm: add HMM test for mmap lock-dropping faults Stanislav Kinsburskii
2026-07-22 21:53   ` sashiko-bot
2026-07-22 21:44 ` [PATCH v10 4/8] mshv: Use hmm_range_fault_unlocked_timeout() for region faults Stanislav Kinsburskii
2026-07-22 21:44 ` [PATCH v10 5/8] drm/nouveau: Use hmm_range_fault_unlocked_timeout() for SVM faults Stanislav Kinsburskii
2026-07-22 21:44 ` [PATCH v10 6/8] RDMA/umem: Use hmm_range_fault_unlocked_timeout() for ODP faults Stanislav Kinsburskii
2026-07-22 21:56   ` sashiko-bot
2026-07-22 21:44 ` [PATCH v10 7/8] accel/amdxdna: Use hmm_range_fault_unlocked_timeout() for range population Stanislav Kinsburskii
2026-07-22 21:44 ` [PATCH v10 8/8] drm/gpusvm: Use hmm_range_fault_unlocked_timeout() for range faults Stanislav Kinsburskii
2026-07-22 21:59   ` sashiko-bot [this message]
2026-07-22 22:48 ` [PATCH v10 0/8] mm/hmm: Add mmap lock-drop support for userfaultfd-backed mappings Andrew Morton
2026-07-22 22:48   ` Andrew Morton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260722215932.41A591F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=skinsburskii@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.