[PATCH] drm/cache: return early from a zero-length clflush
Taimuraz Kaitmazov <[email protected]>
| Newsgroups | org.freedesktop.lists.dri-devel |
|---|---|
| Message-ID | <[email protected]> |
drm_clflush_virt_range() ends with an unconditional clflushopt(end - 1) to force serialisation. For a zero-length range end equals addr, so it reads the byte before the region. Where that byte is the guard page below a vmap, the read faults: BUG: unable to handle page fault for address: ffffd16fbbc70fff #PF: supervisor read access in kernel mode RIP: 0010:drm_clflush_virt_range+0x3c/0x70 Reproduced through amdxdna's SYNC_BO ioctl, which passed a caller-supplied length straight through, so any process able to open that render node oopsed the kernel. clflush_cache_range_opt(), which this mirrors, already answers an empty range with "if (p >= vend) return", and has no trailing flush to make the case special. Do the same here, above the CONFIG_X86 test so an empty range stops calling wbinvd_on_all_cpus() on a CPU without CLFLUSH as well. The other callers are safe today by their own construction rather than by anything this helper does: of the 54 in the tree, 33 pass a compile-time constant, and of the rest only i915's phys pread/pwrite pair takes a length from userspace, which i915_gem_pread_ioctl() and i915_gem_pwrite_ioctl() reject at zero before it gets there. Signed-off-by: Taimuraz Kaitmazov <[email protected]> --- drivers/gpu/drm/drm_cache.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index ea1d2d5d2c66..86abee80e5fe 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -156,6 +156,9 @@ EXPORT_SYMBOL(drm_clflush_sg); void drm_clflush_virt_range(void *addr, unsigned long length) { + if (!length) + return; + #if defined(CONFIG_X86) if (static_cpu_has(X86_FEATURE_CLFLUSH)) { const int size = boot_cpu_data.x86_clflush_size; -- 2.55.0